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 ;
2022-07-07 10:00:40 +02:00
static bool cooked_changed ;
2019-04-04 08:45:55 +11:00
2021-11-01 19:18:33 +00: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 ;
}
2022-07-07 10:00:40 +02:00
bool 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 ;
2022-07-07 10:00:40 +02:00
cooked_changed = false ;
2021-06-09 08:23:21 +01:00
2019-08-30 11:19:03 -07:00
if ( counters_need_update ) {
2021-11-01 19:18:33 +00:00
fast_timer_t now = timer_read_fast ( ) ;
2021-06-09 08:23:21 +01:00
fast_timer_t elapsed_time = TIMER_DIFF_FAST ( now , last_time ) ;
2021-11-01 19:18:33 +00:00
last_time = now ;
2021-06-09 08:23:21 +01:00
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
}
2022-07-07 10:00:40 +02:00
return cooked_changed ;
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 ) {
2021-11-01 19:18:33 +00: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 ) {
2022-07-07 10:00:40 +02:00
* debounce_pointer = DEBOUNCE ;
cooked [ row ] = raw_row ;
cooked_changed | = cooked [ row ] ^ raw [ row ] ;
2019-08-30 11:19:03 -07:00
counters_need_update = true ;
}
}
debounce_pointer + + ;
2019-04-04 08:45:55 +11:00
}
}
2021-06-09 08:23:21 +01:00
# else
# include "none.c"
# endif