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.