I'm a child of the 80s and have fond memories of the 8-bit computers of that era. My first computer - one which holds a special place in my heart - was a Sinclair ZX Spectrum 48K. Having recently discovered some communities focused on older computers on the web, I decided I wanted to relive some of that nostalgia for myself and installed the Fuse emulator on my MacBook. This was fun for a while but I really wanted a dedicated device - preferably something small, portable and self-contained to fit in with my lifestyle. The choice at this stage was to either follow the path of the awesome Ben Heck and shrink original ZX hardware into something portable or to cheat and use emulation on a small single-board computer. I'm going to cheat :)
So, what do I want from my portable ZX Spectrum?
- Cheap: I have far too many projects to spend large sums of money on a bit of fun nostalgia.
- Portable: It needs to be something I can play with on the sofa or on a lazy afternoon in the garden.
- Keyboard: I don't just want to play games, I also want to program it. To get the full experience, it needs to have those wonderful keyword keys.
- Joystick: I was never into playing platform games with a keyboard. Adventure games, sure, but I don't just want to play adventure games so it's going to need a joystick.
- Instant: I hated tape loading in the 80s and I can't imagine I've grown any fonder of it in the intervening years.
With all this in mind, I drafted a block diagram to help me understand the various components. So let's get building.
Step 1: USB Keyboard & Joystick
Getting the keyboard right is the key to capturing the look and feel of the original ZX Spectrum. We may be building a handheld emulated device which shares nothing in common with the original Spectrum internals but, with careful design, it should be possible to create something which feels reminiscent of the 80s computing experience.
Starting with some protoboards and a big pile of tactile switches, I experimented with a few ideas and settled on the staggered layout shown in the photos. The protoboards we're using are a standard 7x9cm (26x31 holes) available online from many retailers. The switches are surface mount versions which have a softer feel and are less noisy than their more common through-hole counterparts, but either should work as their body sizes are almost identical.
The joystick controls then went into the remaining space immediately above the keyboard. I decided to use a 5-way tactile navigation switch on the left and a large fire button on the right. The joystick will double-up as a controller for the emulator's menu system and a mouse for interacting with the underlying Linux system, so I also added a small secondary button.
The microcontroller for the keyboard is an Arduino Pro Micro. This is a small board which can be programmed as a USB human interface device (HID) such as a keyboard, mouse or joystick.
Once the switches were soldered in place, the matrix which connects the rows and columns of switches to the microcontroller needs to be built. This matrix will enable us to connect all 40 keys plus the 7 joystick buttons to the Pro Micro's 18 I/O pins. The Spectrum keyboard doesn't need to handle multiple key-presses except for the Caps Shift and Symbol Shift keys so we're going to put those on dedicated pins, then we won't need to worry about using diodes to prevent phantom key-presses. I've included a schematic to show how the keyboard, including the matrix, is wired-up. First, each column is linked with a length of single-core wire and then the rows are connected using single-core wire which is carefully shaped to cross over the columns without shorting. This can be a bit tricky because you need to get the row wires high enough to avoid contacting the columns but low enough to leave room for all the wiring we need to stuff in during the final assembly. Finally, the rows and columns are connected to the Arduino pins with wires from old IDE cables.
As mentioned above, the joystick controller is also going to function as a cursor controller and a mouse so we'll need to be able to switch between modes. The default mode will be cursor mode, a combination of Caps Shift + the Fire button will switch to joystick mode and the Symbol Shift + Fire button combination will switch to mouse mode. To show which mode it's in, there are a couple of 3mm LEDs in the middle of the joystick panel. A Power LED will also be useful and a good way to provide this with the Pi is to connect a LED to the Pi's UART TX pin as that will constantly be sending data while the device is on.
To prevent the loose wires from fraying in use, or the matrix wires from shorting, everything is liberally covered in hot glue - ugly but effective!
The last step to get the keyboard working is to program the Arduino with the ZX_Spectrum_Keyboard code from my repository. With that done, you can actually put the soldering iron down, plug the keyboard into a regular computer and use it with a Spectrum emulator like Fuse or Spectaculator. But we're not stopping here, so let's move on ...
Step 2: LCD Screen
The original Spectrum has a screen resolution of 256x192 pixels. To keep (approximately) this ratio and avoid having black bars down both sides, I selected a Waveshare 3.2" 320x240 TFT LCD touchscreen designed for the Raspberry Pi. It isn't going to be connected directly to the Pi's GPIO header so we can remove the connector's plastic surround and trim the pins. I trimmed a 7x9cm protoboard down to 2.1x9cm (the exact size doesn't matter as long as the two remaining corner holes align with the top keyboard holes and there's enough space to solder the GPIO header pins) and soldered the pins in position, which will give us an easy way to mount the screen above the keyboard.
We only need to connect the SPI, power and touchscreen I/O pins to the Pi - it can be quite tricky to track down which pins are actually needed but the information is out there if you look hard enough. The Waveshare screen uses 10 pins: 4, 6, 9, 13, 15, 19, 21, 23, 24 and 26. Obviously, if you're making this with a different screen, you'll need to verify the correct pins before grabbing your soldering iron.
There's no special software configuration needed - just install the manufacturer's driver software and it's ready to use.
Step 3: Wireless (Bluetooth)
The Raspberry Pi Zero board has no wireless capability, only one useful USB port and there's not going to be enough room in the case for a USB hub so I had to get a bit inventive to add some kind of wireless capability for my build. If you're building this with the Zero W then you can skip this step.
There's a neat feature of the Raspberry Pi which will allow us to add a useful wireless capability. By attaching a cheap HC-05 Bluetooth serial module to the Pi's UART pins and tweaking the system configuration, it's possible to get wireless access to the command line terminal using serial-over-Bluetooth. We can then use common tools to send files to the device and manage the filesystem.
Step 4: Power
I chose my battery at the end of development so needed to pick a cell which would fit into the available space. The one I chose was a 2000mAH 25C 1S Lipo (dimensions: 81x34x9mm) sold as a replacement for the Walkera Syma X5 drone. It would be good to be able to charge the battery in-situ with a regular USB connection and to be able to use the device while it's being charged. We don't really want to be fiddling with complex power control circuitry so we're going to use a ready-made module which provides USB charging and also a stepped-up 5V output to power the Pi directly. To ensure the device can be turned completely off, there's a slide switch between the output of this module and the Pi which ensures that the battery can still be charged even when the device is turned off. The Pi needs to be shut down properly to avoid data corruption issues. Rather than needing to log in over Bluetooth serial, we can connect a tactile switch to the Pi's pin 5 (GPIO3) and write a small script which watches this and initiates a shutdown when it's pressed. The power and wireless components were soldered to another 7x9cm protoboard which will sit directly below the keyboard.
Step 5: Connecting It All Together
With all the various parts built, we can assemble the internals. The biggest issue I ran into during assembly was that the USB port broke off my Arduino Pro Micro, requiring me to solder wires directly to the solder pads rather than using a USB cable. This is a notorious weak point on the Pro Micro boards so it's probably worth applying a good glob of hot glue to it before assembly to avoid this. Assuming this particular misfortune doesn't befall you, you have a choice: you can either make a super-slim micro USB to micro USB cable to connect your keyboard to the Pi or you can solder one or both ends directly to the boards. As I needed to solder the Arduino side, I also soldered the Pi side directly to the test points on the rear of the board. There are pros and cons to each option so it's up to you which you prefer.
We'll be keeping the boards together with M3 nylon standoffs. We need 2x 9mm standoffs to connect the bottom holes between the keyboard and the power board. The top holes also retain the screen so we want 2.5mm standoffs between the keyboard and the screen, and 4.5mm standoffs between the screen and the power board. The side photo shows how this looks. The standoffs will need a little careful trimming to get everything parallel - it can be a bit of a tight fit with all the keyboard wires but it should go together. As can be seen from the photos, the device can be powered-up and used after assembly, without needing an actual enclosure. We'll be printing an enclosure soon but, before we get to that, we'll need to install the operating system and get it configured.
Step 6: Software
With the internals assembled, we can go ahead with the software installation and configuration. The Raspberry Pi will run on a standard Raspbian installation The only extra software which needs to be installed, apart from the TFT screen drivers, is the Fuse application. We're using the SDL version to get proper full-screen functionality, which can be installed with:
sudo apt-get install fuse-emulator-sdl
To handle our shutdown button presses, copy the 'shutdown' script from my code repository to /home/pi/
To get a serial console over Bluetooth, add the following line to /boot/config:
We'll want our shutdown script and the Fuse emulator to run on launch so add these lines to /etc/xdg/lxsession/LXDE-pi/autostart:
@fuse-sdl --no-sound --kempston --no-auto-load
Reboot the Pi after making these changes and you should be done.
Step 7: Enclosure and Final Assembly
The enclosure was modelled in Fusion 360 (how to do that is outside the scope of this instructable). There are 5 parts: the case back, screen front, keyboard front, power button and control panel cover. The control panel cover should be printed in a flexible filament (I used flexible PLA but a softer material like NinjaFlex might be better); everything else should be printed in a rigid plastic (I used Filamentum black PLA).
To give the power button some resistance and to prevent it from rattling, stick some 3mm adhesive foam to its back and then punch-out a 4mm hole to allow it to sit snugly over the vertical tac switch on the power PCB. You may need to trim one edge slightly, as can be seen in the photos, to avoid snagging the power board. I also found it helpful to use a small dab of glue to hold the button to the power switch.
We need to glue a couple of nylon standoffs into the upper mounts on the screen front panel to allow the top parts of the enclosure to be fastened securely. Once dried, trim the standoffs flush.
To fit the boards, we first need to create the mounting posts. Remove the heads from some M3 nylon screws and glue the threaded parts into the lower holes of each of the front panels. When these have dried, the 2 front panels can be glued together and the keyboard can be fixed in place using the 9mm and 2.5mm standoffs. Next, With this in place, the screen can be placed onto the upper posts and the 4.5mm standoffs can be added. Finally, the power board can be placed in position and the wires arranged to allow the back to be fitted.
The battery should be stuck in place with some double-sided tape or foam sheet and plugged into the power connector. Now the two halves can be brought together and some short countersunk M3 machine screws used to secure everything in place.
Finally, flip it over and glue the control panel cover to the keyboard panel. I did this with a two-part epoxy adhesive for a strong bond.
Step 8: Keyboard Overlay
We're almost done. All that's missing are some key markings and an overlay so we know how to get to all those wonderful keywords.
The primary letters and numbers are on the actual switch tops. I found some really small 2.5mm letter transfers which fit perfectly on the 4mm diameter tops. They're a bit tricky to apply because the tops move as you rub them but you get quite a few letters in a pack so it's fine to make some mistakes. I ended up touching a few up with a fine permanent marker although, in hindsight, I should have tried soaking them in warm water and sliding them into place (if you've ever built a model kit, you'll be familiar with this process). To protect the letters during use, I dabbed some clear nail varnish onto each key top.
To prevent the silver bodies of the switches from showing through the gaps in the overlay, I used a permanent marker to colour them in - this can be seen in the bottom row of one of the photos.
I designed the printed overlays in the open source GIMP graphics program and then printed them onto photo quality matt paper. Ideally, the overlays will be as thin as possible - I was able to peel the backing from the Epson branded paper I used very easily although this won't be the case with all brands. To protect the print, I covered the paper in clear adhesive vinyl sheet and applied double-sided tape to the back to stick it to the case. Before sticking the overlays down, however, we need to punch out the holes. I used a cheap 4mm leather hole punch and got the best results by sharpening the punches and cutting directly against some scrap 3mm aluminium sheet. Then the overlays just need to be lined-up and stuck down.
Step 9: Conclusion
And we're done! This has been quite a large project demanding a range of skills including basic electronics, soldering, 3D modelling, programming and even a little graphical layout. It's ultimately been very rewarding and the finished device is great fun to play with, but how does it fare against my original criteria?
Cheap: The overall cost of everything, including current retail prices of items I already owned and the stationery items like double-sided tape which will last well beyond this project, is around £80 which make it an affordable project.
Portable: It's definitely portable. This device fits comfortably in a pocket and is completely self-contained so it can be used anywhere. If I were to build it again, I'd make a flat 4-way joypad-style controller rather than using the navigation stick as it protrudes above the line of the device leaving it vulnerable to damage. I'd also like to see if a non-touch screen of similar size and ratio is available with a more scratch-resistant cover as I don't need the touchscreen interface and the resistive surface is particularly prone to damage.
Keyboard & Joystick: I'm really pleased with how these worked out. Although it doesn't have the dead-flesh feel of the original, using the keyboard feels surprisingly reminiscent of the old ZX Spectrum - the layout, overlay and keyword implementation work well together to achieve this. The USB keyboard can also be used on its own with a computer running the Fuse emulator to provide the same experience.
Instant: Using the Bluetooth serial module makes it relatively easy to transfer tape archives to the device from another computer without needing to exit the Fuse interface, and it should be possible to streamline the process further by writing a client-side script to send a file to the device. I would prefer to be able to use the standard Bluetooth "send to device" file transfer feature built into most operating systems, or a proper file sharing system like Samba. However, those are only going to be available with the Pi Zero W board and I didn't use that for this build.
In addition to the items noted above, if I started this project again from scratch, I'd choose a thinner battery with a larger capacity early in the project and design around it rather than needing to select a suitably-sized battery at the end of the project. I'd also use a Pi Zero W rather than a Bluetooth serial module to expand the options for sending files to the device. Another obvious improvement would be some kind of hardware battery state indication as there's currently no way to see how much charge is left. I'd also consider using a Ramdisk-based OS like Alpine Linux which would be more tolerant to hard shutdowns and should allow for a single on/off switch without the need for a separate shutdown button - much more like the original ZX Spectrum, just unplug it when you're finished.
It might be interesting to design a custom PCB for this device which would, potentially, allow us to put the power components on the back of the keyboard rather than having a separate board. This could significantly reduce the depth of the finished device. It would also make assembling the device easier and offer the potential of some kind of self-assembly kit. If there's enough interest in this project, I might do a version 2 which addresses these issues.