@ -1,52 +0,0 @@ | |||||
#include "matrix.h" | |||||
#include "timer.h" | |||||
#include "quantum.h" | |||||
#ifndef DEBOUNCING_DELAY | |||||
# define DEBOUNCING_DELAY 5 | |||||
#endif | |||||
void debounce_init(uint8_t num_rows) { | |||||
} | |||||
#if DEBOUNCING_DELAY > 0 | |||||
static bool debouncing = false; | |||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { | |||||
static uint16_t debouncing_time; | |||||
if (changed) { | |||||
debouncing = true; | |||||
debouncing_time = timer_read(); | |||||
} | |||||
if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) { | |||||
for (uint8_t i = 0; i < num_rows; i++) { | |||||
cooked[i] = raw[i]; | |||||
} | |||||
debouncing = false; | |||||
} | |||||
} | |||||
bool debounce_active(void) { | |||||
return debouncing; | |||||
} | |||||
#else | |||||
// no debounce | |||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { | |||||
if (changed) | |||||
{ | |||||
for (uint8_t i = 0; i < num_rows; i++) { | |||||
cooked[i] = raw[i]; | |||||
} | |||||
} | |||||
} | |||||
bool debounce_active(void) { | |||||
return false; | |||||
} | |||||
#endif |
@ -1,11 +1,26 @@ | |||||
#pragma once | #pragma once | ||||
/* | |||||
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/>. | |||||
*/ | |||||
#include "matrix.h" | |||||
void debounce_init(void); //every debounce algorithm will have unique storage needs. | |||||
// raw is the current key state | // raw is the current key state | ||||
// on entry cooked is the previous debounced state | |||||
// on exit cooked is the current debounced state | |||||
// cooked is the debounced input/output key state | |||||
// changed is true if raw has changed since the last call | // changed is true if raw has changed since the last call | ||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed); | |||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed); | |||||
bool debounce_active(void); | bool debounce_active(void); | ||||
void debounce_init(uint8_t num_rows); |
@ -0,0 +1,123 @@ | |||||
/* | |||||
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/>. | |||||
*/ | |||||
/* | |||||
Basic 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. | |||||
*/ | |||||
#include "debounce.h" | |||||
#include "matrix.h" | |||||
#include "timer.h" | |||||
#ifndef DEBOUNCE | |||||
#define DEBOUNCE 5 | |||||
#endif | |||||
#if (MATRIX_COLS <= 8) | |||||
# define ROW_SHIFTER ((uint8_t)1) | |||||
#elif (MATRIX_COLS <= 16) | |||||
# define ROW_SHIFTER ((uint16_t)1) | |||||
#elif (MATRIX_COLS <= 32) | |||||
# define ROW_SHIFTER ((uint32_t)1) | |||||
#endif | |||||
#define debounce_counter_t uint8_t | |||||
static matrix_row_t matrix_debounced[MATRIX_ROWS]; | |||||
static debounce_counter_t debounce_counters[MATRIX_ROWS*MATRIX_COLS]; | |||||
#define DEBOUNCE_ELAPSED 251 | |||||
#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1) | |||||
void update_debounce_counters(uint8_t current_time); | |||||
void transfer_matrix_values(uint8_t current_time); | |||||
void matrix_debounce_init(void) | |||||
{ | |||||
for (uint8_t r = 0; r < MATRIX_ROWS; r++) | |||||
{ | |||||
matrix_debounced[r] = 0; | |||||
} | |||||
int i = 0; | |||||
for (uint8_t r = 0; r < MATRIX_ROWS; r++) | |||||
{ | |||||
for (uint8_t c = 0; c < MATRIX_COLS; c++) | |||||
{ | |||||
debounce_counters[i++] = DEBOUNCE_ELAPSED; | |||||
} | |||||
} | |||||
} | |||||
void matrix_debounce(void) | |||||
{ | |||||
uint8_t current_time = timer_read() % MAX_DEBOUNCE; | |||||
update_debounce_counters(current_time); | |||||
transfer_matrix_values(current_time); | |||||
} | |||||
//If the current time is > debounce counter, set the counter to enable input. | |||||
void update_debounce_counters(uint8_t current_time) | |||||
{ | |||||
debounce_counter_t *debounce_pointer = debounce_counters; | |||||
for (uint8_t row = 0; row < MATRIX_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) >= | |||||
DEBOUNCING_DELAY) { | |||||
*debounce_pointer = DEBOUNCE_ELAPSED; | |||||
} | |||||
} | |||||
debounce_pointer++; | |||||
} | |||||
} | |||||
} | |||||
// upload from raw_matrix to final matrix; | |||||
void transfer_matrix_values(uint8_t current_time) | |||||
{ | |||||
debounce_counter_t *debounce_pointer = debounce_counters; | |||||
for (uint8_t row = 0; row < MATRIX_ROWS; row++) | |||||
{ | |||||
matrix_row_t existing_row = matrix_debounced[row]; | |||||
matrix_row_t raw_row = matrix_get_row(row); | |||||
for (uint8_t col = 0; col < MATRIX_COLS; col++) | |||||
{ | |||||
matrix_row_t col_mask = (ROW_SHIFTER << col); | |||||
bool final_value = raw_row & col_mask; | |||||
bool existing_value = existing_row & col_mask; | |||||
if (*debounce_pointer == DEBOUNCE_ELAPSED && | |||||
(existing_value != final_value)) | |||||
{ | |||||
*debounce_pointer = current_time; | |||||
existing_row ^= col_mask; //flip the bit. | |||||
} | |||||
debounce_pointer++; | |||||
} | |||||
matrix_debounced[row] = existing_row; | |||||
} | |||||
} | |||||
//Implementation of no debounce. |
@ -0,0 +1,58 @@ | |||||
/* | |||||
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/>. | |||||
*/ | |||||
/* | |||||
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 "matrix.h" | |||||
#include "timer.h" | |||||
#ifndef DEBOUNCE | |||||
#define DEBOUNCE 5 | |||||
#endif | |||||
static bool debouncing = false; | |||||
static uint16_t debouncing_time; | |||||
void debounce_init(void) {} | |||||
#if DEBOUNCE > 0 | |||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed) | |||||
{ | |||||
if (changed) { | |||||
debouncing = true; | |||||
debouncing_time = timer_read(); | |||||
} | |||||
if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { | |||||
for (int i = 0; i < MATRIX_ROWS; i++) { | |||||
cooked[i] = raw[i]; | |||||
} | |||||
debouncing = false; | |||||
} | |||||
} | |||||
#else //no debouncing. | |||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed) | |||||
{ | |||||
for (int i = 0; i < MATRIX_ROWS; i++) { | |||||
cooked[i] = raw[i]; | |||||
} | |||||
} | |||||
#endif | |||||
bool debounce_active() { | |||||
return debouncing; | |||||
} | |||||
@ -0,0 +1,28 @@ | |||||
Debounce algorithms belong in this folder. | |||||
Here are a few ideas | |||||
1) Global vs Per-Key vs Per-Row | |||||
* Global - one timer for all keys. Any key change state affects global timer | |||||
* Per key - one timer per key | |||||
* Per row - one timer per row | |||||
2) Eager vs symmetric vs assymetric | |||||
* Eager - any key change is reported immediately. All further inputs for DEBOUNCE ms are ignored. | |||||
* Symmetric - wait for no changes for DEBOUNCE ms before reporting change | |||||
* Assymetric - wait for different times depending on key-down/key-up. E.g. Eager key-down, DEBOUNCE ms key up. | |||||
3) Timestamp vs cycles | |||||
* old old old code waits n cycles, decreasing count by one each matrix_scan | |||||
* newer code stores the millisecond the change occurred, and does subraction to figure out time elapsed. | |||||
* Timestamps are superior, i don't think cycles will ever be used again once upgraded. | |||||
The default algorithm is symmetric and global. | |||||
Here are a few that could be implemented: | |||||
debounce_sym_g.c | |||||
debounce_sym_pk.c | |||||
debounce_sym_pr.c | |||||
debounce_sym_pr_cycles.c //currently used in ergo-dox | |||||
debounce_eager_g.c | |||||
debounce_eager_pk.c | |||||
debounce_eager_pr.c //could be used in ergo-dox! |