mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-07-27 03:21:15 +00:00
Merge 52a90587e4
into 542440eac5
This commit is contained in:
commit
9fc72569a0
3
docs/ChangeLog/20250831/PR25515.md
Normal file
3
docs/ChangeLog/20250831/PR25515.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Refactor debounce algorithm with static allocation [#25515](https://github.com/qmk/qmk_firmware/pull/25515)
|
||||
|
||||
Removed dynamic memory allocation (malloc, free) from all debounce implementations for improved efficiency on embedded systems and to avoid runtime allocation overhead. Refactored state arrays to use direct indexing, simplifying code and eliminating pointer arithmetic. Standardized usage of MATRIX_ROWS_PER_HAND throughout the codebase to ensure consistent support for split keyboards.
|
@ -17,5 +17,3 @@
|
||||
bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed);
|
||||
|
||||
void debounce_init(uint8_t num_rows);
|
||||
|
||||
void debounce_free(void);
|
||||
|
@ -1,31 +1,15 @@
|
||||
/*
|
||||
* 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
|
||||
* (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 <the.onga@gmail.com>
|
||||
// Copyright 2020 Andrei Purdea <andrei@purdea.ro>
|
||||
// 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>
|
||||
#include "util.h"
|
||||
|
||||
#ifdef PROTOCOL_CHIBIOS
|
||||
# if CH_CFG_USE_MEMCORE == FALSE
|
||||
@ -43,40 +27,25 @@ 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)
|
||||
|
||||
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;
|
||||
// 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] = {0};
|
||||
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);
|
||||
static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t elapsed_time);
|
||||
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[]);
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void debounce_free(void) {
|
||||
free(debounce_counters);
|
||||
debounce_counters = NULL;
|
||||
}
|
||||
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;
|
||||
@ -88,12 +57,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 UINT8_MAX
|
||||
update_debounce_counters_and_transfer_if_expired(raw, cooked, MIN(elapsed_time, UINT8_MAX));
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,74 +69,92 @@ 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 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++) {
|
||||
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
|
||||
matrix_row_t col_mask = (ROW_SHIFTER << col);
|
||||
uint16_t index = row * MATRIX_COLS + 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 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++) {
|
||||
for (uint8_t row = 0; row < MATRIX_ROWS_PER_HAND; row++) {
|
||||
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 * MATRIX_COLS + 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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,4 @@ bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
|
||||
}
|
||||
|
||||
return cooked_changed;
|
||||
}
|
||||
|
||||
void debounce_free(void) {}
|
||||
}
|
@ -1,22 +1,10 @@
|
||||
/*
|
||||
Copyright 2017 Alex Ong<the.onga@gmail.com>
|
||||
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/>.
|
||||
*/
|
||||
// Copyright 2017 Alex Ong<the.onga@gmail.com>
|
||||
// Copyright 2021 Simon Arlott
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
//
|
||||
// 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.
|
||||
|
||||
/*
|
||||
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 "debounce.h"
|
||||
#include "timer.h"
|
||||
#include <string.h>
|
||||
@ -54,7 +42,6 @@ bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
|
||||
return cooked_changed;
|
||||
}
|
||||
|
||||
void debounce_free(void) {}
|
||||
#else // no debouncing.
|
||||
# include "none.c"
|
||||
#endif
|
||||
|
@ -1,27 +1,14 @@
|
||||
/*
|
||||
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
|
||||
(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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Basic symmetric per-key algorithm. Uses an 8-bit counter per key.
|
||||
When no state changes have occured for DEBOUNCE milliseconds, we push the state.
|
||||
*/
|
||||
// Copyright 2017 Alex Ong<the.onga@gmail.com>
|
||||
// Copyright 2020 Andrei Purdea<andrei@purdea.ro>
|
||||
// Copyright 2021 Simon Arlott
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
//
|
||||
// Basic symmetric per-key algorithm. Uses an 8-bit counter per key.
|
||||
// When no state changes have occured for DEBOUNCE milliseconds, we push the state.
|
||||
|
||||
#include "debounce.h"
|
||||
#include "timer.h"
|
||||
#include <stdlib.h>
|
||||
#include "util.h"
|
||||
|
||||
#ifdef PROTOCOL_CHIBIOS
|
||||
# if CH_CFG_USE_MEMCORE == FALSE
|
||||
@ -39,36 +26,21 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.
|
||||
# define DEBOUNCE UINT8_MAX
|
||||
#endif
|
||||
|
||||
#define ROW_SHIFTER ((matrix_row_t)1)
|
||||
|
||||
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;
|
||||
static bool cooked_changed;
|
||||
// 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] = {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 num_rows, uint8_t elapsed_time);
|
||||
static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
|
||||
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[]);
|
||||
|
||||
// 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_free(void) {
|
||||
free(debounce_counters);
|
||||
debounce_counters = NULL;
|
||||
}
|
||||
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;
|
||||
@ -80,12 +52,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 UINT8_MAX
|
||||
update_debounce_counters_and_transfer_if_expired(raw, cooked, MIN(elapsed_time, UINT8_MAX));
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,47 +64,69 @@ bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
|
||||
last_time = timer_read_fast();
|
||||
}
|
||||
|
||||
start_debounce_counters(raw, cooked, num_rows);
|
||||
start_debounce_counters(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) {
|
||||
counters_need_update = false;
|
||||
debounce_counter_t *debounce_pointer = debounce_counters;
|
||||
for (uint8_t row = 0; row < num_rows; row++) {
|
||||
/**
|
||||
* @brief Updates debounce counters and transfers debounced key states if the debounce period has expired.
|
||||
*
|
||||
* Iterates through each key in the matrix and checks its debounce counter. If the debounce period has expired
|
||||
* for a key, 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++) {
|
||||
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
|
||||
if (*debounce_pointer != DEBOUNCE_ELAPSED) {
|
||||
if (*debounce_pointer <= elapsed_time) {
|
||||
*debounce_pointer = DEBOUNCE_ELAPSED;
|
||||
matrix_row_t cooked_next = (cooked[row] & ~(ROW_SHIFTER << col)) | (raw[row] & (ROW_SHIFTER << col));
|
||||
uint16_t index = row * MATRIX_COLS + col;
|
||||
|
||||
if (debounce_counters[index] != DEBOUNCE_ELAPSED) {
|
||||
if (debounce_counters[index] <= elapsed_time) {
|
||||
debounce_counters[index] = DEBOUNCE_ELAPSED;
|
||||
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[row] ^ cooked_next;
|
||||
cooked[row] = cooked_next;
|
||||
} else {
|
||||
*debounce_pointer -= elapsed_time;
|
||||
debounce_counters[index] -= elapsed_time;
|
||||
counters_need_update = true;
|
||||
}
|
||||
}
|
||||
debounce_pointer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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++) {
|
||||
/**
|
||||
* @brief Initializes debounce counters for keys with changed states.
|
||||
*
|
||||
* For each key 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++) {
|
||||
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 = DEBOUNCE;
|
||||
counters_need_update = true;
|
||||
uint16_t index = row * MATRIX_COLS + col;
|
||||
|
||||
if (delta & (MATRIX_ROW_SHIFTER << col)) {
|
||||
if (debounce_counters[index] == DEBOUNCE_ELAPSED) {
|
||||
debounce_counters[index] = DEBOUNCE;
|
||||
counters_need_update = true;
|
||||
}
|
||||
} else {
|
||||
*debounce_pointer = DEBOUNCE_ELAPSED;
|
||||
debounce_counters[index] = DEBOUNCE_ELAPSED;
|
||||
}
|
||||
debounce_pointer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,77 +1,124 @@
|
||||
/*
|
||||
Copyright 2021 Chad Austin <chad@chadaustin.me>
|
||||
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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Symmetric per-row debounce algorithm. Changes only apply when
|
||||
DEBOUNCE milliseconds have elapsed since the last change.
|
||||
*/
|
||||
// Copyright 2017 Alex Ong<the.onga@gmail.com>
|
||||
// Copyright 2020 Andrei Purdea<andrei@purdea.ro>
|
||||
// Copyright 2021 Simon Arlott
|
||||
// Copyright @filterpaper
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
//
|
||||
// Basic symmetric per-row algorithm. Uses an 8-bit counter per row.
|
||||
// When no state changes have occured for DEBOUNCE milliseconds, we push the state.
|
||||
|
||||
#include "debounce.h"
|
||||
#include "timer.h"
|
||||
#include <stdlib.h>
|
||||
#include "util.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
|
||||
# define DEBOUNCE 5
|
||||
#endif
|
||||
|
||||
static uint16_t last_time;
|
||||
// [row] milliseconds until key's state is considered debounced.
|
||||
static uint8_t* countdowns;
|
||||
// [row]
|
||||
static matrix_row_t* last_raw;
|
||||
// Maximum debounce: 255ms
|
||||
#if DEBOUNCE > UINT8_MAX
|
||||
# undef DEBOUNCE
|
||||
# define DEBOUNCE UINT8_MAX
|
||||
#endif
|
||||
|
||||
void debounce_init(uint8_t num_rows) {
|
||||
countdowns = (uint8_t*)calloc(num_rows, sizeof(uint8_t));
|
||||
last_raw = (matrix_row_t*)calloc(num_rows, sizeof(matrix_row_t));
|
||||
typedef uint8_t debounce_counter_t;
|
||||
|
||||
last_time = timer_read();
|
||||
}
|
||||
#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;
|
||||
|
||||
void debounce_free(void) {
|
||||
free(countdowns);
|
||||
countdowns = NULL;
|
||||
free(last_raw);
|
||||
last_raw = NULL;
|
||||
}
|
||||
# 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) {}
|
||||
|
||||
bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
|
||||
uint16_t now = timer_read();
|
||||
uint16_t elapsed16 = TIMER_DIFF_16(now, last_time);
|
||||
last_time = now;
|
||||
uint8_t elapsed = (elapsed16 > 255) ? 255 : elapsed16;
|
||||
bool cooked_changed = false;
|
||||
bool updated_last = false;
|
||||
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 < num_rows; ++row, ++countdown) {
|
||||
matrix_row_t raw_row = raw[row];
|
||||
last_time = now;
|
||||
updated_last = true;
|
||||
|
||||
if (raw_row != last_raw[row]) {
|
||||
*countdown = DEBOUNCE;
|
||||
last_raw[row] = raw_row;
|
||||
} else if (*countdown > elapsed) {
|
||||
*countdown -= elapsed;
|
||||
} else if (*countdown) {
|
||||
cooked_changed |= cooked[row] ^ raw_row;
|
||||
cooked[row] = raw_row;
|
||||
*countdown = 0;
|
||||
if (elapsed_time > 0) {
|
||||
// Update debounce counters with elapsed timer clamped to UINT8_MAX
|
||||
update_debounce_counters_and_transfer_if_expired(raw, cooked, MIN(elapsed_time, UINT8_MAX));
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
if (!updated_last) {
|
||||
last_time = timer_read_fast();
|
||||
}
|
||||
|
||||
start_debounce_counters(raw, cooked);
|
||||
}
|
||||
|
||||
return cooked_changed;
|
||||
}
|
||||
|
||||
bool debounce_active(void) {
|
||||
return true;
|
||||
/**
|
||||
* @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
|
@ -21,7 +21,7 @@ No further inputs are accepted until DEBOUNCE milliseconds have occurred.
|
||||
|
||||
#include "debounce.h"
|
||||
#include "timer.h"
|
||||
#include <stdlib.h>
|
||||
#include "util.h"
|
||||
|
||||
#ifdef PROTOCOL_CHIBIOS
|
||||
# if CH_CFG_USE_MEMCORE == FALSE
|
||||
@ -39,37 +39,22 @@ No further inputs are accepted until DEBOUNCE milliseconds have occurred.
|
||||
# define DEBOUNCE UINT8_MAX
|
||||
#endif
|
||||
|
||||
#define ROW_SHIFTER ((matrix_row_t)1)
|
||||
|
||||
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;
|
||||
static bool matrix_need_update;
|
||||
static bool cooked_changed;
|
||||
// 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] = {0};
|
||||
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(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);
|
||||
static void update_debounce_counters(uint8_t elapsed_time);
|
||||
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[]);
|
||||
|
||||
// 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_free(void) {
|
||||
free(debounce_counters);
|
||||
debounce_counters = NULL;
|
||||
}
|
||||
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;
|
||||
@ -81,12 +66,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(num_rows, elapsed_time);
|
||||
// Update debounce counters with elapsed timer clamped to UINT8_MAX
|
||||
update_debounce_counters(MIN(elapsed_time, UINT8_MAX));
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,51 +78,68 @@ 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;
|
||||
}
|
||||
|
||||
// If the current time is > debounce counter, set the counter to enable input.
|
||||
static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {
|
||||
counters_need_update = false;
|
||||
matrix_need_update = false;
|
||||
debounce_counter_t *debounce_pointer = debounce_counters;
|
||||
for (uint8_t row = 0; row < num_rows; row++) {
|
||||
/**
|
||||
* @brief Updates per-key debounce counters and determines if matrix needs updating.
|
||||
*
|
||||
* Iterates through each key in the matrix and checks its debounce counter. If the debounce
|
||||
* period has elapsed, the counter is reset and the matrix is marked for update. Otherwise,
|
||||
* the counter is decremented by the elapsed time and marked for further updates if needed.
|
||||
*
|
||||
* @param elapsed_time The time elapsed since the last debounce update, in milliseconds.
|
||||
*/
|
||||
static void update_debounce_counters(uint8_t elapsed_time) {
|
||||
counters_need_update = false;
|
||||
matrix_need_update = false;
|
||||
for (uint8_t row = 0; row < MATRIX_ROWS_PER_HAND; row++) {
|
||||
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
|
||||
if (*debounce_pointer != DEBOUNCE_ELAPSED) {
|
||||
if (*debounce_pointer <= elapsed_time) {
|
||||
*debounce_pointer = DEBOUNCE_ELAPSED;
|
||||
matrix_need_update = true;
|
||||
uint16_t index = row * MATRIX_COLS + col;
|
||||
|
||||
if (debounce_counters[index] != DEBOUNCE_ELAPSED) {
|
||||
if (debounce_counters[index] <= elapsed_time) {
|
||||
debounce_counters[index] = DEBOUNCE_ELAPSED;
|
||||
matrix_need_update = true;
|
||||
} else {
|
||||
*debounce_pointer -= elapsed_time;
|
||||
debounce_counters[index] -= elapsed_time;
|
||||
counters_need_update = true;
|
||||
}
|
||||
}
|
||||
debounce_pointer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// upload from raw_matrix to final matrix;
|
||||
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {
|
||||
matrix_need_update = false;
|
||||
debounce_counter_t *debounce_pointer = debounce_counters;
|
||||
for (uint8_t row = 0; row < num_rows; row++) {
|
||||
/**
|
||||
* @brief Transfers debounced key states from the raw matrix to the cooked matrix.
|
||||
*
|
||||
* For each key in the matrix, this function checks if its state has changed and if its
|
||||
* debounce counter has elapsed. If so, the debounce counter is reset, the cooked matrix
|
||||
* is updated to reflect the new state, and the matrix is marked for further updates.
|
||||
*
|
||||
* @param raw The current raw key state matrix.
|
||||
* @param cooked The debounced key state matrix to be updated.
|
||||
*/
|
||||
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[]) {
|
||||
matrix_need_update = false;
|
||||
for (uint8_t row = 0; row < MATRIX_ROWS_PER_HAND; row++) {
|
||||
matrix_row_t delta = raw[row] ^ cooked[row];
|
||||
matrix_row_t existing_row = cooked[row];
|
||||
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
|
||||
matrix_row_t col_mask = (ROW_SHIFTER << col);
|
||||
uint16_t index = row * MATRIX_COLS + col;
|
||||
|
||||
matrix_row_t col_mask = (MATRIX_ROW_SHIFTER << col);
|
||||
if (delta & col_mask) {
|
||||
if (*debounce_pointer == DEBOUNCE_ELAPSED) {
|
||||
*debounce_pointer = DEBOUNCE;
|
||||
counters_need_update = true;
|
||||
if (debounce_counters[index] == DEBOUNCE_ELAPSED) {
|
||||
debounce_counters[index] = DEBOUNCE;
|
||||
counters_need_update = true;
|
||||
existing_row ^= col_mask; // flip the bit.
|
||||
cooked_changed = true;
|
||||
}
|
||||
}
|
||||
debounce_pointer++;
|
||||
}
|
||||
cooked[row] = existing_row;
|
||||
}
|
||||
|
@ -1,27 +1,14 @@
|
||||
/*
|
||||
Copyright 2019 Alex Ong<the.onga@gmail.com>
|
||||
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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Basic per-row algorithm. Uses an 8-bit counter per row.
|
||||
After pressing a key, it immediately changes state, and sets a counter.
|
||||
No further inputs are accepted until DEBOUNCE milliseconds have occurred.
|
||||
*/
|
||||
// Copyright 2017 Alex Ong<the.onga@gmail.com>
|
||||
// Copyright 2021 Simon Arlott
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
//
|
||||
// Basic per-row 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 "debounce.h"
|
||||
#include "timer.h"
|
||||
#include <stdlib.h>
|
||||
#include "util.h"
|
||||
|
||||
#ifdef PROTOCOL_CHIBIOS
|
||||
# if CH_CFG_USE_MEMCORE == FALSE
|
||||
@ -42,30 +29,19 @@ No further inputs are accepted until DEBOUNCE milliseconds have occurred.
|
||||
typedef uint8_t debounce_counter_t;
|
||||
|
||||
#if DEBOUNCE > 0
|
||||
static bool matrix_need_update;
|
||||
|
||||
static debounce_counter_t *debounce_counters;
|
||||
static fast_timer_t last_time;
|
||||
static bool counters_need_update;
|
||||
static bool cooked_changed;
|
||||
// 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 matrix_need_update;
|
||||
static bool cooked_changed;
|
||||
|
||||
# define DEBOUNCE_ELAPSED 0
|
||||
|
||||
static void update_debounce_counters(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);
|
||||
static void update_debounce_counters(uint8_t elapsed_time);
|
||||
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[]);
|
||||
|
||||
// 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 * sizeof(debounce_counter_t));
|
||||
for (uint8_t r = 0; r < num_rows; r++) {
|
||||
debounce_counters[r] = DEBOUNCE_ELAPSED;
|
||||
}
|
||||
}
|
||||
|
||||
void debounce_free(void) {
|
||||
free(debounce_counters);
|
||||
debounce_counters = NULL;
|
||||
}
|
||||
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;
|
||||
@ -77,12 +53,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(num_rows, elapsed_time);
|
||||
// Update debounce counters with elapsed timer clamped to UINT8_MAX
|
||||
update_debounce_counters(MIN(elapsed_time, UINT8_MAX));
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,49 +65,62 @@ 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;
|
||||
}
|
||||
|
||||
// If the current time is > debounce counter, set the counter to enable input.
|
||||
static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {
|
||||
counters_need_update = false;
|
||||
matrix_need_update = false;
|
||||
debounce_counter_t *debounce_pointer = debounce_counters;
|
||||
for (uint8_t row = 0; row < num_rows; row++) {
|
||||
if (*debounce_pointer != DEBOUNCE_ELAPSED) {
|
||||
if (*debounce_pointer <= elapsed_time) {
|
||||
*debounce_pointer = DEBOUNCE_ELAPSED;
|
||||
matrix_need_update = true;
|
||||
/**
|
||||
* @brief Updates per-row debounce counters and determines if matrix needs updating.
|
||||
*
|
||||
* Iterates through each row in the matrix and checks its debounce counter. If the debounce
|
||||
* period has elapsed, the counter is reset and the matrix is marked for update. Otherwise,
|
||||
* the counter is decremented by the elapsed time and marked for further updates if needed.
|
||||
*
|
||||
* @param elapsed_time The time elapsed since the last debounce update, in milliseconds.
|
||||
*/
|
||||
static void update_debounce_counters(uint8_t elapsed_time) {
|
||||
counters_need_update = false;
|
||||
matrix_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;
|
||||
matrix_need_update = true;
|
||||
} else {
|
||||
*debounce_pointer -= elapsed_time;
|
||||
debounce_counters[row] -= elapsed_time;
|
||||
counters_need_update = true;
|
||||
}
|
||||
}
|
||||
debounce_pointer++;
|
||||
}
|
||||
}
|
||||
|
||||
// upload from raw_matrix to final matrix;
|
||||
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {
|
||||
matrix_need_update = false;
|
||||
debounce_counter_t *debounce_pointer = debounce_counters;
|
||||
for (uint8_t row = 0; row < num_rows; row++) {
|
||||
/**
|
||||
* @brief Transfers debounced key states from the raw matrix to the cooked matrix.
|
||||
*
|
||||
* For each row in the matrix, this function checks if its state has changed and if its
|
||||
* debounce counter has elapsed. If so, the debounce counter is reset, the cooked matrix
|
||||
* is updated to reflect the new state, and the matrix is marked for further updates.
|
||||
*
|
||||
* @param raw The current raw key state matrix.
|
||||
* @param cooked The debounced key state matrix
|
||||
*/
|
||||
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[]) {
|
||||
matrix_need_update = false;
|
||||
for (uint8_t row = 0; row < MATRIX_ROWS_PER_HAND; row++) {
|
||||
matrix_row_t existing_row = cooked[row];
|
||||
matrix_row_t raw_row = raw[row];
|
||||
|
||||
// determine new value basd on debounce pointer + raw value
|
||||
if (existing_row != raw_row) {
|
||||
if (*debounce_pointer == DEBOUNCE_ELAPSED) {
|
||||
*debounce_pointer = DEBOUNCE;
|
||||
if (debounce_counters[row] == DEBOUNCE_ELAPSED) {
|
||||
debounce_counters[row] = DEBOUNCE;
|
||||
cooked_changed |= cooked[row] ^ raw_row;
|
||||
cooked[row] = raw_row;
|
||||
counters_need_update = true;
|
||||
}
|
||||
}
|
||||
debounce_pointer++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,8 +121,6 @@ void DebounceTest::runEventsInternal() {
|
||||
checkCookedMatrix(false, "debounce() modified cooked matrix");
|
||||
advance_time(1);
|
||||
}
|
||||
|
||||
debounce_free();
|
||||
}
|
||||
|
||||
void DebounceTest::runDebounce(bool changed) {
|
||||
|
Loading…
Reference in New Issue
Block a user