Compared to a lot of people, I know a lot about computers, but compared to what there is to know, I know very little. The deep magic is a bit lost on me. I don’t really know much about the hardware except theoretically what the different bits do, and how to plug it in.
After seeing some examples of people doing this with other microcontrollers, I wanted to experiment a bit with a vintage electronics project and get a bit closer to how it all works behind the scenes.
What I wanted to try was connecting a BBC Micro keyboard to a modern computer. The BBC Micro’s big day was in the ‘80s, but we had one at home in the 90s, and they’d be at the back of classrooms sometimes. I remember bringing home some ‘learn to code on the micro’ books from the library, so logically this is what I actually first coded on (even if I don’t think I got that far).
I’m following in the footsteps of people who know what they’re doing, and the mechanics of how the keyboard works are explained in this blog post, and this blog post had a better diagram of exactly what the keyboard cable is connected to.
What I did differently was use a Raspberry Pico microcontroller - which could be programmed in a form of Python, so I don’t have to learn too many things at once to try and make use of it. I bought a broken BBC Micro off ebay and started learning and experimenting.
My final code is in a github repo (more useful for reference purposes than something you can just pick up and use obviously).
Here are some things I learned along the way:
Mechanically a keyboard is a matrix, where keys are arranged into rows and columns. By activating a row and a column, you can then check if that key is currently being pressed. This means rather than a connection for each key, you just need the necessary connections for activating rows and columns, and getting a signal back.
The BBC Micro keyboard has a few extra complications. The break key is off the matrix with its own connection because originally this would have triggered a reset directly. More complicatedly, to take some of the load off the CPU, the keyboard scanning is handled by a hardware component. Triggered by a regular on-off signal (clock) from the main machine, this cycles through every key to see if it has been pushed. If any key has been pushed, it sends a signal back, which would have interrupted the main CPU, which would then have done a software scan to figure out which key was being pressed. Technically I didn’t have to implement the hardware clock at all and the pico could just run the software scan all the time, but it seemed a good challenge to do both.
This explains all the connections coming out of the keyboard. There are 3 wires for the 3 LEDs (Caps lock, Shift lock, and Cassette Motor). 4 wires to set the column (up to 16 in binary), 3 wires for the rows , 1 for the clock pulse, 1 for the break button, one for the output of the hardware scan, one for the output of the software scan, one to turn the hardware scan on and off, and the 5v and ground wires.
To connect these to the Pico, I used a breadboard, leading to a bit of a jungle of wires. This connects most of the wires to the GPIO (general purpose input output) pins, which can either be set ‘high’ or ‘low’ to send a signal, or can read if a ‘high’ or ‘low’ signal is being sent from the other end. The pico is running Circuit Python, which has libraries to help the pico act as an interface device like a keyboard or mouse. This meant most of the really fiddly stuff was handled for me, and I just had to write a script that connected the signals to and from the physical with how the keys should be being pressed and released on a normal keyboard. The video below shows one of my early attempts to control both the status lights and get input from the break button.
The final circuit python script has a main loop which implements the 1 MHZ clock, controlling the hardware scan. If a key is pressed, the pico detects the hardware scan output going high, turns off the hardware scan, and starts a software scan to find out which key it was. I got stuck here for a while, but eventually figured out a clock pulse (something that would have kept going independently anyway if it was controlled by hardware) is needed to set the column after the value is changed. Adding that in successfully gave me back a column and row position for any currently pressed keys.
Then came the really boring bit, mapping each key to the correct value. For most this is simple enough (you press A, set the map for the row and column to `Keycode.A`). However, the Micro keyboard is by modern standards non-standard. It has a separate @ key, and different options for a number of the shift options of a key. There is no backspace or alt key, a COPY key, and a shift lock button.
Because the adafruit package I’m using to act as a keyboard is a US-keyboard, I decided to go with a fairly basic approach to solving this problem, where for certain keys it will pretend the shift key is down, and for others it will pretend a completely different key is pressed if the shift is down. Technically you could do a nicer key mapping using adafruit’s option for other keyboard layouts, but it works, so it’s good enough. I haven’t implemented shift lock (it’s the alt key), and I’ve set ‘Copy’ to Windows/Control. The keyboard interface knows the system state of the caps lock, and so there’s a stage in the loop where it checks that the Caps lock LED is in sync with that. The break key is outside the matrix grid, and so it has its own button handling that acts as a backspace.
The one remaining thing I had to learn about was ‘debouncing’. When you hold a key down, it waits a certain amount of time before it says you’ve pressed it again, but then it assumes you want to press the button lots (especially useful on backspace). I added a small queue that stops a key-press being triggered for the same key too quickly, but this interval then drops if the key is still being held down.
Once this was all working, I needed to get my jungle of wires into something a bit more robust. I considered learning how to use some circuit drawing software and getting a pcb made, but seemed inefficient for a one off.
Instead, I had to relearn how to solder, and make a little board that could take the ribbon cable from the keyboard, and map the inputs to the pins of a pico. After eventually getting the hang of how soldering worked, on my third attempt to make a connector I managed to correctly wire a little board to do the work. After plugging this in, all I had to do was adjust the mapping as I’d moved some of the connections I was using around.
At the end of this is a perfectly functional keyboard, that plugged into a modern machine works exactly as you’d want. Now I needed something to plug it into.
Technically I could get another pico to emulate the bbc micro, and then plug my pico into it. This might be fun at some point, but it looks a bit fiddly. Instead I’m using an old Raspberry PI 3, which can fit in the bbc micro case, and run linux, so is a bit more multifunctional. This is annoyingly just not quite fast enough to run a bbc micro emulator in the browser. It works for light browsing, but can also run other emulators - which means I can play the DOS games of the 90s, happily on a 2015 mini-computer, inside the case of an 80s computer. This isn’t the easiest way to do that, but I did learn a lot, and isn’t that fun?