2019-04-04 08:45:55 +11:00
/*
Copyright 2019 Alex Ong<the.onga@gmail.com>
2021-06-09 08:23:21 +01:00
Copyright 2021 Simon Arlott
2019-04-04 08:45:55 +11:00
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.
*/
#include "matrix.h"
#include "timer.h"
#include "quantum.h"
#include <stdlib.h>
2021-01-30 15:13:56 +11:00
#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
2019-04-04 08:45:55 +11:00
#ifndef DEBOUNCE
2019-08-30 11:19:03 -07:00
# define DEBOUNCE 5
2019-04-04 08:45:55 +11:00
#endif
2021-06-09 08:23:21 +01:00
// Maximum debounce: 255ms
#if DEBOUNCE > UINT8_MAX
# undef DEBOUNCE
# define DEBOUNCE UINT8_MAX
#endif
typedef uint8_t debounce_counter_t ;
#if DEBOUNCE > 0
2019-08-30 11:19:03 -07:00
static bool matrix_need_update ;
2019-04-04 08:45:55 +11:00
static debounce_counter_t * debounce_counters ;
2021-06-09 08:23:21 +01:00
static fast_timer_t last_time ;
2019-04-16 05:58:03 +10:00
static bool counters_need_update ;
2019-04-04 08:45:55 +11:00
2021-06-09 08:23:21 +01:00
#define DEBOUNCE_ELAPSED 0
2019-04-04 08:45:55 +11:00
2021-06-09 08:23:21 +01:00
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 );
2019-04-04 08:45:55 +11:00
2019-04-16 05:58:03 +10:00
// we use num_rows rather than MATRIX_ROWS to support split keyboards
void debounce_init ( uint8_t num_rows ) {
2019-08-30 11:19:03 -07:00
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 ;
}
2019-04-04 08:45:55 +11:00
}
2021-06-09 08:23:21 +01:00
void debounce_free ( void ) {
free ( debounce_counters );
debounce_counters = NULL ;
}
2019-04-16 05:58:03 +10:00
void debounce ( matrix_row_t raw [], matrix_row_t cooked [], uint8_t num_rows , bool changed ) {
2021-06-09 08:23:21 +01:00
bool updated_last = false ;
2019-08-30 11:19:03 -07:00
if ( counters_need_update ) {
2021-06-09 08:23:21 +01:00
fast_timer_t now = timer_read_fast ();
fast_timer_t elapsed_time = TIMER_DIFF_FAST ( now , last_time );
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 );
}
2019-08-30 11:19:03 -07:00
}
2019-04-16 05:58:03 +10:00
2021-06-09 08:23:21 +01:00
if ( changed || matrix_need_update ) {
if ( ! updated_last ) {
last_time = timer_read_fast ();
}
transfer_matrix_values ( raw , cooked , num_rows );
2019-08-30 11:19:03 -07:00
}
2019-04-04 08:45:55 +11:00
}
2019-04-16 05:58:03 +10:00
// If the current time is > debounce counter, set the counter to enable input.
2021-06-09 08:23:21 +01:00
static void update_debounce_counters ( uint8_t num_rows , uint8_t elapsed_time ) {
2019-08-30 11:19:03 -07:00
counters_need_update = false ;
2021-06-09 08:23:21 +01:00
matrix_need_update = false ;
2019-08-30 11:19:03 -07:00
debounce_counter_t * debounce_pointer = debounce_counters ;
for ( uint8_t row = 0 ; row < num_rows ; row ++ ) {
if ( * debounce_pointer != DEBOUNCE_ELAPSED ) {
2021-06-09 08:23:21 +01:00
if ( * debounce_pointer <= elapsed_time ) {
2019-08-30 11:19:03 -07:00
* debounce_pointer = DEBOUNCE_ELAPSED ;
2021-06-09 08:23:21 +01:00
matrix_need_update = true ;
2019-08-30 11:19:03 -07:00
} else {
2021-06-09 08:23:21 +01:00
* debounce_pointer -= elapsed_time ;
2019-08-30 11:19:03 -07:00
counters_need_update = true ;
}
}
debounce_pointer ++ ;
2019-04-04 08:45:55 +11:00
}
}
// upload from raw_matrix to final matrix;
2021-06-09 08:23:21 +01:00
static void transfer_matrix_values ( matrix_row_t raw [], matrix_row_t cooked [], uint8_t num_rows ) {
2019-08-30 11:19:03 -07:00
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 ];
2019-04-16 05:58:03 +10:00
2019-08-30 11:19:03 -07:00
// determine new value basd on debounce pointer + raw value
if ( existing_row != raw_row ) {
if ( * debounce_pointer == DEBOUNCE_ELAPSED ) {
2021-06-09 08:23:21 +01:00
* debounce_pointer = DEBOUNCE ;
2019-08-30 11:19:03 -07:00
cooked [ row ] = raw_row ;
counters_need_update = true ;
}
}
debounce_pointer ++ ;
2019-04-04 08:45:55 +11:00
}
}
2019-04-16 05:58:03 +10:00
bool debounce_active ( void ) { return true ; }
2021-06-09 08:23:21 +01:00
#else
# include "none.c"
#endif