[A Project to interface a PS/2 keyboard to a 68hc11 microcontroller]
At the lowest level PS/2 keyboard interface is an active-clocked packetised serial bitstream using open-drain drivers, running at 10KHz-30KHz (frequency depends on keyboard, and can vary somewhat at runtime!). The clock signal is “idle-high”.
The keyboard provides the clock-signal for both directions, although for the host-to-keyboard direction, it needs to be prompted to do so by the host pulling the clock-line low for approx 60 microseconds then pulling the data line low for 60 microseconds (whilst continuing to hold clock low), followed by releasing the clock (letting it float high via pullup) – the keyboard will start providing clocks shortly after the host releases it: the first clock will see the data-line low (as just described) which acts as the start-bit. A darned complicated arrangement for sure, but at least it saves on pins, and it is much less complex than, say, 10BaseT Ethernet!
Each keypress or release causes the 8-bit scan-code for that key to be sent to the host from the keyboard, prefixed by a start-bit and suffixed by an even-parity bit followed by a stop-bit, ie: 8e1. The driving device (keyboard or host) must ensure that data (bit) values are stable and valid on the falling edge of the clock.
A final wrinkle is that shortly after a host-to-keyboard packet is received by the keyboard, the keyboard drives a 1-bit “acknowledge” zero.
Although there are many different (and occasionally contradictory) descriptions of the protocol, wiring and logic-drive, I will be using http://pcbheaven.com/wikipages/The_PS2_protocol/ and http://www.computer-engineering.org/ps2protocol/ as my guides.
This particular protocol is not so straightforward (can’t use a simple UART). Rather than using a dedicated programmed peripheral 8048, 8051, AVR or ATmega (cough, choke), we can use the timer facilities of the 68hc11 central processor to do it…
The 68hc11 provides programmable input-capture pins, which (amongst many other things) can be configured to trigger a pin-specific interrupt when either a rising-edge, falling-edge, or any-edge is detected (you choose which you want, and program the configuration accordingly), and whose input pin-level can be read with a single instruction. Thus connecting the data and clock lines each to an input-capture should allow detection of incoming clock-edges and the detection and collection of incoming data-bits.
The interrupt-service routine will have to use a stateful counter to know when to read-and-save the data-bits, and a memory-location as a “shift-register” to accumulate the packet payload (scan-code).
Sounds grand, I bet, but time is running short today so let’s instead have a look at a 68hc11 program that does 16-bit counting and output-pin control (code at http://shelldozer.im/cherryside/src).
If you can afford to completely waste 10 minutes of your life, check out the demonstration (best viewed full-screen) of what my utterly minimal character-mode development environment is like to use – surprisingly, it’s quite comfortable and effective for small programs like this.