* Added xeal60 via clone of lets split * Delete removed other keymaps * Basic keymap (no FN). Compiles. * Removed NP_STAR and NP_SLSH. * Removed "debounce_algo = manual" in all keyboards with CUSTOM_MATRIX = yes. * Changed order of rules in TMK. Documented feature. * Fixed missing whitespace in debounce documentation Table wasn't working due to missing newline. * Added bold in a few areas. * DO NOT USE - Removed debounce from TMK. * Remove accidental xeal60 commit * DO NOT USE - debounce successfully compiled. * DO NOT USE Revert back to original API to support split_keyboards. * Working eager_pk * Whitespace cleanup. * Restored debounce.h since there wasnt any real change. * Moved debouncing_time variable to inside #if debounce * Removed check for custom_matrix. We can safely include the debounce file for compilation when custom_matrix is used. * Removed #include "matrix.h" from debounce.h * Bug fix - was using MATRIX_ROWS instead of num_rows * Fixed compilation error with debounce_sym_g * Renamed DEBOUNCE_ALGO to DEBOUNCE_TYPE * Malloc array in debounce_eager_pk, since split keyboards only use MATRIX_ROWS/2. * Fix compile error in debounce_eager_pk * Stricter, leaner DEBOUNCE_TYPE section in common_features.mk. Cleanup debounce_type.mkpull/5134/head 0.6.280
@ -0,0 +1,46 @@ | |||||
# Debounce algorithm | |||||
QMK supports multiple debounce algorithms through its debounce API. | |||||
The underlying debounce algorithm is determined by which matrix.c file you are using. | |||||
The logic for which debounce method called is below. It checks various defines that you have set in rules.mk | |||||
``` | |||||
DEBOUNCE_TYPE?= sym_g | |||||
VALID_DEBOUNCE_TYPES := sym_g eager_pk custom | |||||
ifeq ($(filter $(DEBOUNCE_TYPE),$(VALID_DEBOUNCE_TYPES)),) | |||||
$(error DEBOUNCE_TYPE="$(DEBOUNCE_TYPE)" is not a valid debounce algorithm) | |||||
endif | |||||
ifeq ($(strip $(DEBOUNCE_TYPE)), sym_g) | |||||
QUANTUM_SRC += $(DEBOUNCE_DIR)/debounce_sym_g.c | |||||
else ifeq ($(strip $(DEBOUNCE_TYPE)), eager_pk) | |||||
QUANTUM_SRC += $(DEBOUNCE_DIR)/debounce_eager_pk.c | |||||
endif | |||||
``` | |||||
# Debounce selection | |||||
| DEBOUNCE_ALGO | Description | What to do | | |||||
| ------------- | --------------------------------------------------- | ----------------------------- | | |||||
| Not defined | You are using the included matrix.c and debounce.c | Nothing. Debounce_sym_g will be compiled, and used if necessary | | |||||
| custom | Use your own debounce.c | ```SRC += debounce.c``` add your own debounce.c and implement necessary functions | | |||||
| sym_g / eager_pk | You are using the included matrix.c and debounce.c | Use an alternative debounce algorithm | | |||||
**Regarding split keyboards**: | |||||
The debounce code is compatible with split keyboards. | |||||
# Use your own debouncing code | |||||
* Set ```DEBOUNCE_TYPE = custom ```. | |||||
* Add ```SRC += debounce.c``` | |||||
* Add your own ```debounce.c```. Look at included ```debounce_sym_g.c```s for sample implementations. | |||||
* Debouncing occurs after every raw matrix scan. | |||||
* Use num_rows rather than MATRIX_ROWS, so that split keyboards are supported correctly. | |||||
# Changing between included debouncing methods | |||||
You can either use your own code, by including your own debounce.c, or switch to another included one. | |||||
Included debounce methods are: | |||||
* debounce_eager_pk - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE_DELAY``` millseconds of no further input for that key | |||||
* debounce_sym_g - debouncing per keyboard. On any state change, a global timer is set. When ```DEBOUNCE_DELAY``` milliseconds of no changes has occured, all input changes are pushed. | |||||
@ -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 |
@ -0,0 +1,121 @@ | |||||
/* | |||||
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 "matrix.h" | |||||
#include "timer.h" | |||||
#include "quantum.h" | |||||
#include <stdlib.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 debounce_counter_t *debounce_counters; | |||||
#define DEBOUNCE_ELAPSED 251 | |||||
#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1) | |||||
void update_debounce_counters(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 = timer_read() % MAX_DEBOUNCE; | |||||
update_debounce_counters(num_rows, current_time); | |||||
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(uint8_t num_rows, uint8_t current_time) | |||||
{ | |||||
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) { | |||||
*debounce_pointer = DEBOUNCE_ELAPSED; | |||||
} | |||||
} | |||||
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) | |||||
{ | |||||
debounce_counter_t *debounce_pointer = debounce_counters; | |||||
for (uint8_t row = 0; row < num_rows; row++) | |||||
{ | |||||
matrix_row_t existing_row = cooked[row]; | |||||
matrix_row_t raw_row = raw[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++; | |||||
} | |||||
cooked[row] = existing_row; | |||||
} | |||||
} | |||||
bool debounce_active(void) | |||||
{ | |||||
return true; | |||||
} | |||||
@ -0,0 +1,57 @@ | |||||
/* | |||||
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 "matrix.h" | |||||
#include "timer.h" | |||||
#include "quantum.h" | |||||
#ifndef DEBOUNCE | |||||
#define DEBOUNCE 5 | |||||
#endif | |||||
void debounce_init(uint8_t num_rows) {} | |||||
static bool debouncing = false; | |||||
#if DEBOUNCE > 0 | |||||
static uint16_t debouncing_time; | |||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) | |||||
{ | |||||
if (changed) { | |||||
debouncing = true; | |||||
debouncing_time = timer_read(); | |||||
} | |||||
if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { | |||||
for (int i = 0; i < num_rows; i++) { | |||||
cooked[i] = raw[i]; | |||||
} | |||||
debouncing = false; | |||||
} | |||||
} | |||||
#else //no debouncing. | |||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) | |||||
{ | |||||
for (int i = 0; i < num_rows; i++) { | |||||
cooked[i] = raw[i]; | |||||
} | |||||
} | |||||
#endif | |||||
bool debounce_active(void) { | |||||
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! |