From c7c4937eef9cb34b73e765390b842282ad9f0544 Mon Sep 17 00:00:00 2001 From: James Churchill Date: Tue, 5 Mar 2019 01:44:46 +1000 Subject: Clean up debounce a bit (#5255) --- common_features.mk | 14 +--- docs/config_options.md | 4 +- docs/feature_debounce_type.md | 31 ++++----- docs/getting_started_make_guide.md | 4 +- quantum/debounce/debounce_eager_pk.c | 121 ----------------------------------- quantum/debounce/debounce_sym_g.c | 57 ----------------- quantum/debounce/eager_pk.c | 121 +++++++++++++++++++++++++++++++++++ quantum/debounce/readme.md | 18 +++--- quantum/debounce/sym_g.c | 57 +++++++++++++++++ show_options.mk | 2 +- 10 files changed, 207 insertions(+), 222 deletions(-) delete mode 100644 quantum/debounce/debounce_eager_pk.c delete mode 100644 quantum/debounce/debounce_sym_g.c create mode 100644 quantum/debounce/eager_pk.c create mode 100644 quantum/debounce/sym_g.c diff --git a/common_features.mk b/common_features.mk index f5bef3d5d..20c38ae82 100644 --- a/common_features.mk +++ b/common_features.mk @@ -298,19 +298,11 @@ ifneq ($(strip $(CUSTOM_MATRIX)), yes) endif DEBOUNCE_DIR:= $(QUANTUM_DIR)/debounce -# Debounce Modules. If implemented in matrix.c, don't use these. +# Debounce Modules. Set DEBOUNCE_TYPE=custom if including one manually. DEBOUNCE_TYPE?= sym_g -VALID_DEBOUNCE_TYPES := sym_g eager_pk custom -ifeq ($(filter $(DEBOUNCE_TYPE),$(VALID_DEBOUNCE_TYPES)),) - $(error DEBOUNCE_TYPE="$(DEBOUNCE_TYPE)" is not a valid debounce algorithm) +ifneq ($(strip $(DEBOUNCE_TYPE)), custom) + QUANTUM_SRC += $(DEBOUNCE_DIR)/$(strip $(DEBOUNCE_TYPE)).c endif -ifeq ($(strip $(DEBOUNCE_TYPE)), sym_g) - QUANTUM_SRC += $(DEBOUNCE_DIR)/debounce_sym_g.c -else ifeq ($(strip $(DEBOUNCE_TYPE)), eager_pk) - QUANTUM_SRC += $(DEBOUNCE_DIR)/debounce_eager_pk.c -endif - - ifeq ($(strip $(SPLIT_KEYBOARD)), yes) OPT_DEFS += -DSPLIT_KEYBOARD diff --git a/docs/config_options.md b/docs/config_options.md index 8fa6e944f..336feee8f 100644 --- a/docs/config_options.md +++ b/docs/config_options.md @@ -307,8 +307,8 @@ Use these to enable or disable building certain features. The more you have enab * Enables split keyboard support (dual MCU like the let's split and bakingpy's boards) and includes all necessary files located at quantum/split_common * `CUSTOM_MATRIX` * Allows replacing the standard matrix scanning routine with a custom one. -* `CUSTOM_DEBOUNCE` - * Allows replacing the standard key debouncing routine with a custom one. +* `DEBOUNCE_TYPE` + * Allows replacing the standard key debouncing routine with an alternative or custom one. * `WAIT_FOR_USB` * Forces the keyboard to wait for a USB connection to be established before it starts up * `NO_USB_STARTUP_CHECK` diff --git a/docs/feature_debounce_type.md b/docs/feature_debounce_type.md index 82b3d7de1..5d4343f08 100644 --- a/docs/feature_debounce_type.md +++ b/docs/feature_debounce_type.md @@ -2,45 +2,38 @@ QMK supports multiple debounce algorithms through its debounce API. -The underlying debounce algorithm is determined by which matrix.c file you are using. - 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_g -VALID_DEBOUNCE_TYPES := sym_g eager_pk custom -ifeq ($(filter $(DEBOUNCE_TYPE),$(VALID_DEBOUNCE_TYPES)),) - $(error DEBOUNCE_TYPE="$(DEBOUNCE_TYPE)" is not a valid debounce algorithm) -endif -ifeq ($(strip $(DEBOUNCE_TYPE)), sym_g) - QUANTUM_SRC += $(DEBOUNCE_DIR)/debounce_sym_g.c -else ifeq ($(strip $(DEBOUNCE_TYPE)), eager_pk) - QUANTUM_SRC += $(DEBOUNCE_DIR)/debounce_eager_pk.c +ifneq ($(strip $(DEBOUNCE_TYPE)), custom) + QUANTUM_SRC += $(DEBOUNCE_DIR)/$(strip $(DEBOUNCE_TYPE)).c endif ``` # Debounce selection -| DEBOUNCE_ALGO | Description | What to do | -| ------------- | --------------------------------------------------- | ----------------------------- | -| Not defined | You are using the included matrix.c and debounce.c | Nothing. Debounce_sym_g will be compiled, and used if necessary | -| custom | Use your own debounce.c | ```SRC += debounce.c``` add your own debounce.c and implement necessary functions | -| sym_g / eager_pk | You are using the included matrix.c and debounce.c | Use an alternative debounce algorithm | +| DEBOUNCE_TYPE | Description | What else is needed | +| ------------- | --------------------------------------------------- | ----------------------------- | +| Not defined | Use the default algorithm, currently sym_g | Nothing | +| custom | Use your own debounce.c | ```SRC += debounce.c``` add your own debounce.c and implement necessary functions | +| anything_else | Use another algorithm from quantum/debounce/* | Nothing | -**Regarding split keyboards**: +**Regarding split keyboards**: The debounce code is compatible with split keyboards. # Use your own debouncing code * Set ```DEBOUNCE_TYPE = custom ```. * Add ```SRC += debounce.c``` -* Add your own ```debounce.c```. Look at included ```debounce_sym_g.c```s for sample implementations. +* Add your own ```debounce.c```. Look at current implementations in ```quantum/debounce``` for examples. * Debouncing occurs after every raw matrix scan. * Use num_rows rather than MATRIX_ROWS, so that split keyboards are supported correctly. # Changing between included debouncing methods You can either use your own code, by including your own debounce.c, or switch to another included one. Included debounce methods are: -* debounce_eager_pk - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE_DELAY``` millseconds of no further input for that key -* debounce_sym_g - debouncing per keyboard. On any state change, a global timer is set. When ```DEBOUNCE_DELAY``` milliseconds of no changes has occured, all input changes are pushed. +* eager_pk - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE_DELAY``` millseconds of no further input for that key +* sym_g - debouncing per keyboard. On any state change, a global timer is set. When ```DEBOUNCE_DELAY``` milliseconds of no changes has occured, all input changes are pushed. diff --git a/docs/getting_started_make_guide.md b/docs/getting_started_make_guide.md index bb7e1e7e3..75eafd42c 100644 --- a/docs/getting_started_make_guide.md +++ b/docs/getting_started_make_guide.md @@ -143,9 +143,9 @@ As there is no standard split communication driver for ARM-based split keyboards Lets you replace the default matrix scanning routine with your own code. You will need to provide your own implementations of matrix_init() and matrix_scan(). -`CUSTOM_DEBOUNCE` +`DEBOUNCE_TYPE` -Lets you replace the default key debouncing routine with your own code. You will need to provide your own implementation of debounce(). +Lets you replace the default key debouncing routine with an alternative one. If `custom` you will need to provide your own implementation. ## Customizing Makefile Options on a Per-Keymap Basis diff --git a/quantum/debounce/debounce_eager_pk.c b/quantum/debounce/debounce_eager_pk.c deleted file mode 100644 index b8ad09cee..000000000 --- a/quantum/debounce/debounce_eager_pk.c +++ /dev/null @@ -1,121 +0,0 @@ -/* -Copyright 2017 Alex Ong -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -/* -Basic per-key algorithm. Uses an 8-bit counter per key. -After pressing a key, it immediately changes state, and sets a counter. -No further inputs are accepted until DEBOUNCE milliseconds have occurred. -*/ - -#include "matrix.h" -#include "timer.h" -#include "quantum.h" -#include - -#ifndef DEBOUNCE - #define DEBOUNCE 5 -#endif - - -#if (MATRIX_COLS <= 8) -# define ROW_SHIFTER ((uint8_t)1) -#elif (MATRIX_COLS <= 16) -# define ROW_SHIFTER ((uint16_t)1) -#elif (MATRIX_COLS <= 32) -# define ROW_SHIFTER ((uint32_t)1) -#endif - - - -#define debounce_counter_t uint8_t - -static debounce_counter_t *debounce_counters; - -#define DEBOUNCE_ELAPSED 251 -#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1) - -void update_debounce_counters(uint8_t num_rows, uint8_t current_time); -void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); - -//we use num_rows rather than MATRIX_ROWS to support split keyboards -void debounce_init(uint8_t num_rows) -{ - debounce_counters = (debounce_counter_t*)malloc(num_rows*MATRIX_COLS * sizeof(debounce_counter_t)); - int i = 0; - for (uint8_t r = 0; r < num_rows; r++) - { - for (uint8_t c = 0; c < MATRIX_COLS; c++) - { - debounce_counters[i++] = DEBOUNCE_ELAPSED; - } - } -} - -void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) -{ - uint8_t current_time = timer_read() % MAX_DEBOUNCE; - update_debounce_counters(num_rows, current_time); - transfer_matrix_values(raw, cooked, num_rows, current_time); -} - -//If the current time is > debounce counter, set the counter to enable input. -void update_debounce_counters(uint8_t num_rows, uint8_t current_time) -{ - debounce_counter_t *debounce_pointer = debounce_counters; - for (uint8_t row = 0; row < num_rows; row++) - { - for (uint8_t col = 0; col < MATRIX_COLS; col++) - { - if (*debounce_pointer != DEBOUNCE_ELAPSED) - { - if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { - *debounce_pointer = DEBOUNCE_ELAPSED; - } - } - debounce_pointer++; - } - } -} - -// upload from raw_matrix to final matrix; -void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) -{ - debounce_counter_t *debounce_pointer = debounce_counters; - for (uint8_t row = 0; row < num_rows; row++) - { - matrix_row_t existing_row = cooked[row]; - matrix_row_t raw_row = raw[row]; - - for (uint8_t col = 0; col < MATRIX_COLS; col++) - { - matrix_row_t col_mask = (ROW_SHIFTER << col); - bool final_value = raw_row & col_mask; - bool existing_value = existing_row & col_mask; - if (*debounce_pointer == DEBOUNCE_ELAPSED && - (existing_value != final_value)) - { - *debounce_pointer = current_time; - existing_row ^= col_mask; //flip the bit. - } - debounce_pointer++; - } - cooked[row] = existing_row; - } -} - -bool debounce_active(void) -{ - return true; -} - diff --git a/quantum/debounce/debounce_sym_g.c b/quantum/debounce/debounce_sym_g.c deleted file mode 100644 index c8ab34e1a..000000000 --- a/quantum/debounce/debounce_sym_g.c +++ /dev/null @@ -1,57 +0,0 @@ -/* -Copyright 2017 Alex Ong -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -/* -Basic global debounce algorithm. Used in 99% of keyboards at time of implementation -When no state changes have occured for DEBOUNCE milliseconds, we push the state. -*/ -#include "matrix.h" -#include "timer.h" -#include "quantum.h" -#ifndef DEBOUNCE - #define DEBOUNCE 5 -#endif - -void debounce_init(uint8_t num_rows) {} -static bool debouncing = false; - -#if DEBOUNCE > 0 -static uint16_t debouncing_time; -void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) -{ - if (changed) { - debouncing = true; - debouncing_time = timer_read(); - } - - if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { - for (int i = 0; i < num_rows; i++) { - cooked[i] = raw[i]; - } - debouncing = false; - } -} -#else //no debouncing. -void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) -{ - for (int i = 0; i < num_rows; i++) { - cooked[i] = raw[i]; - } -} -#endif - -bool debounce_active(void) { - return debouncing; -} - diff --git a/quantum/debounce/eager_pk.c b/quantum/debounce/eager_pk.c new file mode 100644 index 000000000..b8ad09cee --- /dev/null +++ b/quantum/debounce/eager_pk.c @@ -0,0 +1,121 @@ +/* +Copyright 2017 Alex Ong +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* +Basic per-key algorithm. Uses an 8-bit counter per key. +After pressing a key, it immediately changes state, and sets a counter. +No further inputs are accepted until DEBOUNCE milliseconds have occurred. +*/ + +#include "matrix.h" +#include "timer.h" +#include "quantum.h" +#include + +#ifndef DEBOUNCE + #define DEBOUNCE 5 +#endif + + +#if (MATRIX_COLS <= 8) +# define ROW_SHIFTER ((uint8_t)1) +#elif (MATRIX_COLS <= 16) +# define ROW_SHIFTER ((uint16_t)1) +#elif (MATRIX_COLS <= 32) +# define ROW_SHIFTER ((uint32_t)1) +#endif + + + +#define debounce_counter_t uint8_t + +static debounce_counter_t *debounce_counters; + +#define DEBOUNCE_ELAPSED 251 +#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1) + +void update_debounce_counters(uint8_t num_rows, uint8_t current_time); +void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); + +//we use num_rows rather than MATRIX_ROWS to support split keyboards +void debounce_init(uint8_t num_rows) +{ + debounce_counters = (debounce_counter_t*)malloc(num_rows*MATRIX_COLS * sizeof(debounce_counter_t)); + int i = 0; + for (uint8_t r = 0; r < num_rows; r++) + { + for (uint8_t c = 0; c < MATRIX_COLS; c++) + { + debounce_counters[i++] = DEBOUNCE_ELAPSED; + } + } +} + +void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) +{ + uint8_t current_time = timer_read() % MAX_DEBOUNCE; + update_debounce_counters(num_rows, current_time); + transfer_matrix_values(raw, cooked, num_rows, current_time); +} + +//If the current time is > debounce counter, set the counter to enable input. +void update_debounce_counters(uint8_t num_rows, uint8_t current_time) +{ + debounce_counter_t *debounce_pointer = debounce_counters; + for (uint8_t row = 0; row < num_rows; row++) + { + for (uint8_t col = 0; col < MATRIX_COLS; col++) + { + if (*debounce_pointer != DEBOUNCE_ELAPSED) + { + if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { + *debounce_pointer = DEBOUNCE_ELAPSED; + } + } + debounce_pointer++; + } + } +} + +// upload from raw_matrix to final matrix; +void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) +{ + debounce_counter_t *debounce_pointer = debounce_counters; + for (uint8_t row = 0; row < num_rows; row++) + { + matrix_row_t existing_row = cooked[row]; + matrix_row_t raw_row = raw[row]; + + for (uint8_t col = 0; col < MATRIX_COLS; col++) + { + matrix_row_t col_mask = (ROW_SHIFTER << col); + bool final_value = raw_row & col_mask; + bool existing_value = existing_row & col_mask; + if (*debounce_pointer == DEBOUNCE_ELAPSED && + (existing_value != final_value)) + { + *debounce_pointer = current_time; + existing_row ^= col_mask; //flip the bit. + } + debounce_pointer++; + } + cooked[row] = existing_row; + } +} + +bool debounce_active(void) +{ + return true; +} + diff --git a/quantum/debounce/readme.md b/quantum/debounce/readme.md index 1a77d44df..5b318d845 100644 --- a/quantum/debounce/readme.md +++ b/quantum/debounce/readme.md @@ -6,10 +6,10 @@ Here are a few ideas * Per key - one timer per key * Per row - one timer per row -2) Eager vs symmetric vs assymetric +2) Eager vs symmetric vs asymmetric * Eager - any key change is reported immediately. All further inputs for DEBOUNCE ms are ignored. * Symmetric - wait for no changes for DEBOUNCE ms before reporting change - * Assymetric - wait for different times depending on key-down/key-up. E.g. Eager key-down, DEBOUNCE ms key up. + * Asymmetric - wait for different times depending on key-down/key-up. E.g. Eager key-down, DEBOUNCE ms key up. 3) Timestamp vs cycles * old old old code waits n cycles, decreasing count by one each matrix_scan @@ -19,10 +19,10 @@ Here are a few ideas The default algorithm is symmetric and global. Here are a few that could be implemented: -debounce_sym_g.c -debounce_sym_pk.c -debounce_sym_pr.c -debounce_sym_pr_cycles.c //currently used in ergo-dox -debounce_eager_g.c -debounce_eager_pk.c -debounce_eager_pr.c //could be used in ergo-dox! +sym_g.c +sym_pk.c +sym_pr.c +sym_pr_cycles.c //currently used in ergo-dox +eager_g.c +eager_pk.c +eager_pr.c //could be used in ergo-dox! diff --git a/quantum/debounce/sym_g.c b/quantum/debounce/sym_g.c new file mode 100644 index 000000000..c8ab34e1a --- /dev/null +++ b/quantum/debounce/sym_g.c @@ -0,0 +1,57 @@ +/* +Copyright 2017 Alex Ong +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* +Basic global debounce algorithm. Used in 99% of keyboards at time of implementation +When no state changes have occured for DEBOUNCE milliseconds, we push the state. +*/ +#include "matrix.h" +#include "timer.h" +#include "quantum.h" +#ifndef DEBOUNCE + #define DEBOUNCE 5 +#endif + +void debounce_init(uint8_t num_rows) {} +static bool debouncing = false; + +#if DEBOUNCE > 0 +static uint16_t debouncing_time; +void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) +{ + if (changed) { + debouncing = true; + debouncing_time = timer_read(); + } + + if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { + for (int i = 0; i < num_rows; i++) { + cooked[i] = raw[i]; + } + debouncing = false; + } +} +#else //no debouncing. +void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) +{ + for (int i = 0; i < num_rows; i++) { + cooked[i] = raw[i]; + } +} +#endif + +bool debounce_active(void) { + return debouncing; +} + diff --git a/show_options.mk b/show_options.mk index e72dd75cf..c72059118 100644 --- a/show_options.mk +++ b/show_options.mk @@ -7,7 +7,7 @@ BUILD_OPTION_NAMES = \ NKRO_ENABLE \ TERMINAL_ENABLE \ CUSTOM_MATRIX \ - CUSTOM_DEBOUNCE \ + DEBOUNCE_TYPE \ SPLIT_KEYBOARD \ DYNAMIC_KEYMAP_ENABLE \ USB_HID_ENABLE -- cgit v1.2.3-70-g09d2