forked from qmk/qmk_firmware
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
implement asym_eager_defer_pk debounce algorithm
- Loading branch information
1 parent
791dc61
commit 335d803
Showing
4 changed files
with
139 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
# Debounce eagerly (report change immediately), keep per-key timers. We can use | ||
# this because the kinT does not have to deal with noise. | ||
DEBOUNCE_TYPE = sym_eager_pk | ||
DEBOUNCE_TYPE = asym_eager_defer_pk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/* | ||
Copyright 2017 Alex Ong<the.onga@gmail.com> | ||
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/>. | ||
*/ | ||
|
||
/* | ||
Asymmetric 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. | ||
After releasing a key, a counter is started and once DEBOUNCE milliseconds | ||
have occurred, the key changes state. | ||
*/ | ||
|
||
#include "matrix.h" | ||
#include "timer.h" | ||
#include "quantum.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 | ||
|
||
#ifndef DEBOUNCE | ||
# define DEBOUNCE 5 | ||
#endif | ||
|
||
#define ROW_SHIFTER ((matrix_row_t)1) | ||
|
||
#define debounce_counter_t uint8_t | ||
|
||
static debounce_counter_t *debounce_counters; | ||
static bool counters_need_update; | ||
static bool matrix_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; | ||
} | ||
|
||
void update_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], 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 = wrapping_timer_read(); | ||
if (counters_need_update) { | ||
update_debounce_counters(raw, cooked, num_rows, current_time); | ||
} | ||
|
||
if (changed || matrix_need_update) { | ||
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(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_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) { | ||
const bool pressed_raw = raw[row] & (ROW_SHIFTER << col); | ||
const bool pressed_cooked = cooked[row] & (ROW_SHIFTER << col); | ||
|
||
if (!pressed_raw && pressed_cooked) { | ||
// key-up: set key as unpressed (deferred) after debounce | ||
cooked[row] = (cooked[row] & ~(ROW_SHIFTER << col)); | ||
} | ||
*debounce_pointer = DEBOUNCE_ELAPSED; | ||
} else { | ||
counters_need_update = true; | ||
} | ||
} | ||
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) { | ||
matrix_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++) { | ||
const bool pressed_raw = raw[row] & (ROW_SHIFTER << col); | ||
const bool pressed_cooked = cooked[row] & (ROW_SHIFTER << col); | ||
if (pressed_raw ^ pressed_cooked) { | ||
if (*debounce_pointer == DEBOUNCE_ELAPSED) { | ||
*debounce_pointer = current_time; | ||
counters_need_update = true; | ||
if (pressed_raw && !pressed_cooked) { | ||
// key-down: eagerly set key as pressed | ||
cooked[row] = (cooked[row] | (ROW_SHIFTER << col)); | ||
} | ||
} else { | ||
matrix_need_update = true; | ||
} | ||
} | ||
debounce_pointer++; | ||
} | ||
} | ||
} | ||
|
||
bool debounce_active(void) { return true; } |