Rewrite sym_defer_pr

* Modernise code using sym_defer_pk as template
* Format consistency with other current algorithms
This commit is contained in:
フィルターペーパー 2025-07-26 07:17:38 +08:00
parent 66193ec03e
commit 54ece6abfa

View File

@ -1,5 +1,7 @@
/* /*
Copyright 2021 Chad Austin <chad@chadaustin.me> 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 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or the Free Software Foundation, either version 2 of the License, or
@ -13,66 +15,122 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* /*
Symmetric per-row debounce algorithm. Changes only apply when Basic symmetric per-row algorithm. Uses an 8-bit counter per row.
DEBOUNCE milliseconds have elapsed since the last change. When no state changes have occured for DEBOUNCE milliseconds, we push the state.
*/ */
#include "debounce.h" #include "debounce.h"
#include "timer.h" #include "timer.h"
#include "util.h" #include "util.h"
#include <string.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
#ifndef DEBOUNCE #ifndef DEBOUNCE
# define DEBOUNCE 5 # define DEBOUNCE 5
#endif #endif
static uint16_t last_time; // Maximum debounce: 255ms
// Countdown timers for each matrix row, indexed by row. #if DEBOUNCE > UINT8_MAX
static uint8_t countdowns[MATRIX_ROWS_PER_HAND] = {0}; # undef DEBOUNCE
// Last raw state for each matrix row, indexed by row. # define DEBOUNCE UINT8_MAX
static matrix_row_t last_raw[MATRIX_ROWS_PER_HAND] = {0}; #endif
void debounce_init(uint8_t num_rows) { typedef uint8_t debounce_counter_t;
memset(countdowns, 0, sizeof(countdowns));
memset(last_raw, 0, sizeof(last_raw)); #if DEBOUNCE > 0
} // Uses MATRIX_ROWS_PER_HAND instead of MATRIX_ROWS to support split keyboards
static debounce_counter_t debounce_counters[MATRIX_ROWS_PER_HAND] = {0};
static fast_timer_t last_time;
static bool counters_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 elapsed_time);
static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[]);
void debounce_init(uint8_t num_rows) {}
/**
* @brief Debounces the raw matrix state and updates the cooked (debounced) state.
*
* For each row in the matrix, this function tracks changes and applies a debounce period.
* If a row's state changes, its countdown timer is reset. If the countdown timer expires,
* the debounced state is updated to match the raw state.
*
* @param raw The current raw key state matrix.
* @param cooked The debounced key state matrix to be updated.
* @param num_rows Number of rows in the matrix.
* @param changed True if the raw matrix has changed since the last call.
* @return true if the debounced matrix has new key changes, false otherwise.
*/
bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
uint16_t now = timer_read(); bool updated_last = false;
uint16_t elapsed16 = TIMER_DIFF_16(now, last_time); cooked_changed = false;
last_time = now;
uint8_t elapsed = MIN(elapsed16, UINT8_MAX);
bool cooked_changed = false;
uint8_t* countdown = countdowns; if (counters_need_update) {
fast_timer_t now = timer_read_fast();
fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
for (uint8_t row = 0; row < MATRIX_ROWS_PER_HAND; ++row, ++countdown) { last_time = now;
matrix_row_t raw_row = raw[row]; updated_last = true;
if (raw_row != last_raw[row]) { if (elapsed_time > 0) {
*countdown = DEBOUNCE; // Update debounce counters with elapsed timer clamped to UINT8_MAX
last_raw[row] = raw_row; update_debounce_counters_and_transfer_if_expired(raw, cooked, MIN(elapsed_time, UINT8_MAX));
} else if (*countdown > elapsed) {
*countdown -= elapsed;
} else if (*countdown) {
cooked_changed |= cooked[row] ^ raw_row;
cooked[row] = raw_row;
*countdown = 0;
} }
} }
if (changed) {
if (!updated_last) {
last_time = timer_read_fast();
}
start_debounce_counters(raw, cooked);
}
return cooked_changed; return cooked_changed;
} }
/**
* @brief Updates debounce counters and transfers debounced row states if the debounce period has expired.
*
* Iterates through each row in the matrix and checks its debounce counter. If the debounce period has expired
* for a row, the debounced state is updated to match the raw state. Otherwise, the debounce counter is decremented
* by the elapsed time and marked for further updates.
*
* @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 void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t elapsed_time) {
counters_need_update = false;
for (uint8_t row = 0; row < MATRIX_ROWS_PER_HAND; row++) {
if (debounce_counters[row] != DEBOUNCE_ELAPSED) {
if (debounce_counters[row] <= elapsed_time) {
debounce_counters[row] = DEBOUNCE_ELAPSED;
cooked_changed |= cooked[row] ^ raw[row];
cooked[row] = raw[row];
} else {
debounce_counters[row] -= elapsed_time;
counters_need_update = true;
}
}
}
}
/**
* @brief Initializes debounce counters for rows with changed states.
*
* For each row in the matrix, this function checks if the raw state differs from the debounced state.
* If a change is detected and the debounce counter has elapsed, the counter is set to the debounce period
* and marked for update. Otherwise, the counter is cleared.
*
* @param raw The current raw key state matrix.
* @param cooked The debounced key state matrix.
*/
static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[]) {
for (uint8_t row = 0; row < MATRIX_ROWS_PER_HAND; row++) {
if (raw[row] != cooked[row]) {
debounce_counters[row] = DEBOUNCE;
counters_need_update = true;
} else {
debounce_counters[row] = DEBOUNCE_ELAPSED;
}
}
}
#else
# include "none.c"
#endif