Archived
1
0

Adding timing based debounce code

- Uses expiry timer to decide on when to allow a state change
- Initial state transitions are unaffected
- Use MinDebounceTime define in kll to configure
- ms granularity
This commit is contained in:
Jacob Alexander 2015-06-19 01:50:56 -07:00
parent f708ce720c
commit 98f796d4df
3 changed files with 54 additions and 7 deletions

View File

@ -32,3 +32,10 @@ DebounceThrottleDiv => DebounceThrottleDiv_define;
DebounceThrottleDiv = 0; # Default DebounceThrottleDiv = 0; # Default
#DebounceThrottleDiv = 2; # /4 divider #DebounceThrottleDiv = 2; # /4 divider
# This defines the minimum amount of time after a transition until allowing another transition
# Generally switches require a minimum 5 ms debounce period
# Since a decision can usually be made quite quickly, there is little latency on each press
# However, this defines the latency at which the switch state can change
MinDebounceTime => MinDebounceTime_define;
MinDebounceTime = 5; # 5 ms

View File

@ -82,6 +82,9 @@ uint16_t matrixMaxScans = 0;
uint16_t matrixCurScans = 0; uint16_t matrixCurScans = 0;
uint16_t matrixPrevScans = 0; uint16_t matrixPrevScans = 0;
// System Timer used for delaying debounce decisions
extern volatile uint32_t systick_millis_count;
// ----- Functions ----- // ----- Functions -----
@ -197,10 +200,11 @@ void Matrix_setup()
// Clear out Debounce Array // Clear out Debounce Array
for ( uint8_t item = 0; item < Matrix_maxKeys; item++ ) for ( uint8_t item = 0; item < Matrix_maxKeys; item++ )
{ {
Matrix_scanArray[ item ].prevState = KeyState_Off; Matrix_scanArray[ item ].prevState = KeyState_Off;
Matrix_scanArray[ item ].curState = KeyState_Off; Matrix_scanArray[ item ].curState = KeyState_Off;
Matrix_scanArray[ item ].activeCount = 0; Matrix_scanArray[ item ].activeCount = 0;
Matrix_scanArray[ item ].inactiveCount = DebounceDivThreshold_define; // Start at 'off' steady state Matrix_scanArray[ item ].inactiveCount = DebounceDivThreshold_define; // Start at 'off' steady state
Matrix_scanArray[ item ].prevDecisionTime = 0;
} }
// Clear scan stats counters // Clear scan stats counters
@ -262,6 +266,9 @@ void Matrix_scan( uint16_t scanNum )
matrixCurScans++; matrixCurScans++;
} }
// Read systick for event scheduling
uint8_t currentTime = (uint8_t)systick_millis_count;
// For each strobe, scan each of the sense pins // For each strobe, scan each of the sense pins
for ( uint8_t strobe = 0; strobe < Matrix_colsNum; strobe++ ) for ( uint8_t strobe = 0; strobe < Matrix_colsNum; strobe++ )
{ {
@ -305,11 +312,16 @@ void Matrix_scan( uint16_t scanNum )
} }
// Check for state change if it hasn't been set // Check for state change if it hasn't been set
// But only if enough time has passed since last state change
// Only check if the minimum number of scans has been met // Only check if the minimum number of scans has been met
// the current state is invalid // the current state is invalid
// and either active or inactive count is over the debounce threshold // and either active or inactive count is over the debounce threshold
if ( state->curState == KeyState_Invalid ) if ( state->curState == KeyState_Invalid )
{ {
// Determine time since last decision
uint8_t lastTransition = currentTime - state->prevDecisionTime;
// Attempt state transition
switch ( state->prevState ) switch ( state->prevState )
{ {
case KeyState_Press: case KeyState_Press:
@ -320,6 +332,15 @@ void Matrix_scan( uint16_t scanNum )
} }
else else
{ {
// If not enough time has passed since Hold
// Keep previous state
if ( lastTransition < MinDebounceTime_define )
{
//warn_print("FAST Release stopped");
state->curState = state->prevState;
continue;
}
state->curState = KeyState_Release; state->curState = KeyState_Release;
} }
break; break;
@ -328,6 +349,15 @@ void Matrix_scan( uint16_t scanNum )
case KeyState_Off: case KeyState_Off:
if ( state->activeCount > state->inactiveCount ) if ( state->activeCount > state->inactiveCount )
{ {
// If not enough time has passed since Hold
// Keep previous state
if ( lastTransition < MinDebounceTime_define )
{
//warn_print("FAST Press stopped");
state->curState = state->prevState;
continue;
}
state->curState = KeyState_Press; state->curState = KeyState_Press;
} }
else else
@ -342,6 +372,9 @@ void Matrix_scan( uint16_t scanNum )
break; break;
} }
// Update decision time
state->prevDecisionTime = currentTime;
// Send keystate to macro module // Send keystate to macro module
Macro_keyState( key, state->curState ); Macro_keyState( key, state->curState );

View File

@ -40,6 +40,12 @@
#error "Debounce threshold is too high... 32 bit max. Check .kll defines." #error "Debounce threshold is too high... 32 bit max. Check .kll defines."
#endif #endif
#if ( MinDebounceTime_define > 0xFF )
#error "MinDebounceTime is a maximum of 255 ms"
#elif ( MinDebounceTime_define < 0x00 )
#error "MinDebounceTime is a minimum 0 ms"
#endif
// ----- Enums ----- // ----- Enums -----
@ -126,11 +132,12 @@ typedef struct GPIO_Pin {
// Debounce Element // Debounce Element
typedef struct KeyState { typedef struct KeyState {
KeyPosition prevState;
KeyPosition curState;
DebounceCounter activeCount; DebounceCounter activeCount;
DebounceCounter inactiveCount; DebounceCounter inactiveCount;
} KeyState; KeyPosition prevState;
KeyPosition curState;
uint8_t prevDecisionTime;
} __attribute__((packed)) KeyState;