MIDI to SN76489 to chip music, part 3: putting it all together

Mathieu Favréaux · March 2, 2023

This article is part 3 (see part 1, part 1-B, part 2) in a series were we try to build a MIDI instrument from a bunch of SN76489s, which is the sound chip used in the Sega Game Gear, the BBC Micro, the Neo Geo Pocket and quite a few others.

It is time to make our instrument a bit more permanent than letting it sit on a breadboard. Moreover, I want to max out the Arduino’s pins and connect it to 4 chips together.

The latter is rather trivial to do: the next 3 chips can share most of the Arduino’s output pins already used for the first one. The only pin that must be separately controlled is CE (Chip Enable): by pulling only one to true at a time, we can make sure only one chip listens to its input at any given time. Alternatively, we can also pull them all to true to send the same command to all 4 chips in one go, for instance to quickly turn them off.

I did a layout on paper which has since been lost to time, dusted off my cheapo soldering iron and went on for a long and quiet evening:

4 chips on a protoboard with an Arduino
4 chips on a protoboard with an Arduino
Nightmarish soldering
Nightmarish soldering

Please disregard the sub-optimal soldering job I did there. Note I used 30 AWG (0.25 mm) wire to solder the common data pins, otherwise I don’t see how I could have crammed it all to the same small protoboard. I opted for regular wire for the rest: first, to make it easier to distinguish what is going on; second, so there isn’t too much resistance for the Vcc and ground; finally and most importantly, because the thin wires are very easy to break.

Designing the mixing circuit

Now that we have 4 chips we have 4 outputs, and we need a way to mix them together. Since the signal is a variation of voltage, what we need is effectively a voltage adder.

The simplest circuit we could use is a passive resistor network, where the output voltage VoV_o is composed of equal proportions of the input voltages VixV_{ix}. For N inputs, all connected to the same resistance value RiR_i, we have:

Vo=Vi1RiNRi=Vi1NV_o = { V_{i1} R_i \over {N R_i} } = { V_{i1} \over {N} }

This works well enough for testing purposes, however I see two issues:

  1. Obviously, the voltage of each input to our mixing circuit is divided by the number of inputs, so this will require more amplification on the output which will generate unnecessary noise.
  2. This provides the same impedance on the input & output side. My crude understanding here is that we want stages to be high-enough input impedance (so as not to require too much power from the previous stage, in our case the TI chips) and low output impedance (so we can drive lowish impedance loads if necessary).

The solution I settled on is, again, certainly very obvious to anyone with any knowledge of electronics - I used an active mixing circuit based on operational amplifiers.

In theory it looks like this:

Schematic of a voltage adder
Schematic of a voltage adder

I’m not going to go over the usage of an op-amp here, because there are many resources on the subject. The important points here are:

  • The op-amp inputs sink virtually no current.
  • The op-amp will keep both of its inputs at the same voltage, as long as possible, by varying the voltage on its output.
  • This makes our inverting input a virtual ground (albeit one that sits at 2.5V, because I don’t have a negative rail so I want my signal to oscillate around mid-voltage, not 0V). Because of this:
    • The resistor network to the left does not act as a voltage divider anymore.
    • On the other hand, there is a voltage divider between each input and the resistor across the op-amp, and since both RiRi and R3R3 are identical, V1=ViV_1 = -V_i (again, not really, it’s actually mirrored around 2.5V, stay with me here). Note we could vary the resistor values to multiply the voltage by a different factor than 1.

On the impedance side of things1, I think we have an input impedance of Rin=R1R_{in} = R_1 and and an output Rout=Ropout=125ΩR_{out} = R_{op-out} = 125\Omega2.

Building the circuit

Now that we have our circuit in theory, we can start testing it on the breadboard.

A bit about tooling

When I started experimenting a bit on the breadboard, I realized how absolutely necessary it is to be able to measure things up, otherwise you’re just shooting in the dark. As a complete beginner I lacked all basic equipment: all I had was a multimeter.

Still I couldn’t justify to invest too much at this stage, so I bought an EspoTek board:

The EspoTek Labrador: a small all-in-one lab
The EspoTek Labrador: a small all-in-one lab

We already used it in back part 1-B of this series to do various measurements. It provides a variable voltage source, a signal generator and a digital oscilloscope all in one single board. Of course, due to its accessible price, it comes with significant compromises:

  • The voltage source cannot source a lot of current — still, it was enough for my needs.
  • The oscilloscope’s measured frequency ceiling is the in hundreds of Khz — again, enough for measuring sound frequencies.
  • The voltage resolution is quite poor, even if you can effectively double it up by cheating a little bit. I think this is the most problematic item on the list, and one that will probably justify going with more expensive equipment in the future.

Noise, noise and more noise

During testing, I realized how much noise there was on my chip’s outputs. It was so loud I was afraid it was going to make the whole thing unusable for actual recordings. Unfortunately, looking at the signal didn’t really make obvious what the frequency was, nor did poking around reveal the source.

So I tried to make a filter to block it out: I tried simple RC filters and made multiple unfruitful attempts. Then I started trying semi-random things, and of course nothing worked until magically, putting a small cap on the op-amp’s feedback significantly reduced the noise. Hurray! Not the most formal approach, but hey it worked.

