Added debouncing

This commit is contained in:
David Volovskiy 2024-07-29 07:39:51 -04:00
parent 226cda748c
commit 4375ca37e0
2 changed files with 45 additions and 16 deletions

View file

@ -183,6 +183,17 @@ static inline void _movement_disable_fast_tick_if_possible(void) {
} }
} }
#define DEBOUNCE_FREQ 64 // 64 HZ is 15.625ms
static void cb_debounce(void) {
movement_state.debounce_occurring = false;
watch_rtc_disable_periodic_callback(DEBOUNCE_FREQ);
}
static inline void _movement_enable_debounce_tick(void) {
movement_state.debounce_occurring = true;
watch_rtc_register_periodic_callback(cb_debounce, DEBOUNCE_FREQ);
}
static void _movement_handle_background_tasks(void) { static void _movement_handle_background_tasks(void) {
for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) { for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) {
// For each face, if the watch face wants a background task... // For each face, if the watch face wants a background task...
@ -222,16 +233,28 @@ static void _movement_handle_scheduled_tasks(void) {
} }
} }
static uint8_t swap_endian(uint8_t num) {
uint8_t result = 0;
int i;
for (i = 0; i < 8; i++) {
result <<= 1;
result |= (num & 1);
num >>= 1;
}
return result;
}
void movement_request_tick_frequency(uint8_t freq) { void movement_request_tick_frequency(uint8_t freq) {
// Movement uses the 128 Hz tick internally // Movement uses the 128 Hz tick internally
if (freq == 128) return; if (freq == 128 || freq == DEBOUNCE_FREQ ) return;
// Movement requires at least a 1 Hz tick. // Movement requires at least a 1 Hz tick.
// If we are asked for an invalid frequency, default back to 1 Hz. // If we are asked for an invalid frequency, default back to 1 Hz.
if (freq == 0 || __builtin_popcount(freq) != 1) freq = 1; if (freq == 0 || __builtin_popcount(freq) != 1) freq = 1;
// disable all callbacks except the 128 Hz one // disable all callbacks except the 128 Hz one
watch_rtc_disable_matching_periodic_callbacks(0xFE); int disable_mask = 0xFE ^ swap_endian(DEBOUNCE_FREQ);
watch_rtc_disable_matching_periodic_callbacks(disable_mask);
movement_state.subsecond = 0; movement_state.subsecond = 0;
movement_state.tick_frequency = freq; movement_state.tick_frequency = freq;
@ -614,6 +637,8 @@ bool app_loop(void) {
static movement_event_type_t _figure_out_button_event(bool pin_level, movement_event_type_t button_down_event_type, uint16_t *down_timestamp) { static movement_event_type_t _figure_out_button_event(bool pin_level, movement_event_type_t button_down_event_type, uint16_t *down_timestamp) {
// force alarm off if the user pressed a button. // force alarm off if the user pressed a button.
if (movement_state.alarm_ticks) movement_state.alarm_ticks = 0; if (movement_state.alarm_ticks) movement_state.alarm_ticks = 0;
if ( movement_state.debounce_occurring)
return EVENT_NONE;
if (pin_level) { if (pin_level) {
// handle rising edge // handle rising edge
@ -628,6 +653,7 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e
uint16_t diff = movement_state.fast_ticks - *down_timestamp; uint16_t diff = movement_state.fast_ticks - *down_timestamp;
*down_timestamp = 0; *down_timestamp = 0;
_movement_disable_fast_tick_if_possible(); _movement_disable_fast_tick_if_possible();
_movement_enable_debounce_tick();
// any press over a half second is considered a long press. Fire the long-up event // any press over a half second is considered a long press. Fire the long-up event
if (diff > MOVEMENT_LONG_PRESS_TICKS) return button_down_event_type + 3; if (diff > MOVEMENT_LONG_PRESS_TICKS) return button_down_event_type + 3;
else return button_down_event_type + 1; else return button_down_event_type + 1;
@ -663,20 +689,22 @@ void cb_alarm_fired(void) {
void cb_fast_tick(void) { void cb_fast_tick(void) {
movement_state.fast_ticks++; movement_state.fast_ticks++;
if (movement_state.light_ticks > 0) movement_state.light_ticks--; if (!movement_state.debounce_occurring) {
if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--; if (movement_state.light_ticks > 0) movement_state.light_ticks--;
// check timestamps and auto-fire the long-press events if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--;
// Notice: is it possible that two or more buttons have an identical timestamp? In this case // check timestamps and auto-fire the long-press events
// only one of these buttons would receive the long press event. Don't bother for now... // Notice: is it possible that two or more buttons have an identical timestamp? In this case
if (movement_state.light_down_timestamp > 0) // only one of these buttons would receive the long press event. Don't bother for now...
if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) if (movement_state.light_down_timestamp > 0)
event.event_type = EVENT_LIGHT_LONG_PRESS; if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1)
if (movement_state.mode_down_timestamp > 0) event.event_type = EVENT_LIGHT_LONG_PRESS;
if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) if (movement_state.mode_down_timestamp > 0)
event.event_type = EVENT_MODE_LONG_PRESS; if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1)
if (movement_state.alarm_down_timestamp > 0) event.event_type = EVENT_MODE_LONG_PRESS;
if (movement_state.fast_ticks - movement_state.alarm_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) if (movement_state.alarm_down_timestamp > 0)
event.event_type = EVENT_ALARM_LONG_PRESS; if (movement_state.fast_ticks - movement_state.alarm_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1)
event.event_type = EVENT_ALARM_LONG_PRESS;
}
// this is just a fail-safe; fast tick should be disabled as soon as the button is up, the LED times out, and/or the alarm finishes. // this is just a fail-safe; fast tick should be disabled as soon as the button is up, the LED times out, and/or the alarm finishes.
// but if for whatever reason it isn't, this forces the fast tick off after 20 seconds. // but if for whatever reason it isn't, this forces the fast tick off after 20 seconds.
if (movement_state.fast_ticks >= 128 * 20) { if (movement_state.fast_ticks >= 128 * 20) {

View file

@ -267,6 +267,7 @@ typedef struct {
bool needs_background_tasks_handled; bool needs_background_tasks_handled;
bool has_scheduled_background_task; bool has_scheduled_background_task;
bool needs_wake; bool needs_wake;
bool debounce_occurring;
// low energy mode countdown // low energy mode countdown
int32_t le_mode_ticks; int32_t le_mode_ticks;