Interfacing XT Keyboard with Arduino

Hey guys,

I just bought an IBM Model F "clicky" keyboard for my IBM 5160 XT. However, I would love to use this keyboard eventually with a modern computer. The communication protocol is not difficult. In fact, it's far simpler than PS/2.

There is a clock line and a data line. The clock line is held HIGH when data is not sent, and the data line is held LOW. When a key is pressed, it sends one start bit followed by 8 data bits, starting with the LSB. There is no stop bit to my knowledge. Thus the clock line goes low 9 times during a transmit cycle. When interfaced with the IBM PC/XT, it actually holds the data line low until the keyboard data can be processed.

Also, a note about the scan codes: codes 0-127 are sent when a key is pressed, and codes 128-255 are sent when a key is released. The only difference between a key's scan/release code is the MSB is a 0 vs. a 1.

Though this all sounds simple, I can't for the life of me make a code that works. The only bit of code I found regarding this asynchronous serial communication was not at all helpful. ( The Arduino here makes it's own clock, and the MSB is first. I know there has to be an easier way than what I'm trying.

Code snippets and ideas would be greatly appreciated. Thanks!


You should start with one of the existing PS/2 keyboard libraries. My understanding is that the older protocol is essentially a subset of the ps/2 code (ie not bi-directional.)

I really don't want to deal with libraries. I would rather have one piece of code devoted entirely to the XT keyboard. Trying to sort through someone else's library to pick out all the unneeded code is not my goal.

What I figured would be easiest would just be writing some code specifically for the protocol. I know it shouldn't be difficult, but my code just doesn't seem to want to work correctly. For example, when I press a key, I get the same code as when it's released. What's supposed to happen is the MSB is 0 for a press, and 1 for a release. The rest of the code should remain the same. This leads me to believe that my code is too slow and could be dropping a bit.

Here's what I need: when the clock pin goes low for the second time, the LSB is recorded as whatever the data pin is (HIGH = 1, LOW = 0). When it gets to the third clock cycle, the second bit is recorded. This occurs until it reaches the 9th clock cycle, or in other words, the 8th bit.

If someone could help, I'd be ever so grateful!!


Just because I know someone else one day will want to do the same thing I’m doing, I’ll post the code that I finally got working. There still will be some glitches with this code, because it simply doesn’t seem fast enough to register every release code. Thus, some keys might get “stuck.” However, this might be a keyboard problem. Only a good look on the 'scope will tell…

Oh, and I haven’t (obviously) done the lookup tables yet. But all that info is easily searchable on the internet. Nor have I found an easy way to imitate the computer’s keyboard commands from the Arduino. Any ideas?


int clockPin = 7;
int dataPin = 4;
byte data = B0;
int test = 0;
int counter = 0;
int numbits = 10;

void setup() {
  pinMode(dataPin, INPUT);
  pinMode(clockPin, INPUT);

void loop() {
  if(digitalRead(clockPin) == LOW && test == 0 && counter < numbits) {
    test = 1;
    data = data >> 1;
    if(digitalRead(dataPin) == HIGH) {
      bitSet(data, 7);
  if(digitalRead(clockPin) == HIGH && test == 1) {
    test = 0;
  if(counter >= numbits) {
    data = B0;
    counter = 0;