diff options
Diffstat (limited to 'quantum/debounce/asym_eager_defer_pk.c')
-rw-r--r-- | quantum/debounce/asym_eager_defer_pk.c | 165 |
1 files changed, 74 insertions, 91 deletions
diff --git a/quantum/debounce/asym_eager_defer_pk.c b/quantum/debounce/asym_eager_defer_pk.c index b6fcdc3d4e..a385301c90 100644 --- a/quantum/debounce/asym_eager_defer_pk.c +++ b/quantum/debounce/asym_eager_defer_pk.c @@ -1,37 +1,15 @@ -/* - * Copyright 2017 Alex Ong <[email protected]> - * Copyright 2020 Andrei Purdea <[email protected]> - * 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 - * (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 <http://www.gnu.org/licenses/>. - */ - -/* -Asymetric per-key algorithm. After pressing a key, it immediately changes state, -with no further inputs accepted until DEBOUNCE milliseconds have occurred. After -releasing a key, that state is pushed after no changes occur for DEBOUNCE milliseconds. -*/ +// Copyright 2017 Alex Ong <[email protected]> +// Copyright 2020 Andrei Purdea <[email protected]> +// Copyright 2021 Simon Arlott +// SPDX-License-Identifier: GPL-2.0-or-later +// +// Asymetric per-key algorithm. After pressing a key, it immediately changes state, +// with no further inputs accepted until DEBOUNCE milliseconds have occurred. After +// releasing a key, that state is pushed after no changes occur for DEBOUNCE milliseconds. #include "debounce.h" #include "timer.h" -#include <stdlib.h> - -#ifdef PROTOCOL_CHIBIOS -# if CH_CFG_USE_MEMCORE == FALSE -# error ChibiOS is configured without a memory allocator. Your keyboard may have set `#define CH_CFG_USE_MEMCORE FALSE`, which is incompatible with this debounce algorithm. -# endif -#endif +#include "util.h" #ifndef DEBOUNCE # define DEBOUNCE 5 @@ -43,44 +21,29 @@ releasing a key, that state is pushed after no changes occur for DEBOUNCE millis # define DEBOUNCE 127 #endif -#define ROW_SHIFTER ((matrix_row_t)1) +#define DEBOUNCE_ELAPSED 0 +#if DEBOUNCE > 0 typedef struct { bool pressed : 1; uint8_t time : 7; } debounce_counter_t; -#if DEBOUNCE > 0 -static debounce_counter_t *debounce_counters; -static fast_timer_t last_time; -static bool counters_need_update; -static bool matrix_need_update; -static bool cooked_changed; - -# define DEBOUNCE_ELAPSED 0 - -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 transfer_matrix_values(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) { - debounce_counters = 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++].time = DEBOUNCE_ELAPSED; - } - } -} +// Uses MATRIX_ROWS_PER_HAND instead of MATRIX_ROWS to support split keyboards +static debounce_counter_t debounce_counters[MATRIX_ROWS_PER_HAND * MATRIX_COLS] = {DEBOUNCE_ELAPSED}; +static bool counters_need_update; +static bool matrix_need_update; +static bool cooked_changed; -void debounce_free(void) { - free(debounce_counters); - debounce_counters = NULL; -} +static inline void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t elapsed_time); +static inline void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[]); + +void debounce_init(uint8_t num_rows) {} bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { - bool updated_last = false; - cooked_changed = false; + static fast_timer_t last_time; + bool updated_last = false; + cooked_changed = false; if (counters_need_update) { fast_timer_t now = timer_read_fast(); @@ -88,12 +51,10 @@ bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool 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); + // Update debounce counters with elapsed timer clamped to 127 (maximum debounce) + update_debounce_counters_and_transfer_if_expired(raw, cooked, MIN(elapsed_time, 127)); } } @@ -102,74 +63,96 @@ bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool last_time = timer_read_fast(); } - transfer_matrix_values(raw, cooked, num_rows); + transfer_matrix_values(raw, cooked); } return cooked_changed; } -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) { - debounce_counter_t *debounce_pointer = debounce_counters; - +/** + * @brief Processes per-key debounce counters and updates the debounced matrix state. + * + * This function iterates through each key in the matrix and updates its debounce counter + * based on the elapsed time. If the debounce period has expired, the debounced state is + * updated accordingly for key-down (eager) and key-up (defer) events. + * + * @param raw The current raw key state matrix. + * @param cooked The debounced key state matrix to be updated. + * @param elapsed_time The time elapsed since the last debounce update, in milliseconds. + */ +static inline void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t elapsed_time) { counters_need_update = false; matrix_need_update = false; - for (uint8_t row = 0; row < num_rows; row++) { + for (uint8_t row = 0; row < MATRIX_ROWS_PER_HAND; row++) { + uint16_t row_offset = row * MATRIX_COLS; + for (uint8_t col = 0; col < MATRIX_COLS; col++) { - matrix_row_t col_mask = (ROW_SHIFTER << col); + uint16_t index = row_offset + col; - if (debounce_pointer->time != DEBOUNCE_ELAPSED) { - if (debounce_pointer->time <= elapsed_time) { - debounce_pointer->time = DEBOUNCE_ELAPSED; + if (debounce_counters[index].time != DEBOUNCE_ELAPSED) { + if (debounce_counters[index].time <= elapsed_time) { + debounce_counters[index].time = DEBOUNCE_ELAPSED; - if (debounce_pointer->pressed) { + if (debounce_counters[index].pressed) { // key-down: eager matrix_need_update = true; } else { // key-up: defer + matrix_row_t col_mask = (MATRIX_ROW_SHIFTER << col); matrix_row_t cooked_next = (cooked[row] & ~col_mask) | (raw[row] & col_mask); cooked_changed |= cooked_next ^ cooked[row]; cooked[row] = cooked_next; } } else { - debounce_pointer->time -= elapsed_time; + debounce_counters[index].time -= elapsed_time; counters_need_update = true; } } - debounce_pointer++; } } } -static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) { - debounce_counter_t *debounce_pointer = debounce_counters; - +/** + * @brief Applies debounced changes to the matrix state based on per-key counters. + * + * This function compares the raw and cooked key state matrices to detect changes. + * For each key, it updates the debounce counter and the debounced state according + * to the debounce algorithm. Key-down events are handled eagerly, while key-up + * events are deferred until the debounce period has elapsed. + * + * @param raw The current raw key state matrix. + * @param cooked The debounced key state matrix to be updated. + */ +static inline void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[]) { matrix_need_update = false; - for (uint8_t row = 0; row < num_rows; row++) { - matrix_row_t delta = raw[row] ^ cooked[row]; + for (uint8_t row = 0; row < MATRIX_ROWS_PER_HAND; row++) { + uint16_t row_offset = row * MATRIX_COLS; + matrix_row_t delta = raw[row] ^ cooked[row]; + for (uint8_t col = 0; col < MATRIX_COLS; col++) { - matrix_row_t col_mask = (ROW_SHIFTER << col); + uint16_t index = row_offset + col; + matrix_row_t col_mask = (MATRIX_ROW_SHIFTER << col); if (delta & col_mask) { - if (debounce_pointer->time == DEBOUNCE_ELAPSED) { - debounce_pointer->pressed = (raw[row] & col_mask); - debounce_pointer->time = DEBOUNCE; - counters_need_update = true; + if (debounce_counters[index].time == DEBOUNCE_ELAPSED) { + debounce_counters[index].pressed = (raw[row] & col_mask); + debounce_counters[index].time = DEBOUNCE; + counters_need_update = true; - if (debounce_pointer->pressed) { + if (debounce_counters[index].pressed) { // key-down: eager cooked[row] ^= col_mask; cooked_changed = true; } } - } else if (debounce_pointer->time != DEBOUNCE_ELAPSED) { - if (!debounce_pointer->pressed) { + } else if (debounce_counters[index].time != DEBOUNCE_ELAPSED) { + if (!debounce_counters[index].pressed) { // key-up: defer - debounce_pointer->time = DEBOUNCE_ELAPSED; + debounce_counters[index].time = DEBOUNCE_ELAPSED; } } - debounce_pointer++; } } } |