[A Project to interface a PS/2 keyboard to a 68hc11 microcontroller]This RetroChallenge project reached its’ target – decoding, reading, and reporting PS/2 keyboard scancodes with a 68HC11 microcontroller using only internal resources (no external memory, no external I/O device controllers, no external logic, etc).
I had picked a rather minimal project because I knew April would be an extremely busy time at work (end of financial year, and all that stuff), and in spite of the low bar, it was still a challenge to complete it in time.
And now I guess it time to review the lessons learned:
For someone who’s current employ involves x86/x64 CPUs, massively multi-layered software stacks, incorrigible black-box hardware, truly awful scripting languages, software-patches that break the very systems they are supposed to fix, bait-and-switch online software-subscription services, and so on: RetroChallenge is very therapeutic. Such fun playing with things at a much lower level! And from a simpler, happier technological time.
RetroChallenge also provides a great opportunity to build electronic systems using blu-tack, gaffer-tape, cardboard boxes and random bits of plastic off-cut. What more could you want?
In spite of being determined to avoid lazy-oops issues on this project, I once again got distracted at just the wrong moments and suffered a number of Doh! RTFM! problems, of which I am wholly 100% to blame. Redmond-induced premature senility?
Good Programming Practice – as in: “I needed the practice!”
In spite of the minimal objectives, the project was a very useful exercise in “compacted assembly programming”, getting the program code and data to fit in 280 bytes of on-chip RAM and 76 bytes of on-chip EEPROM. That includes all the MCU initialisation, the command-processor, serial-I/O routines, the PS/2 keyboard interface, the deserializer state-machine, binary-to-hex-ASCII conversion routines, and an implementation of an asynchronous-reader/writer circular-buffer (so an interrupt-service routine can be asynchronously adding bytes to the buffer at the same time as the main program is removing bytes from the buffer, without collision or overrun). For those of you with even more time to waste, the source code for the project programs can be found at http://shelldozer.im/cherryside/src.
As always with 8-bit accumulator-oriented CPUs, there is a trade-off between code-size and speed (although not at all as complex as the trade-offs would be with modern 64-bit CPUs). For instance, on the 68HC11, choices have to be made between a memory-load followed by sequence of 4 shift instructions to maneouver a data-bit into the right position, versus using bitwise AND with a branch and a load-constant instruction: on the 68HC11, using X-indexed memory addressing, the former takes 6 bytes and 12 cycles, whereas the latter takes 8 bytes and 11 cycles. In an ISR needing to be fired at 30KHz on a 2MHz CPU (with minimum 12-cycle interrupt latency), saving even a single cycle might well be needed, but when RAM is so constrained, saving 2 bytes would be a better choice as long as the ISR can complete quickly enough. Similar applies to eg: using explicit load+bitop+branch versus using the BRCLR (branch if bit clear) instruction. The 68HC11 instruction-set is full of these kind of trade-offs…
Dijkstra be Damned
I am also unnecessarily proud of my hand-constructed tail-merging. For an inveterate high-level-language programmer, being able to optimise a function by jumping directly into the middle of another function (and thus subsequently borrowing the latters’ “return-from-subroutine” instruction), is highly intoxicating. A function with no return and no save, but that returns after saving anyway. Cool!
As opposed to my previous 68HC11 project, I was much more familiar with 68HC11 programming this time around. Although sometimes painful, the best practice you can get is to have to implement a program in a very small amount of memory and/or with hard real-time constraints – to actually have to do it.
Debugging with LEDs
…yet again proved to be fantastically useful: being able to illuminate or toggle an LED when a particular state crops up, even within an interrupt-service-routine, turned out to be a sanity-saver at times. For anyone else considering messing about with MCUs, I would not hestitate to recommend putting at least a pair of program-controllable “debug” LEDs into the system – it makes an enormous difference.
Although I have already previously noted how rather fantastic the 68HC11 is, and therefore was expecting it this time around, I was still delighted and surprised at how cleverly put together this family of MCUs is. Quite apart from the incredible timing subsystem, and the built-in devices, and so on, this time around I have noticed something else: although I do not recommend doing so, it appears you can get away with seriously abusing the 68HC11E series – floating inputs, inverted supply voltage, cross-shorted driven pins, and so on, without any detectable damage. Maybe I have shortened the lifetime of this particular MCU chip, but it sure doesn’t look like it, and given that this particular chip was recovered from a beaten-up trashed car radio, it had already had a hard life even before I got my hands on it 3 years ago.
You really do have to be careful with Internet-sourced advice: some of it, nomatter how logical and sensible it seems at first glance, is just complete rubbish. Some of the tips and advice could even cause the magic smoke to make a run for it. On the other hand, the Motorola documentation isn’t always quite up to snuff either. The situation is very like that when dealing with domestic plumbers: when you find a good one, hang on to them, because they can be few and far between.
One particularly good resource for the “behind the scenes” 68HC11 explanations is Mosaic Industries. For example, the 25mA-per-I/O-pin maximum current rating is not only about avoiding pin-damage, there is another more significant reason: voltage droop.
Again previously noted, a minimal but still very capable 68HC11 SBC only really needs to provide an oscillator crystal, an RS-232 level-shifter, a LVI/voltage-regulator, and a very small handful of capacitors and resistors. You don’t even need an external PROM/EEPROM programmer device: the 68HC11 can program EEPROM “in-circuit”, off its’ own 5V supply. Yes, even external parallel EEPROM. The SBC I used in this project is the Adapt-11 from Technological Arts in Canada. Amazingly, although having been listed as a “legacy” product for several years, the Adapt-11 is still available from them. If you want an SBC that is a little like an old-skool 8-bit alternative to a RasPi (and is even smaller than the big Pi), you might want to visit Technological Arts online.
1980s IBM Hardware Designers
…should not generally be trusted, the PS/2 low-level interface is slightly wierd, rather more needlessly inconvenient than it could have been. I suppose at the time, it was cheap, but there is a difference between “complex” and “complicated”, and the PS/2 keyboard might just have fallen on the wrong side.
Given how satisfactory the end result of this project was, there are a few follow-up mini-projects that spring to mind: (1) getting bidirectional communication going properly, so I can turn the keyboard LEDs on and off and set the typematic-repeat rate; (2) extending the program to perform full decode-to-ASCII of ASCII-ish keys, and to provide a state-machine to handle meta-keys which need to have both press and release tracked (L-ctrl, R-ctrl, L-shift, R-shift) and those that don’t (caps-lock, scroll-lock, num-lock). Maybe next RetroChallenge?