Every Key has Its Code
Because every key has a unique code, you might try
to use that code as an index into an array of ASCII values;
basically, a lookup table. That’s a good idea. You could
create the array ASCII_Equivalent[ ] in which to store the
ASCII values. Then, the W key code 0x1D, for example,
would direct software to array element
ASCII_Equivalent[0x1D] that would hold the W key’s ASCII
code. So, do we save the value for an uppercase or
lowercase W in the array? It depends. The software must
monitor codes from the two shift keys (one on the left and
one on the right of the keyboard) and decide which ASCII
value to retrieve. So, we create two arrays — LC_Array[ ]
and UC_Array[ ] — for lowercase and uppercase ASCII
values.
Table 2 shows part of the information for each array.
The downloads for this article include the complete table,
and the PSoC software includes both arrays and all PSoC
files. Gray rows in the table indicate an unused code or
no value assigned for a key such as F1 or F2.
A Flowchart Maps Our Way
The translation of key codes into ASCII values gets
more involved as shown in the software flowchart (Figure
9). This code runs in an infinite loop, but you could use it
as the basis for an interrupt-service routine (ISR). That
approach goes beyond the scope of this article.
The keyboard software has three main tasks. First, it
waits for the SPI buffer memory to become “not empty,”
which signals new information has arrived in the SPI port.
Second, the software must properly detect the shift key’s
condition to choose an uppercase or lowercase ASCII
value. Third, it must handle the key release code and the
key code that follows it to ensure we don’t get duplicate
characters when we release a key.
The software uses two true-false flags: KeyRelease_flag,
which when true indicates the software has detected the
0xF0 key release code; and Shift_flag that gets set to true
when the software senses a pressed shift key (but not caps
lock). Please refer to Figure 9 as I explain the software
operations. Suppose I press the letter G. The “Get Key
Code” software section converts the 11-bit keyboard
information into the eight-bit keyboard code
(Keyboard_Data in the software). This keyboard value
equals the G key code, 0x34.
The next software section tests the value to determine
if it equals the key-release code, 0xF0, or either shift key
code, 0x12 or 0x59. In this case, the G key value matches
none of these three conditions. So, the program continues
and the value from some previously pressed key goes into
variable Old_Data; the G key value, 0x34, gets put into
the New_Data variable.
This process lets the software later determine if the
key just released has the same code as the key pressed
earlier. It’s simply a way to detect an error, such as
pressing two keys at once. More about this shortly.
Next, the software tests the KeyRelease_flag, but
because I haven’t released the G key this flag is false.
Then, based on the state of the Shift_ flag, the MCU
decides whether to fetch the ASCII value for the
uppercase UC_Array[ ] or from the lowercase LC_Array[ ]. I
haven’t touched a shift key, so the Shift_flag is false, and
the software gets the lowercase g ASCII value 0x67. The
software then goes back to await arrival of a new key
code. (In my software, the ASCII value goes to my host PC
and the terminal displays “g.”)
When I release the G key, the software must
recognize the key release code and then ignore the key
code that closely follows (refer back to Figure 2). Without
this test, the software would sense two key codes from the
pressed and released key, and a terminal would display
“gg.” Here’s how the software avoids the “double g”
problem.
Detect a Key Release
When I release the G key, the keyboard transmits the
key release code, 0xF0, which the software detects and
then sets the KeyRelease_flag to true. Next, the program
goes back to wait for another value from the SPI port. In
this key release
example, the
70 July/August 2018
Note 1. A person
in a support group
reported using a
UART with a
12,000 bits per
second (bps) clock.
Worth a try, but an
SPI port can better
handle clock
frequency changes
from keyboard to
keyboard. My PS- 2
keyboard produced
a clock signal
equivalent to
13,700 bits/sec.
Table 2. A portion of the lowercase and uppercase information for PS- 2 keyboard-to-ASCII
conversions. The keyboard does not assign codes 0x17 through 0x19 to any keys.
PS- 2 Keyboard Scan Code Lower-Case Characters Upper-Case Characters
Decimal Hex LC Keyboard Char LC ASCII Value UC Keyboard Char UC ASCII Value
20 14 c 63 C 43
21 15 q 71 Q 51
22 16 1 31 21
23 17 0 0
24 18 0 0
25 19 0 0
26 1A z 7A Z 5A
27 1B s 73 S 53
28 1C a 61 A 41
29 1D w 77 W 57