Still, it’s not all gone. Connecting that thing to my desktop results in a different, but again very present noise. For this reason, I’m quite sure the source of the noise was and still is the power supply: the chips are getting their juice from the Arduino, which is itself powered from USB… And if you look closely (not), you may notice a subtle bit of hot glue. What?

Well, the micro USB connector on these Arduino clone boards is absolute garbage, and despite my carefulness, broke loose after about 3 manipulations. What you see is my heavy-handed attempt at securing the even worse repair job I did by soldering a USB cable’s wire directly to the surface-mounted component next to the connector. However, in my desperate surgery, I had to solder after the component - I believe I may have bypassed some crucial filtering there… I could always replace the Arduino, but hey, where’s the fun in that.

In the meantime, any proper recording from this finished instrument will have to be made from my laptop where the USB bus is very quiet to get a nice and quiet recording.

Keeping options open

Now let’s skip the various other digressions that I went through3, and jump straight to the end. This is what the final circuit looks like:

The mixer's schematic
The mixer's schematic

Note there are 2 outputs, and more than 4 inputs in total. The reason for this is that I wanted to keep a bit of adaptability: I have an external sound card that can capture two inputs, so maybe I’ll apply different filters to different voices in the DAW. But I’m not sure which voice I want to send to either output: do I want 1 chip optimized for bass sounds and the rest flat? Do I want two chips with reverb and two without? Do I want simple left / right channels? With the configuration above, I can do 4/0, 3/1 or 2/2, so I’ve got all the options covered.

Here is what it looks like now:

The mixer soldered on a protoboard
The mixer soldered on a protoboard

Putting it all in a box

Nothing fancy here — I grabbed a cheapo plastic electrical box, a few spacers, some black paint and forgot that varnish was even a thing. I drilled a few holes and voilà:

The final box open
The final box open
The final box closed
The final box closed

I don’t care, I absolutely love it. Beauty is in the eye of the beholder.

… OK but now what? We’re done?

The quest for color

Oh no we aren’t, because now we can sorta make chip music with it! And I’m really keen on experimenting with what sort of sounds we can get out of this thing. That also means improving the software in the Arduino following what we need.

I’ve said it before, I have no illusion about my composing skills. Besides, I want to focus on testing and playing with the instrument, and the frustration of (failing at) trying to compose a track would just get in the way.

For this reason, I started working on covering tracks I loved (or should we call that “porting”?), and I had to implement the following:

Fast arpeggios

This is the definitive signature sound of chip music: instead of playing chords, which require many simultaneous voices, we play the chord’s notes sequentially, on a single voice, very fast. This provides harmony at no cost.

They sound like this:

An example of fast arpeggios.

And I have found them sometimes used to provide some rythmic background as well:

Fast arpeggios as rythmic element.

I didn’t have to do anything to implement arpeggios as Bitwig supports them already (and keeps them correctly in tempo).

The arpeggiator in Bitwig
The arpeggiator in Bitwig

Vibrato

Vibrato is a small variation in the note’s pitch, like on a violin. This is a cheap way to bring expression. I sneaked an example in the previous’ article:

An example of vibrato.

And it’s easy enough to implement: just vary the channel frequency of a small percentage towards the next or previous note. We control this variation with a dedicated MIDI channel.

Careful readers will remember that we have little precision on high notes: the vibrato won’t work well (or at all) there.

Tremolo

On the other hand, we can vary the channel’s volume to bring a similar type of expression. Similar implementation, and it sounds like this:

An example of tremolo.

Interestingly, I found that introducing a fast tremolo also provided some texture to the voice, almost like distortion, which I quite liked in certain situations:

An example of fast tremolo bringing distortion.

Portamento

Finally, the portamento is a glissando from one note to another. It’s generally triggered in MIDI by starting the next note prior to releasing the previous one (similarly for legato), and the glissando speed is controlled by a separate MIDI channel.

An example of portamento.

Putting it all together

Here is a typical screen of Bitwig:

Typical screen in Bitwig with all 8 voices used
Typical screen in Bitwig with all 8 voices used

With 4 chips, I have quite a few voices at my disposal. In my typical setup, I ended up mirroring voices on the left & right channels, allowing for some stereo separation, that I mixed it a bit more in the center in Bitwig so it’s not 100% left or 100% right. On each side, I get:

  • 1 polyphonic channel with up to 2 voices (so I can play 2 notes at the same time).
  • 2 monophonic channel2 which I can use for simple voices or arpeggios.
  • 1 polyphonic drum channel with up to 2 voices, and each drum voice also eats up 1 regular oscillator voice as we’ve seen before.

That’s a total of 8 oscillator voices & 4 drums simultaneously. It is really cheating at this point, compared to what these chips are originally intended for. But it’s plenty of fun!

Conclusion

So far I ported 3 tracks, and it was a really interesting exercise. You can find them on Bandcamp or in the embedded player below. Maybe I’ll port other tracks if I feel like it, but no constraints.

And with this, our little series ends! We dabbed in electronics, theory and practice, and also into chip music & DAWs! It was quite a fun project, that lasted for more than a year.

  1. Rin and Rout of the Inverting Amplifier — Jim Stiles from the University of Kansas. 

  2. TL072 datasheet lists the open-loop output impedance page 18 — I’m not 100% sure this is exactly what we would measure in-situ since we are sourcing current. 

  3. Such as playing with diodes to make the signal clip like a guitar pedal - very fun, A+++ would do again. 

Twitter, Facebook