2016-06-03 06:12:29 +00:00
/* debounce() function
Debounce uses multiple samples to debounces switch states ,
where each sample contains the switch states for a row of switches , one bit per switch .
Debounce uses Dr . Marty ' s debounce algorithm from
http : //drmarty.blogspot.com.br/2009/05/best-switch-debounce-routine-ever.html
2016-06-22 02:40:35 +00:00
SPI , I2C , and TWI protocols do not include any Packet Error Checking ( PEC ) .
2016-06-03 06:12:29 +00:00
The goal of Marty ' s debounce routine is to reject spurious signals ,
2016-06-22 02:40:35 +00:00
which is useful when connecting split keyboards with a cable using SPI , I2C , or TWI .
This class was tested on split keyboard with a 3 - meter long telephone wire to I / O expander .
2016-06-03 06:12:29 +00:00
Dr . Marty ' s debounce algorithm :
Periodically read samples and update the state when a number consecutive sample bits are equal .
2016-07-15 05:15:38 +00:00
Output from keybrd / examples / debounce_unit_test . cpp with SAMPLE_COUNT_MACRO 4 :
2016-06-03 06:12:29 +00:00
button pressed : 100000001111111110000
bouncy signal : 100001001111011110000
debounced signal : 000000000001111111110
isFallingEdge : 000000000000000000001
isRisingEdge : 000000000001000000000
2016-07-15 05:15:38 +00:00
There is a latency equal to SAMPLE_COUNT_MACRO , between button press and debounced signal .
2016-07-18 02:26:00 +00:00
2016-07-15 05:15:38 +00:00
samples [ SAMPLE_COUNT_MACRO ] is a ring buffer . samplesIndex is it ' s current write index .
SAMPLE_COUNT_MACRO is the number of consecutive equal samples needed to debounce .
SAMPLE_COUNT_MACRO is a macro because it defines samples [ SAMPLE_COUNT_MACRO ] array size at compile time .
SAMPLE_COUNT_MACRO is defined in config_keybrd . h and should be at lease 1.
2016-06-03 06:12:29 +00:00
2016-07-15 05:15:38 +00:00
SAMPLE_COUNT_MACRO = 4 is very reliable for a keyboard .
2016-06-22 02:40:35 +00:00
Split keyboards with a long connecting wire or in environment with
2016-07-15 05:15:38 +00:00
strong electromagnetic interference ( EMI ) may need a larger SAMPLE_COUNT_MACRO for reliability .
2016-06-03 06:12:29 +00:00
*/
2016-07-14 10:47:23 +00:00
# include "Debouncer_Samples.h"
2016-06-03 06:12:29 +00:00
2016-09-17 05:45:12 +00:00
/* debounce() sets debounced and returns debouncedChanged.
2016-09-17 21:47:37 +00:00
All parameters and variables are bit patterns .
2016-06-03 06:12:29 +00:00
For parameters , 1 means pressed , 0 means released .
For return , 1 means debounced changed .
*/
2016-07-14 10:47:23 +00:00
read_pins_t Debouncer_Samples : : debounce ( const read_pins_t rawSignal , read_pins_t & debounced )
2016-06-03 06:12:29 +00:00
{
2016-09-17 21:47:37 +00:00
read_pins_t previousDebounced ; //bits, 1 means pressed, 0 means released
read_pins_t all_1 = ~ 0 ; //bits
read_pins_t all_0 = 0 ; //bits
2016-06-03 06:12:29 +00:00
samples [ samplesIndex ] = rawSignal ; //insert rawSignal into samples[] ring buffer
2016-07-15 05:15:38 +00:00
if ( + + samplesIndex > = SAMPLE_COUNT_MACRO ) //if end of ring buffer
2016-06-03 06:12:29 +00:00
{
samplesIndex = 0 ; //wrap samplesIndex to beginning of ring buffer
}
2016-07-15 05:15:38 +00:00
for ( uint8_t j = 0 ; j < SAMPLE_COUNT_MACRO ; j + + ) //traverse the sample[] ring buffer
2016-06-03 06:12:29 +00:00
{
all_1 & = samples [ j ] ; //1 if all samples are 1
all_0 | = samples [ j ] ; //0 if all samples are 0
}
previousDebounced = debounced ;
// update debounced if all the samples agree with one another
// if all samples=1 then debounced=1
// elseif all samples=0 then debounced=0
// else debounced=previousDebounced i.e. no change
debounced = all_1 | ( all_0 & previousDebounced ) ;
return debounced xor previousDebounced ;
}