Project 022 - ZX Spectrum Multi I/O Interface
DISCLAIMER: This design is experimental, so if you decide to build one yourself then you are on your own, I can't be held responsible for any problems/issues/damage/injury that may occur if you decide to follow this build and make one yourself.
INTRO
The project - To design and built a Multi function I/O board for the ZX Spectrum.........
Back in the early 80's when I was a teenager I bought myself a 16k Sinclair ZX Spectrum computer, but rather than play games I spent all my time playing about with BASIC writing some wierd and wonderful programs. I also got into the actual hardware behind the Spectrum which of course is the Z80A Cpu by Zilog. At work we also used the Z80A so it was fun and easy for me to play around with the hardware building the odd interface and gleaning info from those around me more in the know of the Z80A.
Roll the clock on some 30 years and I find myself with the ZX Spectrum once again on the bench in-front of me and looking rather curiously at the edge connector at the back............hmmmm, I wonder!
A lot of my workshop projects recently have been with the Arduino and enjoying interfacing lots of analogue and digital signals, so I thought wouldn't it be nice if the Spectrum had similar analogue and digital I/O capability. So, I set to work and came up with a specification and a number of IC's I'd used previously with the Arduino and thought they might be easily ported to the ZX Spectrum. If anything a nice challenge!
- ADC - 4 analogue inputs - 12 to 18bit configurable
- DAC - 4 analogue outputs - 16bit
- 24 digital I/O
- I2C bus interface
The I2C interface is key to the design as I wanted to use the same I2C based ADC & DAC IC's that i'd used before (with the Arduino). Therefore, I'd need to find a converter IC that would allow this, i.e Spectrum data bus to I2C conversion. The following is the basic hardware behind the entire interface.
- MCP3424 ADC IC - http://ww1.microchip.com/downloads/en/DeviceDoc/22088b.pdf
- DAC8574IPW DAC - http://www.ti.com/lit/ds/slas377b/slas377b.pdf
- PCA9564 Parallel to I2C bus Controller - http://www.nxp.com/documents/data_sheet/PCA9564.pdf
- 82C55 Programmable peripheral interface - http://www.embeddedsys.com/subpages/resources/images/documents/82C55_datasheet.pdf
With the above and a few additional components the basics of the hardware design is there, and so I set to prototype a pcb, and then design a full board using Eagle PCB.
Note: This design has onlybeen tested with a 48K ZX Spectrum rubber keys model. I have not tested it at all with any 128k Spectrums so am unsure of any compatibility there.
CIRCUIT DESIGN
The following is a brief rundown of the circuit.
POWER SUPPLY:
I chose to run the interface from the unregulated DC (9 to 12vdc) rather than the Spectrum's own +5vdc regulated supply. A couple of regulators have been used supplying 3.3vdc & 5.3vdc to the circuit. U6 the PCA9464D parallel to I2C IC requires 3.3vdc (but can handle 5vdc logic I/O). Everything else runs from 5.3vdc, choosing an LM317 to generate this voltage. I chose 5.3vdc so that I could guarantee 0-5vdc on the analogue side of the DAC & ADC. The Vref for the DAC is 5.000vdc (+/- 0.1%). All IC's on the board are spec'd to run at up to 5.5vdc so no problems there.
I/O DECODING:
The first thing to do is connect to the ZX Spectrum's interface, or to be more exact the 8-bit data bus of the Z80A Cpu. This is pretty easy normally and can be done in a number of ways using just one IC for the IO address decoding, and I chose the 74LS138 1 of 8 Decoder - http://www.ti.com/lit/ds/symlink/sn74ls138.pdf
One caveat with the 74LS138 though is that it will not carry full I/O decoding of the entire Z80's address range (A0 to A15) but actually only 3, and in particular I used A1, A2 & A3 thus accessing even adresses only as I believe the ULA utilizes a load of the odd addreses). By doing this not only limits the IO addresses that can be used, but also opens up the fact that many IO addresses share the same bottom addresses and thus possible conflict. Many ZX Spectrum interface designers over the years have done exactly that in order to keep costs down given the relatively low likelyhood that Joe Bloggs will buy 2 interfaces that conflict. For the design I also chose to do it this way. All said and done, the 74LS138 gives me 8 selectable lines I could use as chip selects (CS), and in the end only 2 were required.
In saying that, it wasn't long before I started experiencing an issue during prototyping i.e. glitching on 5 of the 8 chip selects, a little unusual and I had my suspicions on the Spectrum's internal design (the ULA etc!) which isn't your normal Z80A processor board and so I added an extra gate to tie in the RD/WR lines from the Cpu rather than lying on the Z80's IORQ line. In the end, much more reliable and glitch free.
I2C:
A PCA9564 IC is a parallel to I2C bus converter IC and gives the Spectrum an inductry standard I2C interface. The primary function is to interface to the I2C enabled ADC & DAC IC's, but I have also connected the SCL & SDA bus lines to a couple of screw terminals at the back of the board. This will allow the user to extend the bus to other devices or boards.
There is one caveat with this IC though and it's not quite as straight forward in the software as it is with say the Arduino, look up the code for more info.
ADC:
A simple to implement circuit using a MCP3424 quad channel ADC. No Vref is required as it's internal to the IC, and so all I have done is add a voltage divider / low pass filter on each of the four inputs. This gives each input a range of 0 - 10vdc. Resolution is configurable in the software from 12bit, 14bit, 16bit & 18bit. The software default i've set to 16bit to match the DAC.
In real life terms at 16bit I am certainly getting 1-bit stability from an analogue input which isn't too bad considering the sheer noise that can be found on the ZX Spectrums ground plane.
DAC:
I used a DAC8574 quad channel DAC. A 5.00vdc Vref sets the FSD for the outputs, and I used a rail-to-rail (input & output) chopper op-amp on each DAC output to guarantee a stable and accurate output. Optional resistors/caps allow for scaling the output accordingly. By default they are hooked up as voltage followers. Resolution is set at 16bit.
Note: If there's area in the design/layout I would have liked to improve then that would be the DAC, since despite setting VrefLO and VrefHI accordingly I am getting some slight offsets (in order of a few mV's)! Saying that though, stability is certainly in the order of tens of micro volts (uV).
DIGITAL INPUTS / DIGITAL OUTPUTS:
The 82C55 takes care of the digital I/O. This IC interfaces direct to the Z80A's data bus and is fairly easy to setup to control the three 8-bit ports. There's much more to this IC than meets the eye, but for simplicity I've set it up as follows:
Port A = 8 x digital inputs, pulled high to +5v, active low to GND.
Port B = 8 x digital outputs via ULN2803 driver, V+ supplied externally (any voltage).
Port C = Bit 7 is reserved (CS to PCA9564), the remaining 7 bits are configured to drive 3 on-board LEDs and read 4 on-board jumper headers. Upper nibble = 4off outputs, lower nibble = 4off inputs.
VIDEO:
I did record a video blog as I had to troubleshoot an I2C problem during development. See here.
I/O TESTING / SPECIFICATIONS:
The calculated & tested spec. is as follows.
16bit Analogue Output = Range 0 - 65535, 0 - 5vdc, 0.000076vdc per bit (0.076mV or 76uV) calculated.
Voltage at DAC output: 0bits = 0.01463vdc, 32767bits = 2.51308vdc, 65535bits = 5.01020vdc
Voltage at Op-amp output: 0bits = 0.01429vdc, 32767bits = 2.51270vdc, 65535bits = 5.010028vdc
Note: Most DACs don't work down to 0.000vdc very well, this particular DAC specs a zero scale error of 5 to 20mV (I measured 14mV on my particular DAC), see datasheet for explanation.
Note: DAC tested using my uncalibrated bench 6.5digit DMM. I really need to send it away for recalibration and will revisit this once thats done.
16bit Analogue Input = Range 0 - 65535, 0 - 10vdc, 0.000152vdc per bit (0.152mV or 152uV) calculated.
Real life figures = 0.000vdc = 0bit, 2.500vdc = 7994bits, 5.000vdc = 15988bits, 7.500vdc = 23973bits, 10.000vdc = 31966bits
Note: Better absolute accuracy would be attained by using precision resistors on the input voltage divider.
Note: ADC tested using my cheap Ebay Hao Qi Xin voltage ref. (based on AD584LH, 1mV accuracy).
Digital outputs = ULN2803 spec. gives 50vdc max., 500mA per channel, on-board back-emf/clamp diodes. Datasheet here.
Digital inputs = 10k pull-up to +5.3vdc, external connection via contact to 0vdc (GND).
I2C = Bi-directional I2C communication IC standard & fast mode capable. Max. master mode freq. = 360kHz, Max. slave mode freq. = 400kHz. Can operate as master, slave, transmitter or receiver.
GOING FORWARD:
I'd like to experiment further with the external I2C bus connections and possibly try interfacing to some other I2C devices such as a graphics/alphanumeric LCD.
EAGLE PCB FILES & ZX BASIC CODE
I have made available all the design files as I don't intend to sell the PCB's long term, except maybe a limited edition run of 3 or 4. Please contact me if you are interested (fully assembled).
PCB:
Current version = V1.0
Schematic in PDF format - here.
Eagle PCB files - here.
BOM file - here (supply part numbers where applicable).
CODE:
ZX Basic (Boriel) code here. The zip includes a compiled .TAP file as well as the .BAS basic file.
The BASIC code does not run natively on a ZX Spectrum. It requires to be compiled to a .TAP (machine code) file using Boriel's ZX Basic Compiler. See http://www.boriel.com/en/software/the-zx-basic-compiler/
The code by default runs some subroutines to demonstrate how to read and write to both digital & analogue I/O, the idea being that i've provided all the base information for anyone to take the system forward for their own bespoke work.
You can purchase a fully assembled PCB from my online shop here.
PHOTOS
Here's the final version of the board (top of photo) connected to the back of a Spectranet card which is plugged into the ZX Spectrum. The Spectranet card gives the Spectrum an IP address so I could upload the TAP file to the Spectrum easily and quickly via a Lan connection. Luckily it has a full thro' connector so my board could go at the back.
You can see a test relay and external LED connected to a couple of the digital outputs.
I have several ZX Spectrums, this is my dev. machine.......;-)
A close-up of the board. It's a 2-layer Pcb, all electronic components are surface mount, the only through hole devices are the connectors and headers.
An LED at the far left signifies unregulated DC input.
The pushbutton switch is a RESET switch for the Spectrum.
The large IC is the 82C55.
There are several labelled test pads on the board for quick access to the power supply voltages (+unreg, +5.3, +3.3) and the 5.000v Vref for the DAC.
Further view of the board in operation and connected to the back of my Spectranet card.
You can see along the top connectors my test cables etc for the various analogue inputs/outputs.
For those playing along at home, I used my reflow oven to solder up all the SMD parts, but strictly speaking it could all be done by hand with just the DAC8574 being a bit tricky due to it's TSSOP fine pitch (0.65mm).
The pcb, underside view. Most of it is the 0vdc groundplane.
You can also see various mounting holes which, if required, can be used to steady the board in a fixed installation.
Major components & I/O summary.
I designed the board to be the same width of the Spectranet card, just to keep things looking nice and even.
Note shown, the I2C connector also doubles to output the Spectrum Unreg V+ and the Spectrum's +5v regulated supply.
Arty-farty shot. In the foreground the power supply section and the ULN2803 digital output buffer. Over to the right is the address decoding IC's (74HCT86 & 74HCT138).
Eagle PCB artwork screenshot. Amongat everything else, you can see the data bus (D0 - D7) directly between the 82C55 and the PCA9564, and then down to the Spectrum's edge connector.
When I ordered my PCBs from the fab house I got a few extra, interested?....please contact me.
The prototype board.
I had used DIL (non-SMD) parts where I could, but the DAC & ADC in particular required the use of SMD adaptor boards. The 82C55 required a socket.
Full development in progress, including my small 8" LCD (composite input) I used for the Spectrum display.