Close

Keyboard Basics - Debouncing and Repeating

A project log for Thumb Keyboard

Experimental thumb keyboard, suitable for a hand held device

david-boucherDavid Boucher 03/12/2019 at 22:271 Comment

This is the middle bit of the keyboard reading code. At this point we have a map of which keys are pressed and we need to start turning that into key events. The events that we need are:

In order to determine whether a key has been pressed or released we need to keep a record of the state of the keyboard on the last scan and check for state changes. This is simple enough, but the repeat event requires a little more work. For key repeat, we need to know how long a key has been held down, so we need to do a little bit of timing. There are actually two time periods associated with key repeat: the first is how long a key must be held down to produce the first repeat event and the second is how much additional time it must be held down for each additional repeat event. The first of these intervals is generally longer than the second.

The way that I've handled this is to have the scan routine run at regular intervals. I could do this on a timer interrupt but for simplicity I'm just using the millis() function to control a delay between scans. Then I maintain a counter of how many scans a key has been held down for.

I can also use this for key debouncing. Bouncing is when a circuit is made and broken multiple times as a switch is being pressed or released, which in a keyboard would cause spurious key press and release events. I've not actually had a problem with this unless I scan the keyboard continuously with no delay between scans, but I've included code to deal with it anyway just in case.

Putting all these things together, this is how I'm handling this part of the process. Firstly, though, I need a few constants:

Then the code does the following:

  1. Scan the keyboard every KEY_SCAN_INTERVAL milliseconds.
  2. For every scan that a key is held down, increase its scan counter by 1.
  3. When a key has been held down for KEY_DEBOUNCE scans, generate a key press event for it.
  4. When a key has been held down for KEY_DEBOUNCE + KEY_FIRST_REPEAT scans, generate a key repeat event.
  5. When a key has been held down for KEY_DEBOUNCE + KEY_FIRST_REPEAT + KEY_NEXT_REPEAT scans, generate a key repeat event and set the scan count back to KEY_DEBOUNCE + KEY_FIRST_REPEAT.
  6. When a key is released, if the scan count is KEY_DEBOUNCE or more, generate a key release event. Set the scan count back to 0 whether or not a key release event was generated.

Now we have a stream of key events but we only have the key numbers when what we really need to know is what that key represents. That needs key mapping which will be the subject of the next log.

Discussions

Ken Yap wrote 03/13/2019 at 22:57 point

You might be interested in how this can be made more readable with threads: https://hackaday.io/project/162267-8051-tuner/log/157780-using-protothreads-on-mcus

  Are you sure? yes | no