Saturday, January 26, 2008

Soft MIDI Pokey

The Pokey IC: Overview
The Pokey chip is a forty pin IC whose main functions include read keys and analog sensors, outputting serial data and generating audio. The audio section of the chip includes four oscillators which can operate in a number of modes which make it quite versatile (and it sounds great!)

Information on how to control the Pokey chip (ie. registers and functions) comes from a document by Bryan Edewaard. This project would obviously not be possible without fantastic work such as this!

The way that data is read or written to the chip is by the control of four address lines (A0 to A3, that control the register being written to or read from) and eight data lines (D0 to D7, that control the information that is sent to or retrieved from the chip).

Since we are interested in sound generation, let's focus on the relevant registers.

Registers 00 to 08 are responsible for all sounds that this chip can produce.

Registers 00 (0000), 02 (0010), 04 (0100) and 06 (0110) control the frequency of the four voices. The value is between 0 and 255 (00000000 and 11111111 in binary, where each bit represents one of the eight data lines).

Registers 01 (0001), 03 (0011), 05 (0101) and 07 (0111) control the timbral and volume aspects of each voice. The three most significant bits (xxx00000) control the timbre (whether the tone is a 'pure' square wave-type sound or has distortion of some sort).Bit four (000x0000) is used in digital to analog conversion, and should not be set to high for audio generation normally. Bits 0 to 3 (0000xxxx) set the volume of that voice.

Register 08 (1000) sets 'global' parameters that effect the way in which audio is generated. Here is the overview of each bit:

• Bit 7: Changes the type of noise
• Bit 6: Use the undivided clock to time voice 1
• Bit 5: Use the undivided clock to time voice 3
• Bit 4: Combine the frequency registers for voices 1 and 2, creating a single 16-bit oscillator
• Bit 3: Combine the frequency registers for voices 3 and 4, creating a single 16-bit oscillator
• Bit 2: Voice 1 is in high pass mode, set frequency with voice 2
• Bit 1: Voice 3 is in high pass mode, set frequency with voice 4
• Bit 0: Use a divide-by-120 clock or a divide-by-28 clock

So, in order to write data to the Pokey, at least 12 separate digital output lines are required in a circuit.


Updated Circuit and Code
I have been improving the method of controlling the Pokey chip. The improvements i have made are based almost completely on a schematic by Michael Hill. Without people like him, such projects would not be possible also!

I have adapted the schematic to suite the Arduino board. The code has also been re-written to accommodate for the extra chips. The Max/MSP patch now incorporates real-time MIDI controller (hence the title of this post -- the MIDI control is done in the host computer software, not embedded hardware).

The new circuit (thanks to Michael Hill for posting his design) employs two octal flip flops. In my case, i have used a pair of 74hc374 because this IC was readily available. The chip is named "octal edge triggered d-type flip flops with three state outputs". Basically, it consists of eight separate flip flop functions. A flip flop is an electronic device or circuit that changes its binary (ie. either high or low) output (Q) to match the state of the input (D) only when it is triggered by a clock signal (C). We can say that a flip flop stores a single bit of memory, because unless the flip flop is actually triggered, the output will remain the same regardless of the input. When the flip flop is triggered, the output will be updated to reflect the input.

The 374 IC is "edge triggered". Thus, the output (Q) is only updated to match the input state (D) when the clock signal (C) makes a transition from low to high. It follows that if the clock signal is either high or low, but not moving from a low to a high state, the output (Q) will not change (and will stay the same as when the output was last triggered). It should be noted that ll eight flip flops on the 374 share the same clock signal (that is, they all update at the same time).

The circuit makes use of this function by first clocking out the four bits required to set an address for a register of the Pokey to one of the 74hc374s and then clocking out the eight bits of data to the second 74hc374. The two 74hc374 have separate clocks. Then, the Pokey's chip select line is enabled and thus the data is written to the Pokey.

The basic principle of writing data to the chip is as follows:
• For each change, two bytes are sent from the host computer to the Arduino at a baud rate of 57600.
• The first byte that is sent is a number between 0 and 8, signifying the register to write data to.
• The second byte that sent is a number between 0 and 255, signifying the data to write into the previously selected register.
• First, the eight data lines are set the register byte. Then, the '374 that is connected to the register lines is pulsed so that the outputs of the IC set the correct register at the Pokey. However, because the other '374 is not strobed, the data lines are left unchanged.
• Next, the eight data lines are set to the data byte.
• The twelve LED's show the current register and data bytes. Then, the '374 that is connected to the data lines is pulsed so that the outputs of the IC set the correct data value at the Pokey.
• Finally, the chip select line actually writes allows the Pokey to read the data that has been sent to it.


