There are a lot of devices which would be great if we could use them to communicate with a micro-controller and a keyboard is one of them. Adding a keyboard interface opens up a whole world of varying your input to the MCU and controlling it.
A lot many tutorials about this are already available on the internet, but I found that patching ready made code to your MCU is most often problematic. Its best to understand the protocol and write code yourself.
THE PS/2 PROTOCOL :
This is how a male PS/2 connector (on the keyboard) looks like :
Each key press on the keyboard corresponds to a fixed hex code which is communicated by the keyboard controller to the MCU. This code is known as the scan code. This is followed by a “break code”, which indicates that the key was released and consists of two “words”. The first “word” is the same for all keys (generally F0), and the second “word” is generally the scan code repeated again.
Now let’s deal with only communication from the keyboard to the MCU.
The data format is as below :
1 start bit
8 data bits, least significant bit first
1 parity bit (odd parity)
1 stop bit (always 1)
One word therefore consists of 11 bits, and three words make a package. One package corresponds to one key press.
The data and clock lines are open-collector. They are always high in the idle state. The keyboard pulls the clock line low and generates a clock signal to begin sending data on the data line, when a key is pressed. Note that the keyboard won’t send any data if the clock line has been held low by the micro-controller, even if a key is pressed.
The clock line which is normally high is pulled low by the keyboard to begin transmission.
One clock pulse consists of a high level for half a clock cycle followed by a low level for the remaining half. Data is loaded when the clock line is high and therefore must be read when the clock line changes from high to low i.e. on the falling edge of the clock.
Timing is absolutely critical and wrong timing will lead to totally wrong or even no data.
The SCK line (used if communicating via SPI) should have a frequency of about 10 -16.7 kHz. Since we shall be using the interrupt method, we need not bother with the clock frequencies.
The Interface : Data acquisition
Data acquisition can be done in different ways, including SPI , or by continuously polling the data and clock lines to see when they go low etc. However, shall be using the interrupt method here.
The clock signal generated by the keyboard is fed to the INT2 line of the ATMEGA16. The reason for selecting INT2 is that it is an edge triggered interrupt and can be used to detect a rising and falling edge asynchronously i.e. independent of the MCU clock. The data line is sampled at every interrupt trigger and the needed bits are stored and shifted to obtain the scan code.Since we already know the data packet format, we can safely afford to neglect the remaining bits. Here, we shall not be reading the break codes. However, they may be used if special functionality is needed.
Keyboard Code This code is very basic and will help you obtain the key scan codes. You can further add the look-up tables for these scan codes to identify the keys pressed. You could also try out key combinations and implement extra functions, password features etc.
Reliability issue : The above code works just fine. One scan code can be detected additionally as well. However, if code to read the two scan codes that follow is added, all the data i.e. all three words get messed up. Reason yet to be detected and fixed.
References and additional reading :
Images courtesy computerengineering.org
P.S : Code will be improved and added soon. Keep visiting !! 😀