IBM PC PS/2 Keyboard Interface for Sensor Input
Scan codes for PS/2 style IBM PC Keyboard in decimal
Typical scan code transmission from keyboard
GetKey MyBlock reads key code and uses a file to lookup the proper character
Simple one line demo program
Typical timing for one character read
Click here to download the NXT-G programs and the key code data file.
The GetKey MyBlock must be in your MyBlock subdirectory and the data file decode3.txt must be downloaded to your NXT before running the program.
PC keyboards are surprisingly complex. You might think they just send the ASCII value of the key that is being pressed, but that would be way too easy. Iím not going to duplicate the volumes of information already on the web on this subject. However, there are a few basics I should to go over.
The most important thing to know is that the keyboard serially sends an 8-bit key code for the key being pressed. See the figure below. It also sends a code when the key has been released. That is another 8-bit code (F0 hex) followed by the key code again. Some keys send multiple codes, but I will skip that complication. There is a great keyboard emulator that helps explain how all this works.
The serial data is sent synchronously which means, unlike RS-232, it has a separate clock signal. The data is valid on the falling edge of the clock from the keyboard. I invert the clock with a 2N3904 because logic chips work on the rising edge. The data consists of 11-bits; a start bit, 8 data bits, a parity bit and a stop bit. The key code for the Q key is shown below with the already inverted clock. The Interrupt signal will be explained later.
It takes two 74HC164s to shift all 11 bits from the keyboard. When the entire character has been shifted, the stop bit will be in Q0 of U2. Q1 of U2 is the parity bit. The most significant bit of the code is in Q2 and so on till the least significant bit in Q1 of U3. Finally, the start bit is in Q2 of U3, but all we care about are the 8 bits of key code.
The PCF8574 is an I2C interface chip that can read in 8 bits of parallel data. It also provides an interrupt output that goes low when the input data has changed since the last time it was read. This will be handy for detecting that a key has been pressed. This output is wired to the NXT so that it looks like a switch type input. Zener diode D1 and resistor R7 provide voltage protection for the 8574 in case the NXT is accidently put into the old RCX style powered sensor mode.
The NXT-G keyboard sensor interface should look like a block with an output equal to the character of the key being pressed. A simple NXT-G MyBlock GetKey below does just that. It waits till the PCF8574 sees a change on the inputs and then it uses the I2C port on that input to read the value. Remember this is just the key code. A txt file with the appropriate characters for every key code is read till it comes to the right one. You could do this with an array too I suppose.
A program that inputs and displays a line of characters is shown below. First the PCF8574 needs to be configured so all its I/O pins are inputs and it needs to be read once to clear any interrupts. That is all done with the single I2C read. From there it just loops getting characters and displaying them on the NXT.
In NXT-G it takes about 30ms from the time the keyboard sends a new key code to when the I2C read finishes. This can be seen in the scope trace below. I imagine this could be sped up by using NBC or a custom LabView program.
As previously mentioned, the keyboard also sends a two byte sequence when the key is released. Since this sequence ends in the same key code that was sent when the key was first pressed, the PCF8574 will not keep the interrupt line low because the inputs will be now be the same as when the 8574 was last read. If your program doesn't try to read again before the release, then everything will work perfectly (like the middle trace below). However, if the next read takes place before the release, then the release will be falsely read as a second hit of the same key. I'm not sure how to work around this problem gracefully without deliberatly adding delays, but as long as you stick to just typing the keys without holding them down too long it works fine.
You can also decode the keycodes into musical notes. Here is a short video of a piano I made using this interface.