DebounceThrottleDiv = 0; # Default
#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
+
uint16_t matrixCurScans = 0;
uint16_t matrixPrevScans = 0;
+// System Timer used for delaying debounce decisions
+extern volatile uint32_t systick_millis_count;
+
// ----- Functions -----
// Clear out Debounce Array
for ( uint8_t item = 0; item < Matrix_maxKeys; item++ )
{
- Matrix_scanArray[ item ].prevState = KeyState_Off;
- Matrix_scanArray[ item ].curState = KeyState_Off;
- Matrix_scanArray[ item ].activeCount = 0;
- Matrix_scanArray[ item ].inactiveCount = DebounceDivThreshold_define; // Start at 'off' steady state
+ Matrix_scanArray[ item ].prevState = KeyState_Off;
+ Matrix_scanArray[ item ].curState = KeyState_Off;
+ Matrix_scanArray[ item ].activeCount = 0;
+ Matrix_scanArray[ item ].inactiveCount = DebounceDivThreshold_define; // Start at 'off' steady state
+ Matrix_scanArray[ item ].prevDecisionTime = 0;
}
// Clear scan stats counters
matrixCurScans++;
}
+ // Read systick for event scheduling
+ uint8_t currentTime = (uint8_t)systick_millis_count;
+
// For each strobe, scan each of the sense pins
for ( uint8_t strobe = 0; strobe < Matrix_colsNum; strobe++ )
{
}
// 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
// the current state is invalid
// and either active or inactive count is over the debounce threshold
if ( state->curState == KeyState_Invalid )
{
+ // Determine time since last decision
+ uint8_t lastTransition = currentTime - state->prevDecisionTime;
+
+ // Attempt state transition
switch ( state->prevState )
{
case KeyState_Press:
}
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;
}
break;
case KeyState_Off:
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;
}
else
break;
}
+ // Update decision time
+ state->prevDecisionTime = currentTime;
+
// Send keystate to macro module
Macro_keyState( key, state->curState );
#error "Debounce threshold is too high... 32 bit max. Check .kll defines."
#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 -----
// Debounce Element
typedef struct KeyState {
- KeyPosition prevState;
- KeyPosition curState;
DebounceCounter activeCount;
DebounceCounter inactiveCount;
-} KeyState;
+ KeyPosition prevState;
+ KeyPosition curState;
+ uint8_t prevDecisionTime;
+} __attribute__((packed)) KeyState;