summaryrefslogtreecommitdiffstats
path: root/quantum/debounce/sym_defer_pk.c
diff options
context:
space:
mode:
authorSimon Arlott <70171+nomis@users.noreply.github.com>2021-06-09 08:23:21 +0100
committerGitHub <noreply@github.com>2021-06-09 17:23:21 +1000
commitb829a1d2648abd0751e9d3505554547faf643425 (patch)
tree35ba811a62feffd88759d0a53c1d6353d5d6d88a /quantum/debounce/sym_defer_pk.c
parentf287597c19dc926c7c28cefa32ffc3f0b4fdba7f (diff)
Avoid 8-bit timer overflows in debounce algorithms (#12240)
* Add fast_timer_t that is 16-bit or 32-bit based on architecture A 16-bit timer will overflow sooner but be faster to compare on AVR. * Avoid 8-bit timer overflows in debounce algorithms Count down remaining elapsed time instead of trying to do 8-bit timer comparisons. Add a "none" implementation that is automatically used if DEBOUNCE is 0 otherwise it will break the _pk/_pr count down. * Avoid unnecessary polling of the entire matrix in sym_eager_pk The matrix only needs to be updated when a debounce timer expires. * Avoid unnecessary polling of the entire matrix in sym_eager_pr The matrix only needs to be updated when a debounce timer expires. The use of the "needed_update" variable is trying to do what "matrix_need_update" was added to fix but didn't work because it only applied when all keys finished debouncing. * Fix sym_defer_g timing inconsistency compared to other debounce algorithms DEBOUNCE=5 should process the key after 5ms, not 6ms * Add debounce tests
Diffstat (limited to 'quantum/debounce/sym_defer_pk.c')
-rw-r--r--quantum/debounce/sym_defer_pk.c67
1 files changed, 45 insertions, 22 deletions
diff --git a/quantum/debounce/sym_defer_pk.c b/quantum/debounce/sym_defer_pk.c
index 60513f98e1..626a9be841 100644
--- a/quantum/debounce/sym_defer_pk.c
+++ b/quantum/debounce/sym_defer_pk.c
@@ -1,6 +1,7 @@
/*
Copyright 2017 Alex Ong<the.onga@gmail.com>
Copyright 2020 Andrei Purdea<andrei@purdea.ro>
+Copyright 2021 Simon Arlott
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
@@ -33,28 +34,25 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.
# define DEBOUNCE 5
#endif
+// Maximum debounce: 255ms
+#if DEBOUNCE > UINT8_MAX
+# undef DEBOUNCE
+# define DEBOUNCE UINT8_MAX
+#endif
+
#define ROW_SHIFTER ((matrix_row_t)1)
-#define debounce_counter_t uint8_t
+typedef uint8_t debounce_counter_t;
+#if DEBOUNCE > 0
static debounce_counter_t *debounce_counters;
+static fast_timer_t last_time;
static bool counters_need_update;
-#define DEBOUNCE_ELAPSED 251
-#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1)
-
-static uint8_t wrapping_timer_read(void) {
- static uint16_t time = 0;
- static uint8_t last_result = 0;
- uint16_t new_time = timer_read();
- uint16_t diff = new_time - time;
- time = new_time;
- last_result = (last_result + diff) % (MAX_DEBOUNCE + 1);
- return last_result;
-}
+#define DEBOUNCE_ELAPSED 0
-void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time);
-void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time);
+static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time);
+static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
// we use num_rows rather than MATRIX_ROWS to support split keyboards
void debounce_init(uint8_t num_rows) {
@@ -67,27 +65,49 @@ void debounce_init(uint8_t num_rows) {
}
}
+void debounce_free(void) {
+ free(debounce_counters);
+ debounce_counters = NULL;
+}
+
void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
- uint8_t current_time = wrapping_timer_read();
+ bool updated_last = false;
+
if (counters_need_update) {
- update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, current_time);
+ fast_timer_t now = timer_read_fast();
+ fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
+
+ last_time = now;
+ updated_last = true;
+ if (elapsed_time > UINT8_MAX) {
+ elapsed_time = UINT8_MAX;
+ }
+
+ if (elapsed_time > 0) {
+ update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, elapsed_time);
+ }
}
if (changed) {
- start_debounce_counters(raw, cooked, num_rows, current_time);
+ if (!updated_last) {
+ last_time = timer_read_fast();
+ }
+
+ start_debounce_counters(raw, cooked, num_rows);
}
}
-void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) {
+static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time) {
counters_need_update = false;
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) {
+ if (*debounce_pointer <= elapsed_time) {
*debounce_pointer = DEBOUNCE_ELAPSED;
cooked[row] = (cooked[row] & ~(ROW_SHIFTER << col)) | (raw[row] & (ROW_SHIFTER << col));
} else {
+ *debounce_pointer -= elapsed_time;
counters_need_update = true;
}
}
@@ -96,14 +116,14 @@ void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix
}
}
-void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) {
+static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {
debounce_counter_t *debounce_pointer = debounce_counters;
for (uint8_t row = 0; row < num_rows; row++) {
matrix_row_t delta = raw[row] ^ cooked[row];
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
if (delta & (ROW_SHIFTER << col)) {
if (*debounce_pointer == DEBOUNCE_ELAPSED) {
- *debounce_pointer = current_time;
+ *debounce_pointer = DEBOUNCE;
counters_need_update = true;
}
} else {
@@ -115,3 +135,6 @@ void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t
}
bool debounce_active(void) { return true; }
+#else
+# include "none.c"
+#endif