Line 284 calls our function LoadEEPROMcfg(). This
function stores our scan codes into the PIC’s EEPROM
area. There is no need to do this. We could have just as
easily hard-coded the scan codes, but this would require a
complete re-compile of the source code every time we
wanted to make a change.
Storing these values in EEPROM allows us to use an
EEPROM editor to set the appropriate memory locations
with the scan codes that we want reported on a key hit. It
simply makes life a little easier in the cases where we
either don’t have the correct compiler or like our ROM
code just fine.
Line 284 calls our function Fill_USB_SCANCODES().
This function validates our scan code values just to make
sure that the data isn’t corrupted or that our values are
not out of reasonable range. Knowing my customer, I
wanted to make sure that if he accidentally changed the
EEPROM stored scan codes to something that was
‘useless’ for his needs, that the firmware could catch it and
adjust as needed.
Lines 287-290 are just a short delay that lets our
indicator LED stay on for a bit so we can see it. The loop
also calls the internal USB service routine periodically so
that we don’t miss any of the USB communication events.
Lines 292-303 are the main loop infinite service
routine. It is, again, pretty straightforward. We do some
housekeeping to keep the USB connection alive, and if we
are connected and enumerated on the USB chain, we
look for our key hits and send the scan codes as required.
Clean and simple.
Now, let’s look at the function usb_keyboard_task() in
a bit closer detail. After all, it does all of our task-specific
work. Figure 6 is a screenshot of the function that handles
the bulk of this work. The basic flow is: a) Lines 129-144
scan our key contact inputs for what we define as hits, in
this case, a logic 0; b) Lines 147-168 build and send the
HID formatted message and turn on the LED for each of
our pressed keys; c) Line 170 saves some state information
that helps us ignore key presses; and d) Lines 173-174 add
in a little bit of delay so that our keys don’t send
information too quickly.
There is nothing fancy in any of this, and I’m sure
there are many better and different ways to accomplish
the same thing. There are only two specific things worth
commenting on. The first is that the HID message packet
used in this instance is eight bytes long and the key code
is placed into the fourth byte (tx_msg[ 3]). If you look at the
function header comment, the detail of the data packet is
described. Again, I didn’t do anything fancy here, although
we could have been more efficient.
The second is Line 160 shows an if statement that
compares the previous key hit to the present key hit. If it is
November 2013 31
■ FIGURE 6. The firmware function that
processes keyboard hits. ■ FIGURE 5. Main function of the firmware.