Mechanical switches often don't have a clean single transition between pressed and unpressed states.
In an ideal world, when you press a switch, you would expect the digital pin to see something like this: (X axis showing time
voltage +----------------------
^ |
| |
| ------------------+
----> time
However in the real world you will actually see contact bounce, which will look like multiple 1->0 and 0->1 transitions, until the value finally settles.
+-+ +--+ +-------------
| | | | |
| | | | |
+-----------------+ +-+ +-+
The time it takes for the switch to settle might vary with switch type, age, and even pressing technique.
If the device chooses not to mitigate contact bounce, then often actions that happen when the switch is pressed are repeated multiple times.
There are many ways to handle contact bounce ("Debouncing"). Some include employing additional hardware, for example an RC filter, while there are various ways to do debouncing in software too, often called debounce algorithms. This page discusses software debouncing methods available in QMK.
While technically not considered contact bounce/contact chatter, some switch technologies are susceptible to noise, meaning, while the key is not changing state, sometimes short random 0->1 or 1->0 transitions might be read by the digital circuit, for example:
+-+
| |
| |
+-----------------+ +--------------------
Many debounce methods (but not all) will also make the device resistant to noise. If you are working with a technology that is susceptible to noise, you must choose a debounce method that will also mitigate noise for you.
Unit of time: Timestamp (milliseconds) vs Cycles (scans)
config.h
macro.Symmetric vs Asymmetric
sym_*
asym_*
followed by details of the type of algorithm in use, in order, for key-down and then key-upEager vs Defer
sym_eager_*
asym_eager_*_*
: key-down is using eager algorithmasym_*_eager_*
: key-up is using eager algorithmsym_defer_*
asym_defer_*_*
: key-down is using defer algorithmasym_*_defer_*
: key-up is using defer algorithmGlobal vs Per-Key vs Per-Row
*_g
*_pk
*_pr
QMK supports multiple debounce algorithms through its debounce API.
The logic for which debounce method called is below. It checks various defines that you have set in rules.mk
DEBOUNCE_DIR:= $(QUANTUM_DIR)/debounce
DEBOUNCE_TYPE?= sym_defer_g
ifneq ($(strip $(DEBOUNCE_TYPE)), custom)
QUANTUM_SRC += $(DEBOUNCE_DIR)/$(strip $(DEBOUNCE_TYPE)).c
endif
DEBOUNCE_TYPE | Description | What else is needed |
---|---|---|
Not defined | Use the default algorithm, currently sym_defer_g | Nothing |
custom | Use your own debounce code | SRC += debounce.c add your own debounce.c and implement necessary functions |
Anything Else | Use another algorithm from quantum/debounce/* | Nothing |
Regarding split keyboards: The debounce code is compatible with split keyboards.
Keyboards may select one of the already implemented debounce methods, by adding to rules.mk
the following line:
DEBOUNCE_TYPE = <name of algorithm>
Where name of algorithm is one of:
sym_defer_g
- debouncing per keyboard. On any state change, a global timer is set. When DEBOUNCE
milliseconds of no changes has occurred, all input changes are pushed.
sym_eager_pr
- debouncing per row. On any state change, response is immediate, followed by locking the row DEBOUNCE
milliseconds of no further input for that row.
For use in keyboards where refreshing NUM_KEYS
8-bit counters is computationally expensive / low scan rate, and fingers usually only hit one row at a time. This could be
appropriate for the ErgoDox models; the matrix is rotated 90°, and hence its "rows" are really columns, and each finger only hits a single "row" at a time in normal use.sym_eager_pk
- debouncing per key. On any state change, response is immediate, followed by DEBOUNCE
milliseconds of no further input for that keysym_defer_pk
- debouncing per key. On any state change, a per-key timer is set. When DEBOUNCE
milliseconds of no changes have occurred on that key, the key status change is pushed.sym_defer_pr
sym_eager_g
asym_eager_defer_pk
You have the option to implement you own debouncing algorithm. To do this:
DEBOUNCE_TYPE = custom
in rules.mk
.SRC += debounce.c
in rules.mk
debounce.c
. Look at current implementations in quantum/debounce
for examples.quantum/debounce
The following old names for existing algorithms will continue to be supported, however it is recommended to use the new names instead.