As usual, it has been a while since my last update. I've been busy working on some new expansion cards for the MC68000 motherboard. It's a bit boring interacting with the system via an RS232 serial port, so I thought I'd build an expansion card enabling me to connect the motherboard to a keyboard and mouse.
The first step in the design was to pick a communications protocol. I wanted to implement a standardised protocol so that I could use an ordinary keyboard and mouse without modification. Having ruled out ancient XT keyboards, I was left with USB and PS/2. USB felt too modern for this project - after all, the idea is to build a system which has a level of technology roughly in line with the sort of stuff that was available in the 80s and early 90s. PS/2 it is, then! To the breadboards!
Here's the prototype dual-channel PS/2 controller plugged into the MC68000 motherboard.
The PS/2 protocol is pretty straightforward. It's an 8-bit synchronous bidirectional serial interface in which the "device" (the keyboard or mouse) generates a clock signal at around 10kHz and exchanges data with the host in a format quite similar to RS232. In PCs, the interface was implemented using an Intel 8042 microcontroller. When a key is pressed on the keyboard, a scan code is sent by the keyboard to the host. This code uniquely identifies the key, but is not related to e.g. the ASCII code representing the symbol on the key-cap. When the key is released, the keyboard sends a "key released" code (0xF0), followed by the scan code of the key. The PS/2 mouse protocol works a bit differently: whenever the mouse is moved, or a button is pressed or released, the mouse sends a small packet of data (three or four bytes, depending on the type of mouse) containing information about the mouse's relative motion and the state of the buttons.
I considered building the controller around an Intel 8042, but eventually decided against it. It's a decent enough chip, but I felt that I wouldn't learn the protocol in sufficient depth by using somebody else's implementation. Instead, I decided to build an interface around a microcontroller: the (admittedly fairly modern) Atmel ATmega8. This is what I came up with.
The ATmega8 has 28 pins, which is just about enough to implement two separate PS/2 ports and an 8-bit interface to the host system. The firmware is quite simple: it's mainly an interrupt-driven state machine which manages communication between the microcontroller and the PS/2 devices. The non-interrupt-driven part of the code is pretty much just a loop which deals with the interface between the controller and the MC68000.
The controller exposes a bunch of registers to the host processor; these include a configuration register which can be programmed to enable interrupts to be raised when various different conditions are encountered on each port: byte received, transmission completed, timeout, parity error, etc. The controller also contains a 256-byte FIFO for each PS/2 channel (unlike the Intel 8042!); this means that the host doesn't need to respond immediately whenever data is received from the peripherals.
There are horror stories about the damage caused by unplugging PS/2 peripherals from early PCs. Apparently the electrical interface wasn't very well-protected, or whatever; if the rumours are to be believed, a motherboard could be destroyed by connecting or disconnecting a PS/2 keyboard at the wrong moment. It's difficult to know how much of this is true, but given that my controller connects to the outside world, it needs to be reasonably tolerant of abuse. With this in mind I have added short-circuit protection, protection against shorts to out-of-range voltages (within reason), and some transient/noise suppression. In order to make the interface somewhat hot-pluggable, I've wired things up so that the ATmega8 can switch each PS/2 port's power on and off independently.
Another slightly annoying thing about early PCs was the need to connect the keyboard and mouse to particular sockets. There's no electrical reason why the ports shouldn't be interchangeable, so - on my controller - they are. The driver software can easily work out whether it's talking to a keyboard or a mouse, and behave appropriately.
As you can see from the schematic, the controller is an extremely simple circuit; it only took an hour or two to lay out the PCB. The board is 95mm x 45mm, double-sided. I've sent it off for manufacture; the first boards should arrive next week.
If anybody is interested, I might write a little more about the controller firmware and the MC68000 interface. I'm prepared for a wall of silence from you all, though :)