diff options
| author | Purdea Andrei <andrei@purdea.ro> | 2020-09-06 23:13:49 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-09-06 13:13:49 -0700 |
| commit | f7ccbfcea88e127319a4665a6c8ca67883854030 (patch) | |
| tree | 25a2d9f5c7b9b95795d097c9514928af90d5080a | |
| parent | 8ac9940a76f09d4a47be342fc123306ecbfb27f3 (diff) | |
| download | qmk_firmware-f7ccbfcea88e127319a4665a6c8ca67883854030.tar.gz qmk_firmware-f7ccbfcea88e127319a4665a6c8ca67883854030.zip | |
quantum/debounce: rename debouncing algorithms (#9564)
* quantum/debounce: rename debouncing algorithms according to Issue 8763
This is the second attempt at implementation, with no ts_ and cy_ prefixes, since those will be implemented with macros.
* Debouncing documentation: Refactor, add some generic info, and merge into a single document
| -rw-r--r-- | common_features.mk | 13 | ||||
| -rw-r--r-- | docs/feature_debounce_type.md | 146 | ||||
| -rw-r--r-- | quantum/debounce/readme.md | 28 | ||||
| -rw-r--r-- | quantum/debounce/sym_defer_g.c (renamed from quantum/debounce/sym_g.c) | 0 | ||||
| -rw-r--r-- | quantum/debounce/sym_defer_pk.c (renamed from quantum/debounce/sym_pk.c) | 0 | ||||
| -rw-r--r-- | quantum/debounce/sym_eager_pk.c (renamed from quantum/debounce/eager_pk.c) | 0 | ||||
| -rw-r--r-- | quantum/debounce/sym_eager_pr.c (renamed from quantum/debounce/eager_pr.c) | 0 |
7 files changed, 139 insertions, 48 deletions
diff --git a/common_features.mk b/common_features.mk index 1f110d081..ed6908f4b 100644 --- a/common_features.mk +++ b/common_features.mk | |||
| @@ -397,9 +397,20 @@ ifneq ($(strip $(CUSTOM_MATRIX)), yes) | |||
| 397 | endif | 397 | endif |
| 398 | endif | 398 | endif |
| 399 | 399 | ||
| 400 | # Support for translating old names to new names: | ||
| 401 | ifeq ($(strip $(DEBOUNCE_TYPE)),sym_g) | ||
| 402 | DEBOUNCE_TYPE:=sym_defer_g | ||
| 403 | else ifeq ($(strip $(DEBOUNCE_TYPE)),eager_pk) | ||
| 404 | DEBOUNCE_TYPE:=sym_eager_pk | ||
| 405 | else ifeq ($(strip $(DEBOUNCE_TYPE)),sym_pk) | ||
| 406 | DEBOUNCE_TYPE:=sym_defer_pk | ||
| 407 | else ifeq ($(strip $(DEBOUNCE_TYPE)),eager_pr) | ||
| 408 | DEBOUNCE_TYPE:=sym_eager_pr | ||
| 409 | endif | ||
| 410 | |||
| 400 | DEBOUNCE_DIR:= $(QUANTUM_DIR)/debounce | 411 | DEBOUNCE_DIR:= $(QUANTUM_DIR)/debounce |
| 401 | # Debounce Modules. Set DEBOUNCE_TYPE=custom if including one manually. | 412 | # Debounce Modules. Set DEBOUNCE_TYPE=custom if including one manually. |
| 402 | DEBOUNCE_TYPE?= sym_g | 413 | DEBOUNCE_TYPE?= sym_defer_g |
| 403 | ifneq ($(strip $(DEBOUNCE_TYPE)), custom) | 414 | ifneq ($(strip $(DEBOUNCE_TYPE)), custom) |
| 404 | QUANTUM_SRC += $(DEBOUNCE_DIR)/$(strip $(DEBOUNCE_TYPE)).c | 415 | QUANTUM_SRC += $(DEBOUNCE_DIR)/$(strip $(DEBOUNCE_TYPE)).c |
| 405 | endif | 416 | endif |
diff --git a/docs/feature_debounce_type.md b/docs/feature_debounce_type.md index 65b4ea1e5..83ebafe60 100644 --- a/docs/feature_debounce_type.md +++ b/docs/feature_debounce_type.md | |||
| @@ -1,43 +1,151 @@ | |||
| 1 | # Debounce algorithm | 1 | # Contact bounce / contact chatter |
| 2 | 2 | ||
| 3 | QMK supports multiple debounce algorithms through its debounce API. | 3 | Mechanical switches often don't have a clean single transition between pressed and unpressed states. |
| 4 | |||
| 5 | In an ideal world, when you press a switch, you would expect the digital pin to see something like this: | ||
| 6 | (X axis showing time | ||
| 7 | ``` | ||
| 8 | voltage +---------------------- | ||
| 9 | ^ | | ||
| 10 | | | | ||
| 11 | | ------------------+ | ||
| 12 | ----> time | ||
| 13 | ``` | ||
| 14 | |||
| 15 | However in the real world you will actually see contact bounce, which will look like multiple 1->0 and 0->1 transitions, | ||
| 16 | until the value finally settles. | ||
| 17 | ``` | ||
| 18 | +-+ +--+ +------------- | ||
| 19 | | | | | | | ||
| 20 | | | | | | | ||
| 21 | +-----------------+ +-+ +-+ | ||
| 22 | ``` | ||
| 23 | The time it takes for the switch to settle might vary with switch type, age, and even pressing technique. | ||
| 24 | |||
| 25 | If the device chooses not to mitigate contact bounce, then often actions that happen when the switch is pressed are repeated | ||
| 26 | multiple times. | ||
| 27 | |||
| 28 | There are many ways to handle contact bounce ("Debouncing"). Some include employing additional hardware, for example an RC filter, | ||
| 29 | while there are various ways to do debouncing in software too, often called debounce algorithms. This page discusses software | ||
| 30 | debouncing methods available in QMK. | ||
| 31 | |||
| 32 | While technically not considered contact bounce/contact chatter, some switch technologies are susceptible to noise, meaning, | ||
| 33 | 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: | ||
| 34 | ``` | ||
| 35 | +-+ | ||
| 36 | | | | ||
| 37 | | | | ||
| 38 | +-----------------+ +-------------------- | ||
| 39 | ``` | ||
| 40 | |||
| 41 | Many debounce methods (but not all) will also make the device resistant to noise. If you are working with a technology that is | ||
| 42 | susceptible to noise, you must choose a debounce method that will also mitigate noise for you. | ||
| 43 | |||
| 44 | ## Types of debounce algorithms | ||
| 4 | 45 | ||
| 5 | The logic for which debounce method called is below. It checks various defines that you have set in rules.mk | 46 | 1) Unit of time: Timestamp (milliseconds) vs Cycles (scans) |
| 47 | * Debounce algorithms often have a 'debounce time' parameter, that specifies the maximum settling time of the switch contacts. | ||
| 48 | This time might be measured in various units: | ||
| 49 | * Cycles-based debouncing waits n cycles (scans), decreasing count by one each matrix_scan | ||
| 50 | * Timestamp-based debouncing stores the millisecond timestamp a change occurred, and does substraction to figure out time elapsed. | ||
| 51 | * Timestamp-based debouncing is usually superior, especially in the case of noise-resistant devices because settling times of physical | ||
| 52 | switches is specified in units of time, and should not depend on the matrix scan-rate of the keyboard. | ||
| 53 | * Cycles-based debouncing is sometimes considered inferior, because the settling time that it is able to compensate for depends on the | ||
| 54 | performance of the matrix scanning code. If you use cycles-based debouncing, and you significantly improve the performance of your scanning | ||
| 55 | code, you might end up with less effective debouncing. A situation in which cycles-based debouncing might be preferable is when | ||
| 56 | noise is present, and the scanning algorithm is slow, or variable speed. Even if your debounce algorithm is fundamentally noise-resistant, | ||
| 57 | if the scanning is slow, and you are using a timestamp-based algorithm, you might end up making a debouncing decision based on only two | ||
| 58 | sampled values, which will limit the noise-resistance of the algorithm. | ||
| 59 | * Currently all built-in debounce algorithms support timestamp-based debouncing only. In the future we might | ||
| 60 | implement cycles-based debouncing, and it will be selectable via a ```config.h``` macro. | ||
| 61 | |||
| 62 | 2) Symmetric vs Asymmetric | ||
| 63 | * Symmetric - apply the same debouncing algorithm, to both key-up and key-down events. | ||
| 64 | * Recommended naming convention: ```sym_*``` | ||
| 65 | * Asymmetric - apply different debouncing algorithms to key-down and key-up events. E.g. Eager key-down, Defer key-up. | ||
| 66 | * Recommended naming convention: ```asym_*``` followed by details of the type of algorithm in use, in order, for key-down and then key-up | ||
| 67 | |||
| 68 | 3) Eager vs Defer | ||
| 69 | * Eager - any key change is reported immediately. All further inputs for DEBOUNCE ms are ignored. | ||
| 70 | * Eager algorithms are not noise-resistant. | ||
| 71 | * Recommended naming conventions: | ||
| 72 | * ```sym_eager_*``` | ||
| 73 | * ```asym_eager_*_*```: key-down is using eager algorithm | ||
| 74 | * ```asym_*_eager_*```: key-up is using eager algorithm | ||
| 75 | * Defer - wait for no changes for DEBOUNCE ms before reporting change. | ||
| 76 | * Defer algorithms are noise-resistant | ||
| 77 | * Recommended naming conventions: | ||
| 78 | * ```sym_defer_*``` | ||
| 79 | * ```asym_defer_*_*```: key-down is using eager algorithm | ||
| 80 | * ```asym_*_defer_*```: key-up is using eager algorithm | ||
| 81 | |||
| 82 | 4) Global vs Per-Key vs Per-Row | ||
| 83 | * Global - one timer for all keys. Any key change state affects global timer | ||
| 84 | * Recommended naming convention: ```*_g``` | ||
| 85 | * Per-key - one timer per key | ||
| 86 | * Recommended naming convention: ```*_pk``` | ||
| 87 | * Per-row - one timer per row | ||
| 88 | * Recommended naming convention: ```*_pr``` | ||
| 89 | * Per-key and per-row algorithms consume more resources (in terms of performance, | ||
| 90 | and ram usage), but fast typists might prefer them over global. | ||
| 91 | |||
| 92 | ## Debounce algorithms supported by QMK | ||
| 93 | |||
| 94 | QMK supports multiple debounce algorithms through its debounce API. | ||
| 95 | The logic for which debounce method called is below. It checks various defines that you have set in ```rules.mk``` | ||
| 6 | 96 | ||
| 7 | ``` | 97 | ``` |
| 8 | DEBOUNCE_DIR:= $(QUANTUM_DIR)/debounce | 98 | DEBOUNCE_DIR:= $(QUANTUM_DIR)/debounce |
| 9 | DEBOUNCE_TYPE?= sym_g | 99 | DEBOUNCE_TYPE?= sym_defer_g |
| 10 | ifneq ($(strip $(DEBOUNCE_TYPE)), custom) | 100 | ifneq ($(strip $(DEBOUNCE_TYPE)), custom) |
| 11 | QUANTUM_SRC += $(DEBOUNCE_DIR)/$(strip $(DEBOUNCE_TYPE)).c | 101 | QUANTUM_SRC += $(DEBOUNCE_DIR)/$(strip $(DEBOUNCE_TYPE)).c |
| 12 | endif | 102 | endif |
| 13 | ``` | 103 | ``` |
| 14 | 104 | ||
| 15 | # Debounce selection | 105 | ### Debounce selection |
| 16 | 106 | ||
| 17 | | DEBOUNCE_TYPE | Description | What else is needed | | 107 | | DEBOUNCE_TYPE | Description | What else is needed | |
| 18 | | ------------- | --------------------------------------------------- | ----------------------------- | | 108 | | ------------- | --------------------------------------------------- | ----------------------------- | |
| 19 | | Not defined | Use the default algorithm, currently sym_g | Nothing | | 109 | | Not defined | Use the default algorithm, currently sym_defer_g | Nothing | |
| 20 | | custom | Use your own debounce code | ```SRC += debounce.c``` add your own debounce.c and implement necessary functions | | 110 | | custom | Use your own debounce code | ```SRC += debounce.c``` add your own debounce.c and implement necessary functions | |
| 21 | | anything_else | Use another algorithm from quantum/debounce/* | Nothing | | 111 | | Anything Else | Use another algorithm from quantum/debounce/* | Nothing | |
| 22 | 112 | ||
| 23 | **Regarding split keyboards**: | 113 | **Regarding split keyboards**: |
| 24 | The debounce code is compatible with split keyboards. | 114 | The debounce code is compatible with split keyboards. |
| 25 | 115 | ||
| 26 | # Use your own debouncing code | 116 | ### Selecting an included debouncing method |
| 27 | * Set ```DEBOUNCE_TYPE = custom```. | 117 | Keyboards may select one of the already implemented debounce methods, by adding to ```rules.mk``` the following line: |
| 28 | * Add ```SRC += debounce.c``` | 118 | ``` |
| 119 | DEBOUNCE_TYPE = <name of algorithm> | ||
| 120 | ``` | ||
| 121 | Where name of algorithm is one of: | ||
| 122 | * ```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. | ||
| 123 | * This is the current default algorithm. This is the highest performance algorithm with lowest memory usage, and it's also noise-resistant. | ||
| 124 | * ```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. | ||
| 125 | 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 | ||
| 126 | 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. | ||
| 127 | * ```sym_eager_pk``` - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key | ||
| 128 | * ```sym_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. | ||
| 129 | |||
| 130 | ### A couple algorithms that could be implemented in the future: | ||
| 131 | * ```sym_defer_pr``` | ||
| 132 | * ```sym_eager_g``` | ||
| 133 | * ```asym_eager_defer_pk``` | ||
| 134 | |||
| 135 | ### Use your own debouncing code | ||
| 136 | You have the option to implement you own debouncing algorithm. To do this: | ||
| 137 | * Set ```DEBOUNCE_TYPE = custom``` in ```rules.mk```. | ||
| 138 | * Add ```SRC += debounce.c``` in ```rules.mk``` | ||
| 29 | * Add your own ```debounce.c```. Look at current implementations in ```quantum/debounce``` for examples. | 139 | * Add your own ```debounce.c```. Look at current implementations in ```quantum/debounce``` for examples. |
| 30 | * Debouncing occurs after every raw matrix scan. | 140 | * Debouncing occurs after every raw matrix scan. |
| 31 | * Use num_rows rather than MATRIX_ROWS, so that split keyboards are supported correctly. | 141 | * Use num_rows rather than MATRIX_ROWS, so that split keyboards are supported correctly. |
| 142 | * If the algorithm might be applicable to other keyboards, please consider adding it to ```quantum/debounce``` | ||
| 32 | 143 | ||
| 33 | # Changing between included debouncing methods | 144 | ### Old names |
| 34 | You can either use your own code, by including your own debounce.c, or switch to another included one. | 145 | The following old names for existing algorithms will continue to be supported, however it is recommended to use the new names instead. |
| 35 | Included debounce methods are: | ||
| 36 | * 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. | ||
| 37 | 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 | ||
| 38 | 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. | ||
| 39 | * eager_pk - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key | ||
| 40 | * sym_g - debouncing per keyboard. On any state change, a global timer is set. When ```DEBOUNCE``` milliseconds of no changes has occured, all input changes are pushed. | ||
| 41 | * sym_pk - debouncing per key. On any state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occured on that key, the key status change is pushed. | ||
| 42 | 146 | ||
| 147 | * sym_g - old name for sym_defer_g | ||
| 148 | * eager_pk - old name for sym_eager_pk | ||
| 149 | * sym_pk - old name for sym_defer_pk | ||
| 150 | * eager_pr - old name for sym_eager_pr | ||
| 43 | 151 | ||
diff --git a/quantum/debounce/readme.md b/quantum/debounce/readme.md deleted file mode 100644 index f77f78c76..000000000 --- a/quantum/debounce/readme.md +++ /dev/null | |||
| @@ -1,28 +0,0 @@ | |||
| 1 | Debounce algorithms belong in this folder. | ||
| 2 | Here are a few ideas | ||
| 3 | |||
| 4 | 1) Global vs Per-Key vs Per-Row | ||
| 5 | * Global - one timer for all keys. Any key change state affects global timer | ||
| 6 | * Per key - one timer per key | ||
| 7 | * Per row - one timer per row | ||
| 8 | |||
| 9 | 2) Eager vs symmetric vs asymmetric | ||
| 10 | * Eager - any key change is reported immediately. All further inputs for DEBOUNCE ms are ignored. | ||
| 11 | * Symmetric - wait for no changes for DEBOUNCE ms before reporting change | ||
| 12 | * Asymmetric - wait for different times depending on key-down/key-up. E.g. Eager key-down, DEBOUNCE ms key up. | ||
| 13 | |||
| 14 | 3) Timestamp vs cycles | ||
| 15 | * old old old code waits n cycles, decreasing count by one each matrix_scan | ||
| 16 | * newer code stores the millisecond the change occurred, and does subraction to figure out time elapsed. | ||
| 17 | * Timestamps are superior, i don't think cycles will ever be used again once upgraded. | ||
| 18 | |||
| 19 | The default algorithm is symmetric and global. | ||
| 20 | Here are a few that could be implemented: | ||
| 21 | |||
| 22 | sym_g.c | ||
| 23 | sym_pk.c | ||
| 24 | sym_pr.c | ||
| 25 | sym_pr_cycles.c | ||
| 26 | eager_g.c | ||
| 27 | eager_pk.c | ||
| 28 | eager_pr.c //could be used in ergo-dox! | ||
diff --git a/quantum/debounce/sym_g.c b/quantum/debounce/sym_defer_g.c index 3ed9055d2..3ed9055d2 100644 --- a/quantum/debounce/sym_g.c +++ b/quantum/debounce/sym_defer_g.c | |||
diff --git a/quantum/debounce/sym_pk.c b/quantum/debounce/sym_defer_pk.c index f404cf9c4..f404cf9c4 100644 --- a/quantum/debounce/sym_pk.c +++ b/quantum/debounce/sym_defer_pk.c | |||
diff --git a/quantum/debounce/eager_pk.c b/quantum/debounce/sym_eager_pk.c index 93a40ad44..93a40ad44 100644 --- a/quantum/debounce/eager_pk.c +++ b/quantum/debounce/sym_eager_pk.c | |||
diff --git a/quantum/debounce/eager_pr.c b/quantum/debounce/sym_eager_pr.c index d12931fdd..d12931fdd 100644 --- a/quantum/debounce/eager_pr.c +++ b/quantum/debounce/sym_eager_pr.c | |||
