KEYBOARD


Description

In order to input recipes to the Digital Cookbook a PS/2 keybaord interface is used. All standard ASCII characters are supported. Additional keys such as the function keys or the numeric keypad present on some keyboards are not supported since text input is the primary function.

Circuit

Power (+5V) and ground are supplied to the keyboard from the circuit board. The keyboard clock is connected to pin 2 of PortD, which is also External Interrupt 0. The keyboard data line is connected to pin 3 of PortD. A PS/2 connecter is used so that a keyboard can easily be connected or disconnected at any time.

The pinout of a PS/2 connector looks like this:

(The || in the diagram is meant to indicate the notch which forces correct alignment of the connectors).

Driver

-> This keyboard driver was adapted from that given in the AVR 313 application note.<-

The keyboard driver makes use of external interrupt 0. Therefore global interrupts must be enabled and the global interrupt mask register GIMSK must be appropriatly set. Pins 2 and 3 of PortD are also configured as inputs.

Once a key is pressed the keyboard sends out its clock signal. This triggers the external interupt. The interrupt subroutine (actually found in cookbook.c) calls the GetKey() function. It should be noted that static and global variables are used in this function so that the values stay constant across mulitple calls.

The data sent by the keyboard is called a scancode. The scancode is padded with a start bit, a stop bit, and a parity bit, all of which are ignored. The remaining eight bits are read on the falling edges of the clock (data is transmitted serially). The scancode variable is shifted right one position with every falling edge. If the data on that edge is a 1 then the new MSB of the scancode is set to a 1 as well. Otherwise it is left as the 0 resulting from the shift. In this way 1's are explicitly stored while 0's are implicity stored by the shift operation. After 11 (8 data bits + 3 overhead bits) rising edges of the clock the transmission of the scancode is complete.

Shifted and unshifted keys have the same scancodes so once a shift is detected this is remembered for the next key press. However, to prevent a shift from acting as a caps lock the shift is also cleared after the next key press.

Scancodes by themselves are not very useful becuase they are not the same as ASCII. Therefore a table is used to convert scancodes to ASCII values*. The conversion table has three columns, one for scancodes, one for shifted ASCII, and one for unshifted ASCII. The table is stored in program memory instead of RAM because it is so large and conveniently read only. Variables can be stored in program memory by preceding their declarations with "__attribute__ ((progmem))". The data can later be retrieved by passing the variable's address to the PRG_RDB macro included in pgmspace.h.

A keyboard timeout is also used. When a key is pressed the data is usually sent multiple times. I don't know if this is similar to button bounce or if keyboards are simply made to send out scancodes for as long as a key is pressed (leaving the controller to determine if extra transmissions should be rejected). The keyboard timeout is a simple delay that will register only one scancode for each keypress (unless the key is held down excessively long in which case the user must want to repeat the character several times). However the keyboard timeout is still short enough to allow a good rate of typing (at least in my opinion).

Once the key press is decoded and an ASCII value is obtained it is stored into the screen buffer and shown on screen. Backspace is a special character and acts as you would expect. The return key is also special. In MENU mode it has no effect but in EDIT mode it will move the edit position to the beggining of the next line, just as you would expect.


*As a side note I think some of the scancode conversions given in AVR 313 are incorrect. The correct conversions are used here and where determined by hooking the keyboard up to the STK500 and outputting the scancodes to the LED lights.




Written by Mike Lombardo. 12/12/01