Ataru: Building a Modular Z80 Computer
In the beginning… there was dust.
Apes. Magnificent, wretched apes. Screaming at bones. At each other. At the void itself. Then, it appears. Silent. Black. Incomprehensible. A rectangle so perfect it could only be wrong. It does not speak. It does not need to. The apes touch it. And something… ignites.
A bone rises. Falls. Civilisation happens.
Millennia pass in a single cut.
The infinite dark. One man, one machine. The machine is smiling, though it has no face. And, yet, somehow, it is smiling.
“Good morning, Dave.”
Ataru didn’t actually say that, of course. He’s a Z80, and I’m not a miracle worker. But this, dear reader, is the story of how we moved from a clicking buzzer and a stuttering serial port to a six-channel polyphonic soundstage.
The 10 MHz Hubris
I will tell you something. At a certain point in any long saga, I begin to feel like Homer. Not because of the grandeur, but because of the repetition. The Homeric bard had his expanded formulae; stock epithets returning like old friends. I have mine. The warning unheeded. The pride before the fall. The journey that was never really about the destination – and a bloody clock that doesn’t match its intended purpose because it won’t divide cleanly.
But hold on – we’re in media res. Let me take you back to the start.
In my last post, I left you with a question: sound or video? It didn’t take me long to decide. The display adapter required components I didn’t yet own, and in true pipelined fashion, I couldn’t stall development while waiting for the fetch to complete. So, I ordered the silicon (ACT-family logic and some fast RAM, if you’re wondering), and decided to build Ataru a sound card in the interim.
At first glance, the task looked surprisingly simple – the universal tell of disaster to come. I wanted to build the soundcard around the Texas Instruments SN76489. If you aren’t familiar, this is the Programmable Sound Generator (PSG) that voiced the Sega Master System and the BBC Micro. It provides what TI called, ahem, “Digital Complex Sound Generation”: three square-wave tone generators and one noise channel.
As expected, the PSG requires a clock pulse to operate; as not expected, the typical clock frequency used is approximately 3.579545MHz. It felt like reliving the CTC/SIO and 16550 clock nightmare all over again. I tried to brace myself by purchasing an assortment of crystal oscillators, but 3.58MHz is a particularly stubborn frequency – and certainly it isn’t a clean factor of 10. Not in this universe, at least.
By now, I knew the drill: find the next best frequency and build a Pierce oscillator around it. By a stroke of good fortune, the maximum clock frequency supported by the PSG is 4Mhz, which happened to be one of the flavours in my assorted box. I verified the output on my oscilloscope and the circuit was good to go.
Fast and the Furious
I connected the breadboard to the backplane using the harness I’d built for the serial module and set to work on address decoding. In my infinite wisdom, I decided that while the UART sits at port $80, the PSG would inhabit port $40, a feat accomplished with the swap of two jumper wires.
I mounted the PSG, wired the data and control lines, and prepared for preliminary testing. By “testing” I mean I glossed over the data sheet while the rational part of my brain screamed that it wouldn’t work unless I actually followed the specification. Heh. When has that ever stopped me from acquiescing to my own madness?
I wrote a snippet to initialise the PSG and play a 440 Hz tone on the first channel. I built it loaded it, and… silence. Crickets is what I’d like to say, but at least crickets make a sound. The oscilloscope flatlined; for a second, I thought I was looking at my bank account. History repeats itself. It was time for some actual reading.
It turns out that this SN76489 is a bit of a slowpoke. Literally. I know it’s a vintage chip, but a write takes roughly 32 cycles to complete. The CPU physically cannot perform another write until the previous one has settled. The PSG has a READY pin designed to tell the outside world when it’s finished ruminating on a byte and is ready to accept a new one.
On a Z80, you can connect this to the /WAIT line through a contraption of logic circuits and octal transceivers, to force the CPU to pause. However, at 10MHz, this means the CPU is idling for upwards of 80 cycles per write. This is an 8-bit computer, not a government department, and that kind of attitude makes it feel like the boy is just aggressively vibing through the apocalypse.
Fire and forget
The issue might seem easily solvable: just have the CPU do something else between writes to the PSG, right? Wrong.
If the CPU moves on to the next instruction, the data on the bus – that very byte the PSG is try to digest – vanishes or changes. It’s a digital “now you see it, now you don’t” prank that leaves the sound chip confused and silent.
To solve this, the internal committee was called into an emergency session to define a new communication protocol. The minutes of the meeting follow:
- Request: The Z80 issues a write to port $40.
- Validation: The address decoder validates the request (ADDR = $40, /IORQ = low, /WR = low), asserting the /LATCH_EN signal.
- Hand-off: Instead of hitting the PSG directly, the data bus (D0–D7) is latched into an 8-bit register (an octal D-type flip-flop). The register captures and holds these bits the moment /LATCH_EN is asserted.
- Persistence: This is where the rabbit comes out the hat: the PSG is not connected to the Z80’s data bus at all. It is connected to the output of that 8-bit register.
- Perusal: Once the write initiated, the PSG pulled its READY line low to signal it is busy. But because the data is now frozen in the register, the PSG can take all the time it needs to read at its own pace.
Meanwhile, the Z80 is already doing other things, completely unburdened by the PSG’s slow metabolism. Essentially, we moved from a wait-state nightmare to a fire-and-forget architecture.
Mirror Mirror on the Wall
Who’s the dumbest of them all? Why doesn’t this thing work at all?
Famed is a good Internet connection, Majesty. But hold – an illiterate dumbass I see. Alas, he has honed YOLO to perfection.
I would like to say something in my defence, but I am lost for words. Let me continue with the story, dear reader.
Impulses reigned in, I genuinely thought I’d read the datasheet in enough detail to have nailed the logic. I actually had, but as it turns out, Texas Instruments (god bless their hearts) made a move that can only be described as “aggressively non-standard.” They designed the SN76489 to use big-endian pin numbering. To the PSG, D0 is the most significant bit. To the Z80, D0 is the least. By wiring them pin-for-pin, I had effectively mirrored every command.
Now, I’ll take a moment to reflect on the issue.
I should tell you that I approached this in the sensible way, by rewiring the data bus properly. But I didn’t. Not with these short, pudgy fingers of mine.

