Tuesday, February 19, 2008

Cool, it's a MIDI-controlled sega master system sound chip!

I grew up with the Sega Master System, and 8 bit video game console. Apparently, it was actually quite successful here in Australia. The sounds of the system and quite a bit of the music is something that has stayed with me for a while. There is something about nicely detuned square waves that i just can't go past.

In fact, when i was in third year at uni i wrote a paper on the music of the Shinobi series of games (specifically from the 8 and 16 bit era). A large chunk was dedicated to the way in which the music of Shinobi and Alex Kidd in Shinobi World (AKSW) was ported to the Master System, including a discussion of the SN76489 sound chip and a transcription of the entire AKSW soundtrack.
So i have been working on controlling an SN76489 sound chip using MIDI data from a host computer. Actually, i just really started today and things have been progressing quite nicely. Currently, i am using an Arduino board which mates with a soldered protoype circuit board along its digital I/O. The Arduino connects with the host computer using a USB cable. I hope to migrate to a more MIDI-hardware solution soon (ie, no USB cable but MIDI input instead).

Controlling the Arduino on the host computer side is a software layer (a Max patch in this case) that takes MIDI data and generates suitable bytes to send to the SN76489.

The SN76489
The SN76489 has three square wave oscillators and a pseudo-random noise generator. The oscillators have ten bits of frequency control. All voices have four bits of volume control. The noise generator is a little limited by the fact that it is either clock by only one of two values or the current value of the frequency data for the third oscillator voice. However, by writing noise shaping bytes at appropriate times to change what is clocking the noise voice, some variety of percussion and sound effects can be achieved.

The sound chip is pretty easy to work with. A byte will always take one of four forms: Register latch and frequency data, frequency data, volume data or noise shape control. Data is written to the chip and the register by first loading eight bits of data in parallel onto the eight data lines, followed by bringing the chip enable (!CE) line low, followed by bringing the write enable (!WE) line low. The !WE and !CE are then held high (inactive).

When i was trying out writing data to the chip, it seemed as if the !CE and !WE had to complete a write cycle before the next lot of data could be accepted. In other words, both pins had to be pulsed and controlled by the microcontroller board in addition to the eight data lines. I was expecting that i could only pulse one of these two control lines and get away with leaving the other one active low, but hey...

An RC oscillator is used as the master clock. This has been constructed from a 74hc14 inverter with component values of 22kΩ and 27pF. These are simply values that i had lying around. I have no idea what frequency this generates.

Host Computer Software
The host computer software takes MIDI data and transforms this data into byte that are then written directly to the SN76489. It handles the following tasks:
• Data formatting
• Envelope control and generation
• Pitch to frequency data look up tables
• Pitch value to noise shaping mapping
• Noise channel volume scaling

The envelope generator is an eight step, four bit generator. Enough to sort of simulate many classic Master System sounds and melodies (hopefully).

The look up tables used in pitch to frequency data conversion were gathered manually. This means by ear. So there are surely some inaccuracies. However, it all sounds okay, for the time being. In this state, the tone generators have a range from MIDI note A#0 to C6, a respectable range considering there are only ten bits for frequency control. At any rate, all Master System music seems to fit within this range.

The look up table shown below is only true when an RC oscillator is used that is constructed from a 74hc14 inverter with component values of 22kΩ and 27pF. Otherwise, the pitches will not retain their identity but the musical intervals will remain intact to a large extent.

In the table below, the left value is the MIDI note number and the right value is the frequency data value that is fed into the SN76489.

34, 985; 35, 931; 36, 880; 37, 830; 38, 783; 39, 741; 40, 698; 41, 659; 42, 623; 43, 588; 44, 555; 45, 523; 46, 495; 47, 468; 48, 441; 49, 415; 50, 392; 51, 370; 52, 350; 53, 330; 54, 311; 55, 294; 56, 277; 57, 262; 58, 247; 59, 233; 60, 220; 61, 208; 62, 196; 63, 185; 64, 175; 65, 165; 66, 156; 67, 147; 68, 139; 69, 131; 71, 117; 70, 124; 72, 110; 73, 104; 74, 98; 75, 92; 76, 87; 77, 82; 78, 78; 79, 73; 80, 69; 81, 65; 82, 61; 83, 58; 84, 55;85, 52; 86, 49; 87, 46; 88, 43; 89, 41; 90, 39; 91, 37; 92, 35; 93, 33; 94, 31; 95, 29; 97, 26; 96, 27;

Audio Examples
Of course, the point for me in all of this is to make some mu! But, i thought i would just start off with posting some classic Sega music as reproduced by the chip.

At least the tone generators sound reasonably authentic thus far. The biggest problem is the mapping of the noise channel data from a transcription or a MIDI file directly to the SN76489 without having to reprogram the MIDI sequence. This is why the percussion parts are completely incorrect in terms of what sounds the noise channel is playing.

Here are some examples, played on a real SN76489 as controlled from Ableton Live.

Alex Kidd in Shinobi World, Introduction Theme
Alex Kidd in Shinobi World, Level 1 Theme
Alex Kidd in Shinobi World, Level 4 Theme

Demo Video


Please note that JP1 represents the digital IO pins on the Arduino board and the pin numbering is offset by one (eg. in the schematic, RX is pin 1 but on the Arduino board, RX is pin 0).

Arduino Code
byte data;
int WE = 10;
int CE = 11;

void setup() {
DDRD = DDRD | B11111100;
DDRB = DDRB | B00111111;
pinMode(WE, OUTPUT);
digitalWrite(WE, HIGH);
pinMode(CE, OUTPUT);
digitalWrite(CE, HIGH);

void loop() {
if(Serial.available() > 0) {
data = Serial.read();
PORTD = data << 2;
PORTB = data >> 6;
digitalWrite(CE, LOW);
digitalWrite(WE, LOW);
digitalWrite(CE, HIGH);
digitalWrite(WE, HIGH);

Max/MSP Patch
URL: http://milkcrate.com.au/_other/downloads/max_patches/sn76489.zip

In order to use the Max/MSP patch without the full Max/MSP environment, you will need to download a runtime for your operating system. Please go to http://cycling74.com/ for the download.

The SN76489 can be purchased from Unicorn Electronics.


Maxim said...

The noise is different because the SN76489 part you're using has a different noise generator configuration from the custom variant Sega put in the Master System et al. It seems they tuned it for more percussive noise rather than the staticy noise you're hearing.

Sebastian Tomczak said...

I disagree. Although you are correct, of course, that they used a different length reg to produce noise with than the original SN76, I feel that the main reason for the difference in sound is the incomparability of the MIDI data with which the drum track was programmed with being mapped to the SN76. Also, i have not yet added an amplitude envelope for the noise channel; this would also make a huge difference in terms of being able to generate percussive sounds.

Sebastian Tomczak said...

However, the length of the register would still make a large difference in the noise.

I just really need to add an envelope ;-)

MrX said...


How can i get in contact with you regarding this?

Thank You

Sebastian Tomczak said...

Hi there,
You are most welcome to email me at seb.tomczak (at) gmail.com


Sebastian Tomczak

Unknown said...

please please! hurry and make a midi cart!! oh and features for programming a set of envelopes! please!!!
I need this in my life!! oh and a gamegear version with stereo support!!

course no pressure .. :)

Unknown said...

will this work if I pull the ship from my sega master system 2... either way, this is SICK...