MIDI Mapping
The Pokey chip is controlled by MIDI via a Max/MSP patch in the following way:
• Pitch is scaled from 0 to 127 to 0 to 255 and is mapped to frequency for channels 1 to 4
• MIDI CC#2 is scaled from 0 to 127 to 0 to 15 and is mapped to volume for channels 1 to 4
• MIDI CC#1 is scaled from 0 to 127 to 0 7 and is mapped to tone for channels 1 to 4
• MIDI CC#27 is scaled from 0 to 127 to a toggled state (on or off) for distortion type
• MIDI CC#26 is scaled from 0 to 127 to a toggled state (on or off) for undiv. clock voice 1
• MIDI CC#25 is scaled from 0 to 127 to a toggled state (on or off) for undiv. clock voice 3
• MIDI CC#24 is scaled from 0 to 127 to a toggled state (on or off) for 16 bit mode voices 1 and 2
• MIDI CC#23 is scaled from 0 to 127 to a toggled state (on or off) for 16 bit mode voices 3 and 4
• MIDI CC#22 is scaled from 0 to 127 to a toggled state (on or off) for high pass mode voice 1
• MIDI CC#21 is scaled from 0 to 127 to a toggled state (on or off) for high pass mode voice 3
• MIDI CC#20 is scaled from 0 to 127 to a toggled state (on or off) for clock div. 120 or div. 28



Schematic


Breadboard



Code

/*

Soft MIDI Controlled Pokey Chip

by Sebastian Tomczak

26 January 2007


*/


// Pokey Pins

int pokeyCS0 = 12; // chip select


// 74HC374 Pins

int addressClock = 10;

int dataClock = 11;

// d0 to d7 are on pins 2 - 9

// a0 to a3 are on pins 2 - 5


int strobe_wait = 100;


byte registerP;

byte dataP;


void writePortByte(byte PortByte) {

PORTD = PortByte << 2;

PORTB = PortByte >> 6 | B00010000; // OR pin 12 high because of CS0 inverse logic

}


void setup() {

Serial.begin(57600);

DDRD = DDRD | B11111110;

DDRB = DDRB | B00111111;

digitalWrite(pokeyCS0, HIGH); // CS0 has inverse logic (active low)

digitalWrite(addressClock, LOW);

digitalWrite(dataClock, LOW);

}


void loop() {

if(Serial.available() > 1) {

registerP = Serial.read();

dataP = Serial.read();



writePortByte(registerP);

digitalWrite(addressClock, HIGH);

delayMicroseconds(strobe_wait);



writePortByte(dataP);

digitalWrite(dataClock, HIGH);

delayMicroseconds(strobe_wait);



digitalWrite(pokeyCS0, LOW);

delayMicroseconds(strobe_wait);



digitalWrite(pokeyCS0, HIGH);

digitalWrite(dataClock, LOW);

digitalWrite(addressClock, LOW);

}

}

11 comments:

rob said...

Excellent information, thanks!!! Can you an electronics beginner (me) why the flip-flops are in there. It seems like you could do it without just the arduino pins? It does make the circuit and the code simpler and more logical, and I know the parallel port circuit that you drew from already had them in there. Is there any other reason? Thanks again!
rahji

Sebastian Tomczak said...

Heya Rahji,
You must read quickly! I only just posted this.

Well i was having some timing difficulties going straight from the Arduino pins. I think this has to do with the fact that even if you use a PORTD command followed by a PORTB command, you are still setting the eight pins in two steps. So, if i was going quickly and writing data from one register to another, then there was sometimes in certain circumstances data which was written to the wrong register -- because the PORTB command would have set the register and the PORTD command would have set the data. That's a guess though, because i couldn't track down the exact problem. But these issues are fixed with the addition of the two oct flip flops.

cheerio,

sebastian

rob said...

i'm subscribed to the feed so i'm always right on top of your posts. :) i really just started learning about electronics, microcontrollers and such during this past year but something like this just makes sense to me in a logical way. for the same reason that you'd modularize a program in the software-world. i like it for that reason and of course a reason like it didn't work right when just using the pins is just as good a reason.

Sebastian Tomczak said...

yeah for sure. modularity is a beautiful feature of the 7400 and 4000 and similar families of ICs.

i have read some of your wordpress stuff -- excellent material! like the circuit bent things. nice.

Anonymous said...

this proyect was finished? , im waiting for updates for a long time, im learning a lot of things thanks to you

Anonymous said...

hola sebastian ,i am begining with a pokey proyect and i am questioning something, the audio output comes from
pin 17, and another wich another pin to conect to an audio jack? i am a 17 years old girl and i am interested on chiptune ,thank and respect.

sara

Sebastian Tomczak said...

@ Sara: Hi there, the yes pin 17 is the signal but you will also need to connect the jack to ground, so simply grab a ground point from the board.

Anonymous said...

sara again, thanks for answer ! are you using a 74ls14? i dont know how to conect between 100 k pot and pokey,i dont understand de schematic, im so amateur :S



sara

Sebastian Tomczak said...

For the 74ls14:
- connect pin 14 to 5V, pin 7 to gnd
- connect pin 1 to ground via a small capacitor
- connect pin 1 to an outside leg of the 100k pot
- connect pin 2 to the middle leg of the 100k pot
- connect pin 2 to the clock input pin on the pokey (pin 7)

Anonymous said...

hi sebastian

hi sebastian, something goes wrong with my pokey,everything is connected fine and pokey can´t play, I can hear only clicks, the error can be in my max patch everything is included (sto.8b1b) live communicates fine with max , the code is loaded in Arduino, everything is done as the post says, but it does not work, just clicks, you can post the patch max? will be my last attempt to sound the pokey.
maybe you can send more extra info at sara.lantano@gmail.com



sara

Unknown said...

I love the this, will you be updating anytime soon to include a midi in so that this can all be controlled without a computer running MSX?