@ -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 | |||
/* | |||
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 | |||
// 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 | |||
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); | |||
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! |