They say fact is stranger than fiction, but laziness is more reliable than both. What I actually ended up doing was adding a flag to my code to flip endianness on demand. I wrote a bit-reversal routine, wrapped the I/O calls, and let the software do the heavy lifting that my fingers refused to do.
I built the code. I uploaded it.
Ba-Dum.
Channel 1 was suddenly outputting something verging on the meaningful on the oscilloscope. I quickly bodged together a small amplification circuit around an LM386 and wired a tiny speaker to it.
The poet Sappho famously said that the sweetest sound is the voice of the one you love.
No.
The sweetest sound is a PSG playing A4 at glorious 440 Hz on a 3W speaker that was technically connected but only because I was physically pressing the wire against the terminal with my thumb.

Sound Test Suite
I kept adding features to the simple sound test program until it evolved into a fully fledged test suite for the SN76489. Eventually, I couldn’t resist the urge to build a music player. Here’s Ataru’s rendition of Korobeiniki, better known as the the Tetris Theme, running on the original breadboard prototype.
As per tradition, once a design is “good enough,” it is turned into a PCB to clear the breadboards and desktop for the next disaster. With the sound module, I felt somewhat adventurous; I doubled the stakes and added a second PSG to the design, addressable at port $41. This effectively gives us three square-wave channels and a noise channel per stereo side.
I also took the opportunity to give the project some visual identity, adding a custom logo for Ataru to the silkscreen, which you can admire in the image below.

The PCBs arrived without issue, looking professional – deceptively so. I soldered the components, powered it up, and was met with nothing. Yeah, I’ve grown to accept this as normal.
The culprit, once again, was the clock. The Pierce oscillator was stuck pulsing at a pathetic 47kHz. After some sleuthing, I discovered that momentarily shorting the crystal’s legs would kickstart the oscillation, which suggested a biasing issue. I fought dejection and turned this into a learning experience; I think I uttered swearword combinations that hadn’t been heard since the dawn of human speech.
I also learned the technique of “tacking,” where you solder the legs of a component to the PCB pads without going through the holes or removing existing parts. I combined probing and tacking to seek the answer, and the universe finally acquiesced with a small act of grace. To cut a long story short, changing the feedback resistor from 1M to 330k provided the necessary kick. The oscillator sprang to life, the 4MHz clock stabilised and the lambs started bleating.
With the hardware finally finalised, I spent the next few days rearranging tunes I found on the Internet for the dual-PSG setup. Ode to Joy, the Super Mario theme, the Imperial March, and – obviously – Doom’s E1M1.
Epilogue
Well, who would have thought we’d make it this far? Not me, certainly. I’ve been considering releasing the schematics, PCB designs, and code for Ataru, but I fear for humanity. And trust me, it’s nothing to do with being ashamed of how bad the work is. After releasing the source code to Blaze, which is a trainwreck in the making, I can take anything in stride.
I can’t think of anything else to say, really. The monolith appeared, the apes learned something, and Ataru can now play the Tetris theme. Make of that what you will.
Video next. See you soon. Hopefully.

Leave a Reply