Keypad Algorithm
Table of Contents
Issues
Debounce
Auto-repeat (typematic)
Composite Key
Shift keys
Click Duration
Short Click
Long Click
Multi-Clicks
Single Click
Double Clicks
Triple Clicks
…
Detection
1-to-1 GPIO Mapping (for keys <= 4)
Key Scanning (for keys > 4)
Encode
From key detection to key representation
- Set — bitmap
- Code — ID
- Virtual key
Time Constants
Debounce:
typical: 20ms ~ 50ms
max: 100ms
Short Click:
< 500ms (the time from press to release)
Long Press:
> 500ms (the press time)
Interval between clicks:
time between two clicks: < 700ms
A simple 4-stage encoder
Features:
- Click (short, single), long press, and auto-repeat are supported
- Composite Key is not supported,
- although it is easy to be added on.
- Prefers the key detection of 1-to-1 GPIO mapping
- although to adopt matrix scanning is possible.
- Python-like pseudo code is used
- Easy to be implemented with C-like bit-wise operations
Stages:
S_Initial, S_Debounce, S_PressLong, S_Typematic = range(4)
Key Vectors
real
Generated by Key_real()
Key_real() — to get real press from GPIOs
press — debounced press
pressAcc
longAcc
repeatAcc
click — press (debounced) and free
clear after client's reading via Key_clicked()
click = set() # click.clear()
every debounce cycle (20~50 ms)
real = Key_real() if stage == S_Initial: press = set() # press.clear() pressAcc = real if len(pressAcc) != 0: state = S_Debounce else: # stage >= S_Debounce pressAcc &= real press |= pressAcc free = ~pressAcc if len(pressAcc) == 0: # NOTE: go back to S_Initial only when all keys are released state = S_Initial if stage != S_Typematic: click |= press & free
long — long press
clear after client's reading via Key_long()
long = set() # long.clear()
every long press check cycle (10~100 debounce cycles)
if stage == S_Debounce: longAcc = pressAcc.copy() if longAcc != 0: stage = S_PressLong
repeat — auto repeat (typematic) after a long press
clear after client's reading via Key_repeated()
repeat = set() # repeat.clear()
every repeat cycle (2~ debounce cycles)
if stage == S_PressLong: repeatAcc = pressAcc & longAcc if repeatAcc != 0: stage = S_Typematic elif stage == S_Typematic: repeatAcc &= pressAcc & longAcc repeat |= repeatAcc
Prototype of public functions (in C style)
void Key_reset() void Key_update() Key Key_clicked() Key Key_long() Key Key_repeated()
Key matrix scanning
Prototype of public functions (in C style):
void init() MS getKeyDownTime() Key getKey() void flush() bool hit()
Suggested Readings
《匠人手记》11《按键漫谈》
《匠人手记》12《单个按键多次击键的检测方法》
《匠人手记》21《多种击键类型的处理流程图》
《一个按键的多次击键组合判别技巧》大话篇
《多个按键的连按处理技巧》大话篇
5个IO口扫描25个按键的解决方法





