Interfacing the PS/2 Keyboard

As an exercise, and to help me learn about the protocol, I’ve set up my trusty Arduino to read scancodes from a PS/2 keyboard. The protocol is fairly simple. The keyboard uses four pins in the connector whether it is the 5 pin AT style or the 6 pin PS/2 style. These are CLK, DAT, GND, and VCC. When a key is pressed, the keyboard begins generating a clock signal on the CLK pin. At each falling edge of this clock signal, a new data bit is presented on the DAT pin. This lends itself well to an interrupt driven approach. The Arduino supports an external interrupt (interrupt 0) on digital pin 2, so that’s where I connected the clock line. The DAT line was connected to digital pin 3. Pin 2 is then configured to fire an interrupt on the falling edge of the signal, and an interrupt service routine (ISR) is attached to that interrupt so that the Arduino will read the next incoming bit from pin 3, keeping track of where we are in the data sequence so it can store the complete scancode once all of the bits have been read.

PS/2 Pin Connections

Connecting the Keyboard

To start listening for the interrupt, we need to put the following line in the setup() routine:

attachInterrupt(0, kbdint, FALLING);

In this case, kbdint is the name of the ISR which will be doing the work. It will be executed once each time the clock signal on pin 2 is pulled to ground by the keyboard, each time capturing one bit of incoming data.

void kbdint()
{
pin3 = digitalRead(3);
if(pos == 0)//start bit
{
pos++;
datavalid = 0;
scancode = 0;
return;
}
if(pos < 9)
{
if(pin3 == HIGH)
{
scancode |= (1<<(pos-1));
}
pos++;
return;
}
if(pos < 10){pos++; return;}//parity bit
pos = 0;
datavalid = 1;
return;
}

The variables used in the ISR are defined as volatile:

volatile char pos = 0;
volatile char scancode = 0;
volatile char datavalid = 0;
volatile int pin3 = 0;

The keyboard will send data in 11 bit frames consisting of a start bit, eight data bits, a parity bit, and a stop bit. A more complete analysis is found here, among other places. This code keeps track of what bit was just received by incrementing pos. It ignores the start bit, inserts each of the next 8 (data) bits into the scancode variable, and ignores the parity and stop bits. The datavalid flag could be used to indicate to some other part of the program that a complete scancode has been captured.

This is pretty basic, naive code, but I think it proves the concept sufficiently. The protocol also allows for sending data to the keyboard in order to change settings and control the various LED’s. Perhaps that will be fodder for a future post.

Advertisements
This entry was posted in Arduino. Bookmark the permalink.

2 Responses to Interfacing the PS/2 Keyboard

  1. Willi Mussmach says:

    Can you please mail to me a valid example code (Arduino PDE-File, Include Files *.h and *.cpp) for your “Interfacing the PS/2 Keyboard” Project?

    Many Thanks and best Regards from Germany.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s