From 4375ca37e0ccfd60602cade0a571c363c80c58c1 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 07:39:51 -0400 Subject: [PATCH 01/19] Added debouncing --- movement/movement.c | 60 +++++++++++++++++++++++++++++++++------------ movement/movement.h | 1 + 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index cb3dcf78e..cfe914abd 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -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) { for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) { // 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) { // 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. // If we are asked for an invalid frequency, default back to 1 Hz. if (freq == 0 || __builtin_popcount(freq) != 1) freq = 1; // 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.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) { // force alarm off if the user pressed a button. if (movement_state.alarm_ticks) movement_state.alarm_ticks = 0; + if ( movement_state.debounce_occurring) + return EVENT_NONE; if (pin_level) { // 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; *down_timestamp = 0; _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 if (diff > MOVEMENT_LONG_PRESS_TICKS) return button_down_event_type + 3; else return button_down_event_type + 1; @@ -663,20 +689,22 @@ void cb_alarm_fired(void) { void cb_fast_tick(void) { movement_state.fast_ticks++; - if (movement_state.light_ticks > 0) movement_state.light_ticks--; - if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--; - // check timestamps and auto-fire the long-press events - // Notice: is it possible that two or more buttons have an identical timestamp? In this case - // only one of these buttons would receive the long press event. Don't bother for now... - if (movement_state.light_down_timestamp > 0) - if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) - event.event_type = EVENT_LIGHT_LONG_PRESS; - if (movement_state.mode_down_timestamp > 0) - if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) - event.event_type = EVENT_MODE_LONG_PRESS; - if (movement_state.alarm_down_timestamp > 0) - if (movement_state.fast_ticks - movement_state.alarm_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) - event.event_type = EVENT_ALARM_LONG_PRESS; + if (!movement_state.debounce_occurring) { + if (movement_state.light_ticks > 0) movement_state.light_ticks--; + if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--; + // check timestamps and auto-fire the long-press events + // Notice: is it possible that two or more buttons have an identical timestamp? In this case + // only one of these buttons would receive the long press event. Don't bother for now... + if (movement_state.light_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_LIGHT_LONG_PRESS; + if (movement_state.mode_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_MODE_LONG_PRESS; + if (movement_state.alarm_down_timestamp > 0) + 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. // but if for whatever reason it isn't, this forces the fast tick off after 20 seconds. if (movement_state.fast_ticks >= 128 * 20) { diff --git a/movement/movement.h b/movement/movement.h index 1dabfbc5b..56dfc7dce 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -267,6 +267,7 @@ typedef struct { bool needs_background_tasks_handled; bool has_scheduled_background_task; bool needs_wake; + bool debounce_occurring; // low energy mode countdown int32_t le_mode_ticks; From 7d5aaf60caa943a248a7f635111ddfd50c230389 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 07:44:31 -0400 Subject: [PATCH 02/19] Leaving sleep with alarm button up doesn't trigger alarm button --- movement/movement.c | 9 ++++++++- movement/movement.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/movement/movement.c b/movement/movement.c index cfe914abd..87110da42 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -490,6 +490,7 @@ static void _sleep_mode_app_loop(void) { // we also have to handle background tasks here in the mini-runloop if (movement_state.needs_background_tasks_handled) _movement_handle_background_tasks(); + movement_state.ignore_alarm_after_sleep = true; event.event_type = EVENT_LOW_ENERGY_UPDATE; watch_faces[movement_state.current_face_idx].loop(event, &movement_state.settings, watch_face_contexts[movement_state.current_face_idx]); @@ -675,9 +676,15 @@ void cb_mode_btn_interrupt(void) { void cb_alarm_btn_interrupt(void) { bool pin_level = watch_get_pin_level(BTN_ALARM); _movement_reset_inactivity_countdown(); - event.event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); + uint8_t event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); + if (movement_state.ignore_alarm_after_sleep){ + if (event_type == EVENT_ALARM_BUTTON_UP) movement_state.ignore_alarm_after_sleep = false; + return; + } + event.event_type = event_type; } + void cb_alarm_btn_extwake(void) { // wake up! _movement_reset_inactivity_countdown(); diff --git a/movement/movement.h b/movement/movement.h index 56dfc7dce..1af897537 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -271,6 +271,7 @@ typedef struct { // low energy mode countdown int32_t le_mode_ticks; + bool ignore_alarm_after_sleep; // app resignation countdown (TODO: consolidate with LE countdown?) int16_t timeout_ticks; From df2dac5a073537fc45657f5310a68f33884804aa Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 18:12:46 -0400 Subject: [PATCH 03/19] debouince now uses cb_fast_tick and holding the button now also gets debounced --- movement/movement.c | 106 ++++++++++++++++++++++++++++---------------- movement/movement.h | 9 +++- 2 files changed, 74 insertions(+), 41 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 87110da42..9f6f2959e 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -183,17 +183,6 @@ 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) { for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) { // For each face, if the watch face wants a background task... @@ -409,6 +398,9 @@ void app_init(void) { movement_state.settings.bit.led_duration = MOVEMENT_DEFAULT_LED_DURATION; movement_state.light_ticks = -1; movement_state.alarm_ticks = -1; + movement_state.debounce_ticks_light = -1; + movement_state.debounce_ticks_alarm = -1; + movement_state.debounce_ticks_mode = -1; movement_state.next_available_backup_register = 4; _movement_reset_inactivity_countdown(); @@ -485,12 +477,12 @@ void app_wake_from_standby(void) { static void _sleep_mode_app_loop(void) { movement_state.needs_wake = false; + movement_state.ignore_alarm_btn_after_sleep = true; // as long as le_mode_ticks is -1 (i.e. we are in low energy mode), we wake up here, update the screen, and go right back to sleep. while (movement_state.le_mode_ticks == -1) { // we also have to handle background tasks here in the mini-runloop if (movement_state.needs_background_tasks_handled) _movement_handle_background_tasks(); - movement_state.ignore_alarm_after_sleep = true; event.event_type = EVENT_LOW_ENERGY_UPDATE; watch_faces[movement_state.current_face_idx].loop(event, &movement_state.settings, watch_face_contexts[movement_state.current_face_idx]); @@ -638,8 +630,6 @@ 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) { // force alarm off if the user pressed a button. if (movement_state.alarm_ticks) movement_state.alarm_ticks = 0; - if ( movement_state.debounce_occurring) - return EVENT_NONE; if (pin_level) { // handle rising edge @@ -654,36 +644,49 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e uint16_t diff = movement_state.fast_ticks - *down_timestamp; *down_timestamp = 0; _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 if (diff > MOVEMENT_LONG_PRESS_TICKS) return button_down_event_type + 3; else return button_down_event_type + 1; } } -void cb_light_btn_interrupt(void) { - bool pin_level = watch_get_pin_level(BTN_LIGHT); +static void light_btn_action(bool pin_level) { _movement_reset_inactivity_countdown(); event.event_type = _figure_out_button_event(pin_level, EVENT_LIGHT_BUTTON_DOWN, &movement_state.light_down_timestamp); } -void cb_mode_btn_interrupt(void) { - bool pin_level = watch_get_pin_level(BTN_MODE); +static void mode_btn_action(bool pin_level) { _movement_reset_inactivity_countdown(); event.event_type = _figure_out_button_event(pin_level, EVENT_MODE_BUTTON_DOWN, &movement_state.mode_down_timestamp); } -void cb_alarm_btn_interrupt(void) { - bool pin_level = watch_get_pin_level(BTN_ALARM); +static void alarm_btn_action(bool pin_level) { _movement_reset_inactivity_countdown(); uint8_t event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); - if (movement_state.ignore_alarm_after_sleep){ - if (event_type == EVENT_ALARM_BUTTON_UP) movement_state.ignore_alarm_after_sleep = false; + if (movement_state.ignore_alarm_btn_after_sleep){ + if (event_type == EVENT_ALARM_BUTTON_UP || event_type == EVENT_ALARM_LONG_UP) movement_state.ignore_alarm_btn_after_sleep = false; return; } event.event_type = event_type; } +void cb_light_btn_interrupt(void) { + movement_state.debounce_prev_pin_light = watch_get_pin_level(BTN_LIGHT); + movement_state.debounce_ticks_light = 1; + _movement_enable_fast_tick_if_needed(); +} + +void cb_mode_btn_interrupt(void) { + movement_state.debounce_prev_pin_mode = watch_get_pin_level(BTN_MODE); + movement_state.debounce_ticks_mode = 1; + _movement_enable_fast_tick_if_needed(); +} + +void cb_alarm_btn_interrupt(void) { + movement_state.debounce_prev_pin_alarm = watch_get_pin_level(BTN_ALARM); + movement_state.debounce_ticks_alarm = 1; + _movement_enable_fast_tick_if_needed(); +} void cb_alarm_btn_extwake(void) { // wake up! @@ -695,23 +698,48 @@ void cb_alarm_fired(void) { } void cb_fast_tick(void) { - movement_state.fast_ticks++; - if (!movement_state.debounce_occurring) { - if (movement_state.light_ticks > 0) movement_state.light_ticks--; - if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--; - // check timestamps and auto-fire the long-press events - // Notice: is it possible that two or more buttons have an identical timestamp? In this case - // only one of these buttons would receive the long press event. Don't bother for now... - if (movement_state.light_down_timestamp > 0) - if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) - event.event_type = EVENT_LIGHT_LONG_PRESS; - if (movement_state.mode_down_timestamp > 0) - if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) - event.event_type = EVENT_MODE_LONG_PRESS; - if (movement_state.alarm_down_timestamp > 0) - if (movement_state.fast_ticks - movement_state.alarm_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) - event.event_type = EVENT_ALARM_LONG_PRESS; + if (movement_state.debounce_ticks_light == 0) { + if (movement_state.debounce_prev_pin_light == watch_get_pin_level(BTN_LIGHT)) + light_btn_action(movement_state.debounce_prev_pin_light); + movement_state.debounce_ticks_light = -1; + } + else if (movement_state.debounce_ticks_light > 0) { + movement_state.debounce_ticks_light--; + return; } + if (movement_state.debounce_ticks_alarm == 0) { + if (movement_state.debounce_prev_pin_alarm == watch_get_pin_level(BTN_ALARM)) + alarm_btn_action(movement_state.debounce_prev_pin_alarm); + movement_state.debounce_ticks_alarm = -1; + } + else if (movement_state.debounce_ticks_alarm > 0) { + movement_state.debounce_ticks_alarm--; + return; + } + if (movement_state.debounce_ticks_mode == 0) { + if (movement_state.debounce_prev_pin_mode == watch_get_pin_level(BTN_MODE)) + mode_btn_action(movement_state.debounce_prev_pin_mode); + movement_state.debounce_ticks_mode = -1; + } + else if (movement_state.debounce_ticks_mode > 0) { + movement_state.debounce_ticks_mode--; + return; + } + movement_state.fast_ticks++; + if (movement_state.light_ticks > 0) movement_state.light_ticks--; + if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--; + // check timestamps and auto-fire the long-press events + // Notice: is it possible that two or more buttons have an identical timestamp? In this case + // only one of these buttons would receive the long press event. Don't bother for now... + if (movement_state.light_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_LIGHT_LONG_PRESS; + if (movement_state.mode_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_MODE_LONG_PRESS; + if (movement_state.alarm_down_timestamp > 0) + 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. // but if for whatever reason it isn't, this forces the fast tick off after 20 seconds. if (movement_state.fast_ticks >= 128 * 20) { diff --git a/movement/movement.h b/movement/movement.h index 1af897537..3601d48c5 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -267,11 +267,16 @@ typedef struct { bool needs_background_tasks_handled; bool has_scheduled_background_task; bool needs_wake; - bool debounce_occurring; // low energy mode countdown int32_t le_mode_ticks; - bool ignore_alarm_after_sleep; + int8_t debounce_ticks_light; + int8_t debounce_ticks_alarm; + int8_t debounce_ticks_mode; + bool debounce_prev_pin_light; + bool debounce_prev_pin_alarm; + bool debounce_prev_pin_mode; + bool ignore_alarm_btn_after_sleep; // app resignation countdown (TODO: consolidate with LE countdown?) int16_t timeout_ticks; From 4a4fce428e3230099977d1dc674865f1d08613d5 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 18:24:58 -0400 Subject: [PATCH 04/19] Removed some dead code --- movement/movement.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 9f6f2959e..6bcbf6358 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -222,28 +222,16 @@ 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) { // Movement uses the 128 Hz tick internally - if (freq == 128 || freq == DEBOUNCE_FREQ ) return; + if (freq == 128) return; // Movement requires at least a 1 Hz tick. // If we are asked for an invalid frequency, default back to 1 Hz. if (freq == 0 || __builtin_popcount(freq) != 1) freq = 1; // disable all callbacks except the 128 Hz one - int disable_mask = 0xFE ^ swap_endian(DEBOUNCE_FREQ); - watch_rtc_disable_matching_periodic_callbacks(disable_mask); + watch_rtc_disable_matching_periodic_callbacks(0xFE); movement_state.subsecond = 0; movement_state.tick_frequency = freq; From 947e299494fb34f44daf956d95e9c79769af683b Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 20:13:54 -0400 Subject: [PATCH 05/19] Made the debounce register rising edges rather than falling edges --- movement/movement.c | 87 ++++++++++++++++++++++++++------------------- movement/movement.h | 12 +++---- 2 files changed, 56 insertions(+), 43 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 6bcbf6358..f6657923f 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -99,6 +99,8 @@ #include #endif +#define DEBOUNCE_TICKS 2 // In terms of *7.8125ms + movement_state_t movement_state; void * watch_face_contexts[MOVEMENT_NUM_FACES]; watch_date_time scheduled_tasks[MOVEMENT_NUM_FACES]; @@ -169,6 +171,9 @@ static inline void _movement_reset_inactivity_countdown(void) { static inline void _movement_enable_fast_tick_if_needed(void) { if (!movement_state.fast_tick_enabled) { movement_state.fast_ticks = 0; + movement_state.debounce_ticks_light = 0; + movement_state.debounce_ticks_alarm = 0; + movement_state.debounce_ticks_mode = 0; watch_rtc_register_periodic_callback(cb_fast_tick, 128); movement_state.fast_tick_enabled = true; } @@ -386,9 +391,6 @@ void app_init(void) { movement_state.settings.bit.led_duration = MOVEMENT_DEFAULT_LED_DURATION; movement_state.light_ticks = -1; movement_state.alarm_ticks = -1; - movement_state.debounce_ticks_light = -1; - movement_state.debounce_ticks_alarm = -1; - movement_state.debounce_ticks_mode = -1; movement_state.next_available_backup_register = 4; _movement_reset_inactivity_countdown(); @@ -638,17 +640,20 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e } } -static void light_btn_action(bool pin_level) { +static void light_btn_action(void) { + bool pin_level = watch_get_pin_level(BTN_LIGHT); _movement_reset_inactivity_countdown(); event.event_type = _figure_out_button_event(pin_level, EVENT_LIGHT_BUTTON_DOWN, &movement_state.light_down_timestamp); } -static void mode_btn_action(bool pin_level) { +static void mode_btn_action(void) { + bool pin_level = watch_get_pin_level(BTN_MODE); _movement_reset_inactivity_countdown(); event.event_type = _figure_out_button_event(pin_level, EVENT_MODE_BUTTON_DOWN, &movement_state.mode_down_timestamp); } -static void alarm_btn_action(bool pin_level) { +static void alarm_btn_action(void) { + bool pin_level = watch_get_pin_level(BTN_ALARM); _movement_reset_inactivity_countdown(); uint8_t event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); if (movement_state.ignore_alarm_btn_after_sleep){ @@ -659,20 +664,17 @@ static void alarm_btn_action(bool pin_level) { } void cb_light_btn_interrupt(void) { - movement_state.debounce_prev_pin_light = watch_get_pin_level(BTN_LIGHT); - movement_state.debounce_ticks_light = 1; + movement_state.debounce_btn_trig_light = true; _movement_enable_fast_tick_if_needed(); } void cb_mode_btn_interrupt(void) { - movement_state.debounce_prev_pin_mode = watch_get_pin_level(BTN_MODE); - movement_state.debounce_ticks_mode = 1; + movement_state.debounce_btn_trig_mode = true; _movement_enable_fast_tick_if_needed(); } void cb_alarm_btn_interrupt(void) { - movement_state.debounce_prev_pin_alarm = watch_get_pin_level(BTN_ALARM); - movement_state.debounce_ticks_alarm = 1; + movement_state.debounce_btn_trig_alarm = true; _movement_enable_fast_tick_if_needed(); } @@ -686,34 +688,45 @@ void cb_alarm_fired(void) { } void cb_fast_tick(void) { - if (movement_state.debounce_ticks_light == 0) { - if (movement_state.debounce_prev_pin_light == watch_get_pin_level(BTN_LIGHT)) - light_btn_action(movement_state.debounce_prev_pin_light); - movement_state.debounce_ticks_light = -1; - } - else if (movement_state.debounce_ticks_light > 0) { - movement_state.debounce_ticks_light--; - return; - } - if (movement_state.debounce_ticks_alarm == 0) { - if (movement_state.debounce_prev_pin_alarm == watch_get_pin_level(BTN_ALARM)) - alarm_btn_action(movement_state.debounce_prev_pin_alarm); - movement_state.debounce_ticks_alarm = -1; - } - else if (movement_state.debounce_ticks_alarm > 0) { - movement_state.debounce_ticks_alarm--; - return; + // printf("%d \r\n", movement_state.fast_ticks); + if (movement_state.debounce_ticks_light > 0) movement_state.debounce_ticks_light--; + if (movement_state.debounce_ticks_alarm > 0) movement_state.debounce_ticks_alarm--; + if (movement_state.debounce_ticks_mode > 0) movement_state.debounce_ticks_mode--; + if (movement_state.debounce_btn_trig_light) { + movement_state.debounce_btn_trig_light = false; + if (movement_state.debounce_ticks_light == 0) { + light_btn_action(); + movement_state.debounce_ticks_light = DEBOUNCE_TICKS; + } + else { + movement_state.light_down_timestamp = 0; + _movement_disable_fast_tick_if_possible(); + } } - if (movement_state.debounce_ticks_mode == 0) { - if (movement_state.debounce_prev_pin_mode == watch_get_pin_level(BTN_MODE)) - mode_btn_action(movement_state.debounce_prev_pin_mode); - movement_state.debounce_ticks_mode = -1; + if (movement_state.debounce_btn_trig_alarm) { + movement_state.debounce_btn_trig_alarm = false; + if (movement_state.debounce_ticks_alarm == 0) { + alarm_btn_action(); + movement_state.debounce_ticks_alarm = DEBOUNCE_TICKS; + } + else { + movement_state.alarm_down_timestamp = 0; + _movement_disable_fast_tick_if_possible(); + } } - else if (movement_state.debounce_ticks_mode > 0) { - movement_state.debounce_ticks_mode--; - return; + if (movement_state.debounce_btn_trig_mode) { + movement_state.debounce_btn_trig_mode = false; + if (movement_state.debounce_ticks_mode == 0) { + mode_btn_action(); + movement_state.debounce_ticks_mode = DEBOUNCE_TICKS; + } + else { + movement_state.mode_down_timestamp = 0; + _movement_disable_fast_tick_if_possible(); + } } - movement_state.fast_ticks++; + if (movement_state.debounce_ticks_light + movement_state.debounce_ticks_mode + movement_state.debounce_ticks_alarm == 0) + movement_state.fast_ticks++; if (movement_state.light_ticks > 0) movement_state.light_ticks--; if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--; // check timestamps and auto-fire the long-press events diff --git a/movement/movement.h b/movement/movement.h index 3601d48c5..81e55ab27 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -270,12 +270,12 @@ typedef struct { // low energy mode countdown int32_t le_mode_ticks; - int8_t debounce_ticks_light; - int8_t debounce_ticks_alarm; - int8_t debounce_ticks_mode; - bool debounce_prev_pin_light; - bool debounce_prev_pin_alarm; - bool debounce_prev_pin_mode; + uint8_t debounce_ticks_light; + uint8_t debounce_ticks_alarm; + uint8_t debounce_ticks_mode; + bool debounce_btn_trig_light; + bool debounce_btn_trig_alarm; + bool debounce_btn_trig_mode; bool ignore_alarm_btn_after_sleep; // app resignation countdown (TODO: consolidate with LE countdown?) From 9727dac3c34b918b8ba3a5de2ce34474ffee61a6 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 20:28:10 -0400 Subject: [PATCH 06/19] Revert "Leaving sleep with alarm button up doesn't trigger alarm button" This reverts commit 7d5aaf60caa943a248a7f635111ddfd50c230389. --- movement/movement.c | 114 ++++++++++++++------------------------------ movement/movement.h | 7 +-- 2 files changed, 37 insertions(+), 84 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index f6657923f..a9ff2fa25 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -99,8 +99,6 @@ #include #endif -#define DEBOUNCE_TICKS 2 // In terms of *7.8125ms - movement_state_t movement_state; void * watch_face_contexts[MOVEMENT_NUM_FACES]; watch_date_time scheduled_tasks[MOVEMENT_NUM_FACES]; @@ -171,9 +169,6 @@ static inline void _movement_reset_inactivity_countdown(void) { static inline void _movement_enable_fast_tick_if_needed(void) { if (!movement_state.fast_tick_enabled) { movement_state.fast_ticks = 0; - movement_state.debounce_ticks_light = 0; - movement_state.debounce_ticks_alarm = 0; - movement_state.debounce_ticks_mode = 0; watch_rtc_register_periodic_callback(cb_fast_tick, 128); movement_state.fast_tick_enabled = true; } @@ -188,6 +183,16 @@ static inline void _movement_disable_fast_tick_if_possible(void) { } } +static void cb_debounce(void) { + movement_state.debounce_occurring = false; + watch_rtc_disable_periodic_callback(64); // 64 HZ is 15.625ms +} + +static inline void _movement_enable_debounce_tick(void) { + movement_state.debounce_occurring = true; + watch_rtc_register_periodic_callback(cb_debounce, 64); +} + static void _movement_handle_background_tasks(void) { for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) { // For each face, if the watch face wants a background task... @@ -228,15 +233,15 @@ static void _movement_handle_scheduled_tasks(void) { } void movement_request_tick_frequency(uint8_t freq) { - // Movement uses the 128 Hz tick internally - if (freq == 128) return; + // Movement uses the 128 Hz tick internally; 64 is th edebounce frequency + if (freq == 128 || freq == 64 ) return; // Movement requires at least a 1 Hz tick. // If we are asked for an invalid frequency, default back to 1 Hz. if (freq == 0 || __builtin_popcount(freq) != 1) freq = 1; // disable all callbacks except the 128 Hz one - watch_rtc_disable_matching_periodic_callbacks(0xFE); + watch_rtc_disable_matching_periodic_callbacks(0xFC); movement_state.subsecond = 0; movement_state.tick_frequency = freq; @@ -620,6 +625,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) { // force alarm off if the user pressed a button. if (movement_state.alarm_ticks) movement_state.alarm_ticks = 0; + if ( movement_state.debounce_occurring) + return EVENT_NONE; if (pin_level) { // handle rising edge @@ -634,49 +641,36 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e uint16_t diff = movement_state.fast_ticks - *down_timestamp; *down_timestamp = 0; _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 if (diff > MOVEMENT_LONG_PRESS_TICKS) return button_down_event_type + 3; else return button_down_event_type + 1; } } -static void light_btn_action(void) { +void cb_light_btn_interrupt(void) { bool pin_level = watch_get_pin_level(BTN_LIGHT); _movement_reset_inactivity_countdown(); event.event_type = _figure_out_button_event(pin_level, EVENT_LIGHT_BUTTON_DOWN, &movement_state.light_down_timestamp); } -static void mode_btn_action(void) { +void cb_mode_btn_interrupt(void) { bool pin_level = watch_get_pin_level(BTN_MODE); _movement_reset_inactivity_countdown(); event.event_type = _figure_out_button_event(pin_level, EVENT_MODE_BUTTON_DOWN, &movement_state.mode_down_timestamp); } -static void alarm_btn_action(void) { +void cb_alarm_btn_interrupt(void) { bool pin_level = watch_get_pin_level(BTN_ALARM); _movement_reset_inactivity_countdown(); uint8_t event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); if (movement_state.ignore_alarm_btn_after_sleep){ - if (event_type == EVENT_ALARM_BUTTON_UP || event_type == EVENT_ALARM_LONG_UP) movement_state.ignore_alarm_btn_after_sleep = false; + if (event_type == EVENT_ALARM_BUTTON_UP) movement_state.ignore_alarm_btn_after_sleep = false; return; } event.event_type = event_type; } -void cb_light_btn_interrupt(void) { - movement_state.debounce_btn_trig_light = true; - _movement_enable_fast_tick_if_needed(); -} - -void cb_mode_btn_interrupt(void) { - movement_state.debounce_btn_trig_mode = true; - _movement_enable_fast_tick_if_needed(); -} - -void cb_alarm_btn_interrupt(void) { - movement_state.debounce_btn_trig_alarm = true; - _movement_enable_fast_tick_if_needed(); -} void cb_alarm_btn_extwake(void) { // wake up! @@ -688,59 +682,23 @@ void cb_alarm_fired(void) { } void cb_fast_tick(void) { - // printf("%d \r\n", movement_state.fast_ticks); - if (movement_state.debounce_ticks_light > 0) movement_state.debounce_ticks_light--; - if (movement_state.debounce_ticks_alarm > 0) movement_state.debounce_ticks_alarm--; - if (movement_state.debounce_ticks_mode > 0) movement_state.debounce_ticks_mode--; - if (movement_state.debounce_btn_trig_light) { - movement_state.debounce_btn_trig_light = false; - if (movement_state.debounce_ticks_light == 0) { - light_btn_action(); - movement_state.debounce_ticks_light = DEBOUNCE_TICKS; - } - else { - movement_state.light_down_timestamp = 0; - _movement_disable_fast_tick_if_possible(); - } - } - if (movement_state.debounce_btn_trig_alarm) { - movement_state.debounce_btn_trig_alarm = false; - if (movement_state.debounce_ticks_alarm == 0) { - alarm_btn_action(); - movement_state.debounce_ticks_alarm = DEBOUNCE_TICKS; - } - else { - movement_state.alarm_down_timestamp = 0; - _movement_disable_fast_tick_if_possible(); - } - } - if (movement_state.debounce_btn_trig_mode) { - movement_state.debounce_btn_trig_mode = false; - if (movement_state.debounce_ticks_mode == 0) { - mode_btn_action(); - movement_state.debounce_ticks_mode = DEBOUNCE_TICKS; - } - else { - movement_state.mode_down_timestamp = 0; - _movement_disable_fast_tick_if_possible(); - } + movement_state.fast_ticks++; + if (!movement_state.debounce_occurring) { + if (movement_state.light_ticks > 0) movement_state.light_ticks--; + if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--; + // check timestamps and auto-fire the long-press events + // Notice: is it possible that two or more buttons have an identical timestamp? In this case + // only one of these buttons would receive the long press event. Don't bother for now... + if (movement_state.light_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_LIGHT_LONG_PRESS; + if (movement_state.mode_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_MODE_LONG_PRESS; + if (movement_state.alarm_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.alarm_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_ALARM_LONG_PRESS; } - if (movement_state.debounce_ticks_light + movement_state.debounce_ticks_mode + movement_state.debounce_ticks_alarm == 0) - movement_state.fast_ticks++; - if (movement_state.light_ticks > 0) movement_state.light_ticks--; - if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--; - // check timestamps and auto-fire the long-press events - // Notice: is it possible that two or more buttons have an identical timestamp? In this case - // only one of these buttons would receive the long press event. Don't bother for now... - if (movement_state.light_down_timestamp > 0) - if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) - event.event_type = EVENT_LIGHT_LONG_PRESS; - if (movement_state.mode_down_timestamp > 0) - if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) - event.event_type = EVENT_MODE_LONG_PRESS; - if (movement_state.alarm_down_timestamp > 0) - 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. // but if for whatever reason it isn't, this forces the fast tick off after 20 seconds. if (movement_state.fast_ticks >= 128 * 20) { diff --git a/movement/movement.h b/movement/movement.h index 81e55ab27..5829ba853 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -267,15 +267,10 @@ typedef struct { bool needs_background_tasks_handled; bool has_scheduled_background_task; bool needs_wake; + bool debounce_occurring; // low energy mode countdown int32_t le_mode_ticks; - uint8_t debounce_ticks_light; - uint8_t debounce_ticks_alarm; - uint8_t debounce_ticks_mode; - bool debounce_btn_trig_light; - bool debounce_btn_trig_alarm; - bool debounce_btn_trig_mode; bool ignore_alarm_btn_after_sleep; // app resignation countdown (TODO: consolidate with LE countdown?) From 36117ca20770c7c8815507b1c2e72677f4d49011 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 20:48:17 -0400 Subject: [PATCH 07/19] using cb_fast_tick again --- movement/movement.c | 128 ++++++++++++++++++++++++++++++-------------- movement/movement.h | 7 ++- 2 files changed, 95 insertions(+), 40 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index a9ff2fa25..1c043fc2d 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -99,6 +99,8 @@ #include #endif +#define DEBOUNCE_TICKS 20 // In terms of *7.8125ms + movement_state_t movement_state; void * watch_face_contexts[MOVEMENT_NUM_FACES]; watch_date_time scheduled_tasks[MOVEMENT_NUM_FACES]; @@ -169,6 +171,9 @@ static inline void _movement_reset_inactivity_countdown(void) { static inline void _movement_enable_fast_tick_if_needed(void) { if (!movement_state.fast_tick_enabled) { movement_state.fast_ticks = 0; + movement_state.debounce_ticks_light = 0; + movement_state.debounce_ticks_alarm = 0; + movement_state.debounce_ticks_mode = 0; watch_rtc_register_periodic_callback(cb_fast_tick, 128); movement_state.fast_tick_enabled = true; } @@ -183,16 +188,6 @@ static inline void _movement_disable_fast_tick_if_possible(void) { } } -static void cb_debounce(void) { - movement_state.debounce_occurring = false; - watch_rtc_disable_periodic_callback(64); // 64 HZ is 15.625ms -} - -static inline void _movement_enable_debounce_tick(void) { - movement_state.debounce_occurring = true; - watch_rtc_register_periodic_callback(cb_debounce, 64); -} - static void _movement_handle_background_tasks(void) { for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) { // For each face, if the watch face wants a background task... @@ -233,15 +228,15 @@ static void _movement_handle_scheduled_tasks(void) { } void movement_request_tick_frequency(uint8_t freq) { - // Movement uses the 128 Hz tick internally; 64 is th edebounce frequency - if (freq == 128 || freq == 64 ) return; + // Movement uses the 128 Hz tick internally + if (freq == 128) return; // Movement requires at least a 1 Hz tick. // If we are asked for an invalid frequency, default back to 1 Hz. if (freq == 0 || __builtin_popcount(freq) != 1) freq = 1; // disable all callbacks except the 128 Hz one - watch_rtc_disable_matching_periodic_callbacks(0xFC); + watch_rtc_disable_matching_periodic_callbacks(0xFE); movement_state.subsecond = 0; movement_state.tick_frequency = freq; @@ -625,8 +620,6 @@ 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) { // force alarm off if the user pressed a button. if (movement_state.alarm_ticks) movement_state.alarm_ticks = 0; - if ( movement_state.debounce_occurring) - return EVENT_NONE; if (pin_level) { // handle rising edge @@ -641,36 +634,46 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e uint16_t diff = movement_state.fast_ticks - *down_timestamp; *down_timestamp = 0; _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 if (diff > MOVEMENT_LONG_PRESS_TICKS) return button_down_event_type + 3; else return button_down_event_type + 1; } } -void cb_light_btn_interrupt(void) { - bool pin_level = watch_get_pin_level(BTN_LIGHT); +static void light_btn_action(bool pin_level) { _movement_reset_inactivity_countdown(); event.event_type = _figure_out_button_event(pin_level, EVENT_LIGHT_BUTTON_DOWN, &movement_state.light_down_timestamp); } -void cb_mode_btn_interrupt(void) { - bool pin_level = watch_get_pin_level(BTN_MODE); +static void mode_btn_action(bool pin_level) { _movement_reset_inactivity_countdown(); event.event_type = _figure_out_button_event(pin_level, EVENT_MODE_BUTTON_DOWN, &movement_state.mode_down_timestamp); } -void cb_alarm_btn_interrupt(void) { - bool pin_level = watch_get_pin_level(BTN_ALARM); +static void alarm_btn_action(bool pin_level) { _movement_reset_inactivity_countdown(); uint8_t event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); if (movement_state.ignore_alarm_btn_after_sleep){ - if (event_type == EVENT_ALARM_BUTTON_UP) movement_state.ignore_alarm_btn_after_sleep = false; + if (event_type == EVENT_ALARM_BUTTON_UP || event_type == EVENT_ALARM_LONG_UP) movement_state.ignore_alarm_btn_after_sleep = false; return; } event.event_type = event_type; } +void cb_light_btn_interrupt(void) { + movement_state.debounce_btn_trig_light = true; + _movement_enable_fast_tick_if_needed(); +} + +void cb_mode_btn_interrupt(void) { + movement_state.debounce_btn_trig_mode = true; + _movement_enable_fast_tick_if_needed(); +} + +void cb_alarm_btn_interrupt(void) { + movement_state.debounce_btn_trig_alarm = true; + _movement_enable_fast_tick_if_needed(); +} void cb_alarm_btn_extwake(void) { // wake up! @@ -682,23 +685,70 @@ void cb_alarm_fired(void) { } void cb_fast_tick(void) { - movement_state.fast_ticks++; - if (!movement_state.debounce_occurring) { - if (movement_state.light_ticks > 0) movement_state.light_ticks--; - if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--; - // check timestamps and auto-fire the long-press events - // Notice: is it possible that two or more buttons have an identical timestamp? In this case - // only one of these buttons would receive the long press event. Don't bother for now... - if (movement_state.light_down_timestamp > 0) - if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) - event.event_type = EVENT_LIGHT_LONG_PRESS; - if (movement_state.mode_down_timestamp > 0) - if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) - event.event_type = EVENT_MODE_LONG_PRESS; - if (movement_state.alarm_down_timestamp > 0) - if (movement_state.fast_ticks - movement_state.alarm_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) - event.event_type = EVENT_ALARM_LONG_PRESS; + if (movement_state.debounce_ticks_light > 0) movement_state.debounce_ticks_light--; + if (movement_state.debounce_ticks_alarm > 0) movement_state.debounce_ticks_alarm--; + if (movement_state.debounce_ticks_mode > 0) movement_state.debounce_ticks_mode--; + if (movement_state.debounce_btn_trig_light) { + bool pin_level = watch_get_pin_level(BTN_LIGHT); + movement_state.debounce_btn_trig_light = false; + if (pin_level) { + light_btn_action(pin_level); + } + else if (movement_state.debounce_ticks_light == 0) { + light_btn_action(pin_level); + movement_state.debounce_ticks_light = DEBOUNCE_TICKS; + } + else { + movement_state.light_down_timestamp = 0; + _movement_disable_fast_tick_if_possible(); + } + } + if (movement_state.debounce_btn_trig_alarm) { + bool pin_level = watch_get_pin_level(BTN_ALARM); + movement_state.debounce_btn_trig_alarm = false; + if (pin_level) { + alarm_btn_action(pin_level); + } + else if (movement_state.debounce_ticks_alarm == 0) { + alarm_btn_action(pin_level); + movement_state.debounce_ticks_alarm = DEBOUNCE_TICKS; + } + else { + movement_state.alarm_down_timestamp = 0; + _movement_disable_fast_tick_if_possible(); + } + } + if (movement_state.debounce_btn_trig_mode) { + bool pin_level = watch_get_pin_level(BTN_MODE); + movement_state.debounce_btn_trig_mode = false; + if (pin_level) { + mode_btn_action(pin_level); + } + else if (movement_state.debounce_ticks_mode == 0) { + mode_btn_action(pin_level); + movement_state.debounce_ticks_mode = DEBOUNCE_TICKS; + } + else { + movement_state.mode_down_timestamp = 0; + _movement_disable_fast_tick_if_possible(); + } } + if (movement_state.debounce_ticks_light + movement_state.debounce_ticks_mode + movement_state.debounce_ticks_alarm == 0) + movement_state.fast_ticks++; + if (movement_state.light_ticks > 0) movement_state.light_ticks--; + if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--; + // check timestamps and auto-fire the long-press events + // Notice: is it possible that two or more buttons have an identical timestamp? In this case + // only one of these buttons would receive the long press event. Don't bother for now... + if (movement_state.light_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_LIGHT_LONG_PRESS; + if (movement_state.mode_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_MODE_LONG_PRESS; + if (movement_state.alarm_down_timestamp > 0) + 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. // but if for whatever reason it isn't, this forces the fast tick off after 20 seconds. if (movement_state.fast_ticks >= 128 * 20) { diff --git a/movement/movement.h b/movement/movement.h index 5829ba853..81e55ab27 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -267,10 +267,15 @@ typedef struct { bool needs_background_tasks_handled; bool has_scheduled_background_task; bool needs_wake; - bool debounce_occurring; // low energy mode countdown int32_t le_mode_ticks; + uint8_t debounce_ticks_light; + uint8_t debounce_ticks_alarm; + uint8_t debounce_ticks_mode; + bool debounce_btn_trig_light; + bool debounce_btn_trig_alarm; + bool debounce_btn_trig_mode; bool ignore_alarm_btn_after_sleep; // app resignation countdown (TODO: consolidate with LE countdown?) From 73c3ba3ae7489098a28462a6fb7e7e2c89968665 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 21:05:19 -0400 Subject: [PATCH 08/19] Cleaned up code --- movement/movement.c | 58 +++++++++++++-------------------------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 1c043fc2d..7b938927b 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -684,55 +684,29 @@ void cb_alarm_fired(void) { movement_state.needs_background_tasks_handled = true; } -void cb_fast_tick(void) { - if (movement_state.debounce_ticks_light > 0) movement_state.debounce_ticks_light--; - if (movement_state.debounce_ticks_alarm > 0) movement_state.debounce_ticks_alarm--; - if (movement_state.debounce_ticks_mode > 0) movement_state.debounce_ticks_mode--; - if (movement_state.debounce_btn_trig_light) { - bool pin_level = watch_get_pin_level(BTN_LIGHT); - movement_state.debounce_btn_trig_light = false; - if (pin_level) { - light_btn_action(pin_level); - } - else if (movement_state.debounce_ticks_light == 0) { - light_btn_action(pin_level); - movement_state.debounce_ticks_light = DEBOUNCE_TICKS; - } - else { - movement_state.light_down_timestamp = 0; - _movement_disable_fast_tick_if_possible(); - } - } - if (movement_state.debounce_btn_trig_alarm) { - bool pin_level = watch_get_pin_level(BTN_ALARM); - movement_state.debounce_btn_trig_alarm = false; - if (pin_level) { - alarm_btn_action(pin_level); - } - else if (movement_state.debounce_ticks_alarm == 0) { - alarm_btn_action(pin_level); - movement_state.debounce_ticks_alarm = DEBOUNCE_TICKS; - } - else { - movement_state.alarm_down_timestamp = 0; - _movement_disable_fast_tick_if_possible(); - } - } - if (movement_state.debounce_btn_trig_mode) { - bool pin_level = watch_get_pin_level(BTN_MODE); - movement_state.debounce_btn_trig_mode = false; +static void debounce_btn_press(uint8_t pin, uint8_t *debounce_ticks, bool *debounce_btn_trig, uint16_t *down_timestamp, void (*function)(bool)) { + if (*debounce_ticks > 0) (*debounce_ticks)--; + if (*debounce_btn_trig) { + bool pin_level = watch_get_pin_level(pin); + *debounce_btn_trig = false; if (pin_level) { - mode_btn_action(pin_level); + function(pin_level); } - else if (movement_state.debounce_ticks_mode == 0) { - mode_btn_action(pin_level); - movement_state.debounce_ticks_mode = DEBOUNCE_TICKS; + else if (*debounce_ticks == 0) { + function(pin_level); + *debounce_ticks = DEBOUNCE_TICKS; } else { - movement_state.mode_down_timestamp = 0; + *down_timestamp = 0; _movement_disable_fast_tick_if_possible(); } } +} + +void cb_fast_tick(void) { + debounce_btn_press(BTN_LIGHT, &movement_state.debounce_ticks_light, &movement_state.debounce_btn_trig_light, &movement_state.light_down_timestamp, light_btn_action); + debounce_btn_press(BTN_ALARM, &movement_state.debounce_ticks_alarm, &movement_state.debounce_btn_trig_alarm, &movement_state.alarm_down_timestamp, alarm_btn_action); + debounce_btn_press(BTN_MODE, &movement_state.debounce_ticks_mode, &movement_state.debounce_btn_trig_mode, &movement_state.mode_down_timestamp, mode_btn_action); if (movement_state.debounce_ticks_light + movement_state.debounce_ticks_mode + movement_state.debounce_ticks_alarm == 0) movement_state.fast_ticks++; if (movement_state.light_ticks > 0) movement_state.light_ticks--; From 7f2ac61375f8e746bf49b43d4ae792df54a76509 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 21:43:32 -0400 Subject: [PATCH 09/19] Fixed stuck fast_tick --- movement/movement.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 7b938927b..2ce67a8b5 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -99,7 +99,7 @@ #include #endif -#define DEBOUNCE_TICKS 20 // In terms of *7.8125ms +#define DEBOUNCE_TICKS 2 // In terms of *7.8125ms movement_state_t movement_state; void * watch_face_contexts[MOVEMENT_NUM_FACES]; @@ -633,7 +633,6 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e // now that that's out of the way, handle falling edge uint16_t diff = movement_state.fast_ticks - *down_timestamp; *down_timestamp = 0; - _movement_disable_fast_tick_if_possible(); // 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; else return button_down_event_type + 1; @@ -685,21 +684,20 @@ void cb_alarm_fired(void) { } static void debounce_btn_press(uint8_t pin, uint8_t *debounce_ticks, bool *debounce_btn_trig, uint16_t *down_timestamp, void (*function)(bool)) { - if (*debounce_ticks > 0) (*debounce_ticks)--; + if (*debounce_ticks > 0) + { + if (--(*debounce_ticks) == 0) + _movement_disable_fast_tick_if_possible(); + } if (*debounce_btn_trig) { bool pin_level = watch_get_pin_level(pin); *debounce_btn_trig = false; - if (pin_level) { - function(pin_level); - } - else if (*debounce_ticks == 0) { + if (*debounce_ticks == 0) { function(pin_level); *debounce_ticks = DEBOUNCE_TICKS; } - else { + else *down_timestamp = 0; - _movement_disable_fast_tick_if_possible(); - } } } From f7d1b8f9f33637467b95ed90c505ed66a6e27e0d Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 23:53:25 -0400 Subject: [PATCH 10/19] Delay for starting the debounce no loonger happens --- movement/movement.c | 41 +++++++++++++++++------------------------ movement/movement.h | 3 --- 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 2ce67a8b5..01047671e 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -182,6 +182,7 @@ static inline void _movement_enable_fast_tick_if_needed(void) { static inline void _movement_disable_fast_tick_if_possible(void) { if ((movement_state.light_ticks == -1) && (movement_state.alarm_ticks == -1) && + ((movement_state.debounce_ticks_light + movement_state.debounce_ticks_mode + movement_state.debounce_ticks_alarm) == 0) && ((movement_state.light_down_timestamp + movement_state.mode_down_timestamp + movement_state.alarm_down_timestamp) == 0)) { movement_state.fast_tick_enabled = false; watch_rtc_disable_periodic_callback(128); @@ -659,18 +660,28 @@ static void alarm_btn_action(bool pin_level) { event.event_type = event_type; } +static void debounce_btn_press(uint8_t pin, uint8_t *debounce_ticks, uint16_t *down_timestamp, void (*function)(bool)) { + bool pin_level = watch_get_pin_level(pin); + if (*debounce_ticks <= 1) { + function(pin_level); + *debounce_ticks = DEBOUNCE_TICKS; + } + else + *down_timestamp = 0; +} + void cb_light_btn_interrupt(void) { - movement_state.debounce_btn_trig_light = true; + debounce_btn_press(BTN_LIGHT, &movement_state.debounce_ticks_light, &movement_state.light_down_timestamp, light_btn_action); _movement_enable_fast_tick_if_needed(); } void cb_mode_btn_interrupt(void) { - movement_state.debounce_btn_trig_mode = true; + debounce_btn_press(BTN_MODE, &movement_state.debounce_ticks_mode, &movement_state.mode_down_timestamp, mode_btn_action); _movement_enable_fast_tick_if_needed(); } void cb_alarm_btn_interrupt(void) { - movement_state.debounce_btn_trig_alarm = true; + debounce_btn_press(BTN_ALARM, &movement_state.debounce_ticks_alarm, &movement_state.alarm_down_timestamp, alarm_btn_action); _movement_enable_fast_tick_if_needed(); } @@ -683,28 +694,10 @@ void cb_alarm_fired(void) { movement_state.needs_background_tasks_handled = true; } -static void debounce_btn_press(uint8_t pin, uint8_t *debounce_ticks, bool *debounce_btn_trig, uint16_t *down_timestamp, void (*function)(bool)) { - if (*debounce_ticks > 0) - { - if (--(*debounce_ticks) == 0) - _movement_disable_fast_tick_if_possible(); - } - if (*debounce_btn_trig) { - bool pin_level = watch_get_pin_level(pin); - *debounce_btn_trig = false; - if (*debounce_ticks == 0) { - function(pin_level); - *debounce_ticks = DEBOUNCE_TICKS; - } - else - *down_timestamp = 0; - } -} - void cb_fast_tick(void) { - debounce_btn_press(BTN_LIGHT, &movement_state.debounce_ticks_light, &movement_state.debounce_btn_trig_light, &movement_state.light_down_timestamp, light_btn_action); - debounce_btn_press(BTN_ALARM, &movement_state.debounce_ticks_alarm, &movement_state.debounce_btn_trig_alarm, &movement_state.alarm_down_timestamp, alarm_btn_action); - debounce_btn_press(BTN_MODE, &movement_state.debounce_ticks_mode, &movement_state.debounce_btn_trig_mode, &movement_state.mode_down_timestamp, mode_btn_action); + if (movement_state.debounce_ticks_light > 0){{if (--movement_state.debounce_ticks_light == 0) {_movement_disable_fast_tick_if_possible();}}} + if (movement_state.debounce_ticks_alarm > 0){{if (--movement_state.debounce_ticks_alarm == 0) {_movement_disable_fast_tick_if_possible();}}} + if (movement_state.debounce_ticks_mode > 0){{if (--movement_state.debounce_ticks_mode == 0) {_movement_disable_fast_tick_if_possible();}}} if (movement_state.debounce_ticks_light + movement_state.debounce_ticks_mode + movement_state.debounce_ticks_alarm == 0) movement_state.fast_ticks++; if (movement_state.light_ticks > 0) movement_state.light_ticks--; diff --git a/movement/movement.h b/movement/movement.h index 81e55ab27..67ff2fe5a 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -273,9 +273,6 @@ typedef struct { uint8_t debounce_ticks_light; uint8_t debounce_ticks_alarm; uint8_t debounce_ticks_mode; - bool debounce_btn_trig_light; - bool debounce_btn_trig_alarm; - bool debounce_btn_trig_mode; bool ignore_alarm_btn_after_sleep; // app resignation countdown (TODO: consolidate with LE countdown?) From 607946ed2e123a0a12421f0253555e826f49f116 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Tue, 30 Jul 2024 07:27:47 -0400 Subject: [PATCH 11/19] A little bit of clean-up --- movement/movement.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 01047671e..c0835da81 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -668,21 +668,19 @@ static void debounce_btn_press(uint8_t pin, uint8_t *debounce_ticks, uint16_t *d } else *down_timestamp = 0; + _movement_enable_fast_tick_if_needed(); } void cb_light_btn_interrupt(void) { debounce_btn_press(BTN_LIGHT, &movement_state.debounce_ticks_light, &movement_state.light_down_timestamp, light_btn_action); - _movement_enable_fast_tick_if_needed(); } void cb_mode_btn_interrupt(void) { debounce_btn_press(BTN_MODE, &movement_state.debounce_ticks_mode, &movement_state.mode_down_timestamp, mode_btn_action); - _movement_enable_fast_tick_if_needed(); } void cb_alarm_btn_interrupt(void) { debounce_btn_press(BTN_ALARM, &movement_state.debounce_ticks_alarm, &movement_state.alarm_down_timestamp, alarm_btn_action); - _movement_enable_fast_tick_if_needed(); } void cb_alarm_btn_extwake(void) { @@ -695,9 +693,9 @@ void cb_alarm_fired(void) { } void cb_fast_tick(void) { - if (movement_state.debounce_ticks_light > 0){{if (--movement_state.debounce_ticks_light == 0) {_movement_disable_fast_tick_if_possible();}}} - if (movement_state.debounce_ticks_alarm > 0){{if (--movement_state.debounce_ticks_alarm == 0) {_movement_disable_fast_tick_if_possible();}}} - if (movement_state.debounce_ticks_mode > 0){{if (--movement_state.debounce_ticks_mode == 0) {_movement_disable_fast_tick_if_possible();}}} + if (movement_state.debounce_ticks_light > 0 && --movement_state.debounce_ticks_light == 0) _movement_disable_fast_tick_if_possible(); + if (movement_state.debounce_ticks_alarm > 0 && --movement_state.debounce_ticks_alarm == 0) _movement_disable_fast_tick_if_possible(); + if (movement_state.debounce_ticks_mode > 0 && --movement_state.debounce_ticks_mode == 0) _movement_disable_fast_tick_if_possible(); if (movement_state.debounce_ticks_light + movement_state.debounce_ticks_mode + movement_state.debounce_ticks_alarm == 0) movement_state.fast_ticks++; if (movement_state.light_ticks > 0) movement_state.light_ticks--; From e297b3013e25c4195a8da1ea7e29457523458ee4 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Wed, 31 Jul 2024 07:22:33 -0400 Subject: [PATCH 12/19] Using debounce that triggers when there's no change for Xms rather than just ignoring new presses after Xms --- movement/movement.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index c0835da81..a4ca19a42 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -171,9 +171,6 @@ static inline void _movement_reset_inactivity_countdown(void) { static inline void _movement_enable_fast_tick_if_needed(void) { if (!movement_state.fast_tick_enabled) { movement_state.fast_ticks = 0; - movement_state.debounce_ticks_light = 0; - movement_state.debounce_ticks_alarm = 0; - movement_state.debounce_ticks_mode = 0; watch_rtc_register_periodic_callback(cb_fast_tick, 128); movement_state.fast_tick_enabled = true; } @@ -392,6 +389,9 @@ void app_init(void) { movement_state.settings.bit.led_duration = MOVEMENT_DEFAULT_LED_DURATION; movement_state.light_ticks = -1; movement_state.alarm_ticks = -1; + movement_state.debounce_ticks_light = 0; + movement_state.debounce_ticks_alarm = 0; + movement_state.debounce_ticks_mode = 0; movement_state.next_available_backup_register = 4; _movement_reset_inactivity_countdown(); @@ -634,24 +634,28 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e // now that that's out of the way, handle falling edge uint16_t diff = movement_state.fast_ticks - *down_timestamp; *down_timestamp = 0; + _movement_disable_fast_tick_if_possible(); // 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; else return button_down_event_type + 1; } } -static void light_btn_action(bool pin_level) { +static void light_btn_action(void) { _movement_reset_inactivity_countdown(); + bool pin_level = watch_get_pin_level(BTN_LIGHT); event.event_type = _figure_out_button_event(pin_level, EVENT_LIGHT_BUTTON_DOWN, &movement_state.light_down_timestamp); } -static void mode_btn_action(bool pin_level) { +static void mode_btn_action(void) { _movement_reset_inactivity_countdown(); + bool pin_level = watch_get_pin_level(BTN_MODE); event.event_type = _figure_out_button_event(pin_level, EVENT_MODE_BUTTON_DOWN, &movement_state.mode_down_timestamp); } -static void alarm_btn_action(bool pin_level) { +static void alarm_btn_action(void) { _movement_reset_inactivity_countdown(); + bool pin_level = watch_get_pin_level(BTN_ALARM); uint8_t event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); if (movement_state.ignore_alarm_btn_after_sleep){ if (event_type == EVENT_ALARM_BUTTON_UP || event_type == EVENT_ALARM_LONG_UP) movement_state.ignore_alarm_btn_after_sleep = false; @@ -660,27 +664,19 @@ static void alarm_btn_action(bool pin_level) { event.event_type = event_type; } -static void debounce_btn_press(uint8_t pin, uint8_t *debounce_ticks, uint16_t *down_timestamp, void (*function)(bool)) { - bool pin_level = watch_get_pin_level(pin); - if (*debounce_ticks <= 1) { - function(pin_level); - *debounce_ticks = DEBOUNCE_TICKS; - } - else - *down_timestamp = 0; - _movement_enable_fast_tick_if_needed(); -} - void cb_light_btn_interrupt(void) { - debounce_btn_press(BTN_LIGHT, &movement_state.debounce_ticks_light, &movement_state.light_down_timestamp, light_btn_action); + movement_state.debounce_ticks_light = DEBOUNCE_TICKS; + _movement_enable_fast_tick_if_needed(); } void cb_mode_btn_interrupt(void) { - debounce_btn_press(BTN_MODE, &movement_state.debounce_ticks_mode, &movement_state.mode_down_timestamp, mode_btn_action); + movement_state.debounce_ticks_mode = DEBOUNCE_TICKS; + _movement_enable_fast_tick_if_needed(); } void cb_alarm_btn_interrupt(void) { - debounce_btn_press(BTN_ALARM, &movement_state.debounce_ticks_alarm, &movement_state.alarm_down_timestamp, alarm_btn_action); + movement_state.debounce_ticks_alarm = DEBOUNCE_TICKS; + _movement_enable_fast_tick_if_needed(); } void cb_alarm_btn_extwake(void) { @@ -693,9 +689,12 @@ void cb_alarm_fired(void) { } void cb_fast_tick(void) { - if (movement_state.debounce_ticks_light > 0 && --movement_state.debounce_ticks_light == 0) _movement_disable_fast_tick_if_possible(); - if (movement_state.debounce_ticks_alarm > 0 && --movement_state.debounce_ticks_alarm == 0) _movement_disable_fast_tick_if_possible(); - if (movement_state.debounce_ticks_mode > 0 && --movement_state.debounce_ticks_mode == 0) _movement_disable_fast_tick_if_possible(); + if (movement_state.debounce_ticks_light > 0 && --movement_state.debounce_ticks_light == 0) + light_btn_action(); + if (movement_state.debounce_ticks_alarm > 0 && --movement_state.debounce_ticks_alarm == 0) + alarm_btn_action(); + if (movement_state.debounce_ticks_mode > 0 && --movement_state.debounce_ticks_mode == 0) + mode_btn_action(); if (movement_state.debounce_ticks_light + movement_state.debounce_ticks_mode + movement_state.debounce_ticks_alarm == 0) movement_state.fast_ticks++; if (movement_state.light_ticks > 0) movement_state.light_ticks--; From 027e42dc581fe6bd49b30c5b347fe86699df53b7 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Wed, 31 Jul 2024 07:25:09 -0400 Subject: [PATCH 13/19] Moved a few lines around to match main --- movement/movement.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index a4ca19a42..33e7415de 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -642,21 +642,21 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e } static void light_btn_action(void) { - _movement_reset_inactivity_countdown(); bool pin_level = watch_get_pin_level(BTN_LIGHT); + _movement_reset_inactivity_countdown(); event.event_type = _figure_out_button_event(pin_level, EVENT_LIGHT_BUTTON_DOWN, &movement_state.light_down_timestamp); } static void mode_btn_action(void) { - _movement_reset_inactivity_countdown(); bool pin_level = watch_get_pin_level(BTN_MODE); + _movement_reset_inactivity_countdown(); event.event_type = _figure_out_button_event(pin_level, EVENT_MODE_BUTTON_DOWN, &movement_state.mode_down_timestamp); } static void alarm_btn_action(void) { - _movement_reset_inactivity_countdown(); bool pin_level = watch_get_pin_level(BTN_ALARM); uint8_t event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); + _movement_reset_inactivity_countdown(); if (movement_state.ignore_alarm_btn_after_sleep){ if (event_type == EVENT_ALARM_BUTTON_UP || event_type == EVENT_ALARM_LONG_UP) movement_state.ignore_alarm_btn_after_sleep = false; return; From 7bbac4cd80a74f59443698228c21a6a4469be83d Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Wed, 31 Jul 2024 07:33:25 -0400 Subject: [PATCH 14/19] Brought debounce time to 8ms rather than 15 --- movement/movement.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 33e7415de..d364de547 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -23,6 +23,7 @@ */ #define MOVEMENT_LONG_PRESS_TICKS 64 +#define DEBOUNCE_TICKS 1 // In terms of *7.8125ms #include #include @@ -99,8 +100,6 @@ #include #endif -#define DEBOUNCE_TICKS 2 // In terms of *7.8125ms - movement_state_t movement_state; void * watch_face_contexts[MOVEMENT_NUM_FACES]; watch_date_time scheduled_tasks[MOVEMENT_NUM_FACES]; From 9861da84c389c43639d85b39833c51e434152660 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sun, 11 Aug 2024 11:00:08 -0400 Subject: [PATCH 15/19] Changed debounce to ignore button presses after a press down or up rathe rthan dact after a set amount of time due to an issue of delay_ms allowing a shoft-bricking --- movement/movement.c | 50 +++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index d364de547..2a45f8ae4 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -23,7 +23,8 @@ */ #define MOVEMENT_LONG_PRESS_TICKS 64 -#define DEBOUNCE_TICKS 1 // In terms of *7.8125ms +#define DEBOUNCE_TICKS_DOWN 2 // In terms of *7.8125ms +#define DEBOUNCE_TICKS_UP 2 // In terms of *7.8125ms #include #include @@ -170,6 +171,9 @@ static inline void _movement_reset_inactivity_countdown(void) { static inline void _movement_enable_fast_tick_if_needed(void) { if (!movement_state.fast_tick_enabled) { movement_state.fast_ticks = 0; + movement_state.debounce_ticks_light = 0; + movement_state.debounce_ticks_alarm = 0; + movement_state.debounce_ticks_mode = 0; watch_rtc_register_periodic_callback(cb_fast_tick, 128); movement_state.fast_tick_enabled = true; } @@ -388,9 +392,6 @@ void app_init(void) { movement_state.settings.bit.led_duration = MOVEMENT_DEFAULT_LED_DURATION; movement_state.light_ticks = -1; movement_state.alarm_ticks = -1; - movement_state.debounce_ticks_light = 0; - movement_state.debounce_ticks_alarm = 0; - movement_state.debounce_ticks_mode = 0; movement_state.next_available_backup_register = 4; _movement_reset_inactivity_countdown(); @@ -633,29 +634,25 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e // now that that's out of the way, handle falling edge uint16_t diff = movement_state.fast_ticks - *down_timestamp; *down_timestamp = 0; - _movement_disable_fast_tick_if_possible(); // 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; else return button_down_event_type + 1; } } -static void light_btn_action(void) { - bool pin_level = watch_get_pin_level(BTN_LIGHT); +static void light_btn_action(bool pin_level) { _movement_reset_inactivity_countdown(); event.event_type = _figure_out_button_event(pin_level, EVENT_LIGHT_BUTTON_DOWN, &movement_state.light_down_timestamp); } -static void mode_btn_action(void) { - bool pin_level = watch_get_pin_level(BTN_MODE); +static void mode_btn_action(bool pin_level) { _movement_reset_inactivity_countdown(); event.event_type = _figure_out_button_event(pin_level, EVENT_MODE_BUTTON_DOWN, &movement_state.mode_down_timestamp); } -static void alarm_btn_action(void) { - bool pin_level = watch_get_pin_level(BTN_ALARM); - uint8_t event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); +static void alarm_btn_action(bool pin_level) { _movement_reset_inactivity_countdown(); + uint8_t event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); if (movement_state.ignore_alarm_btn_after_sleep){ if (event_type == EVENT_ALARM_BUTTON_UP || event_type == EVENT_ALARM_LONG_UP) movement_state.ignore_alarm_btn_after_sleep = false; return; @@ -663,19 +660,27 @@ static void alarm_btn_action(void) { event.event_type = event_type; } -void cb_light_btn_interrupt(void) { - movement_state.debounce_ticks_light = DEBOUNCE_TICKS; +static void debounce_btn_press(uint8_t pin, uint8_t *debounce_ticks, uint16_t *down_timestamp, void (*function)(bool)) { + if (*debounce_ticks <= 1) { + bool pin_level = watch_get_pin_level(pin); + function(pin_level); + *debounce_ticks = pin_level ? DEBOUNCE_TICKS_DOWN : DEBOUNCE_TICKS_UP; + } + else + *down_timestamp = 0; _movement_enable_fast_tick_if_needed(); } +void cb_light_btn_interrupt(void) { + debounce_btn_press(BTN_LIGHT, &movement_state.debounce_ticks_light, &movement_state.light_down_timestamp, light_btn_action); +} + void cb_mode_btn_interrupt(void) { - movement_state.debounce_ticks_mode = DEBOUNCE_TICKS; - _movement_enable_fast_tick_if_needed(); + debounce_btn_press(BTN_MODE, &movement_state.debounce_ticks_mode, &movement_state.mode_down_timestamp, mode_btn_action); } void cb_alarm_btn_interrupt(void) { - movement_state.debounce_ticks_alarm = DEBOUNCE_TICKS; - _movement_enable_fast_tick_if_needed(); + debounce_btn_press(BTN_ALARM, &movement_state.debounce_ticks_alarm, &movement_state.alarm_down_timestamp, alarm_btn_action); } void cb_alarm_btn_extwake(void) { @@ -688,12 +693,9 @@ void cb_alarm_fired(void) { } void cb_fast_tick(void) { - if (movement_state.debounce_ticks_light > 0 && --movement_state.debounce_ticks_light == 0) - light_btn_action(); - if (movement_state.debounce_ticks_alarm > 0 && --movement_state.debounce_ticks_alarm == 0) - alarm_btn_action(); - if (movement_state.debounce_ticks_mode > 0 && --movement_state.debounce_ticks_mode == 0) - mode_btn_action(); + if (movement_state.debounce_ticks_light > 0 && --movement_state.debounce_ticks_light == 0) _movement_disable_fast_tick_if_possible(); + if (movement_state.debounce_ticks_alarm > 0 && --movement_state.debounce_ticks_alarm == 0) _movement_disable_fast_tick_if_possible(); + if (movement_state.debounce_ticks_mode > 0 && --movement_state.debounce_ticks_mode == 0) _movement_disable_fast_tick_if_possible(); if (movement_state.debounce_ticks_light + movement_state.debounce_ticks_mode + movement_state.debounce_ticks_alarm == 0) movement_state.fast_ticks++; if (movement_state.light_ticks > 0) movement_state.light_ticks--; From 2cdfa2d3b3bd59f17c20540b3326dd869dc90c10 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 17 Aug 2024 02:45:22 -0400 Subject: [PATCH 16/19] Set the debounce tick variables to 0 to make the face work the same as stock. --- movement/movement.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 2a45f8ae4..9ebf8ecea 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -23,8 +23,8 @@ */ #define MOVEMENT_LONG_PRESS_TICKS 64 -#define DEBOUNCE_TICKS_DOWN 2 // In terms of *7.8125ms -#define DEBOUNCE_TICKS_UP 2 // In terms of *7.8125ms +#define DEBOUNCE_TICKS_DOWN 0 // In terms of *7.8125ms +#define DEBOUNCE_TICKS_UP 0 // In terms of *7.8125ms #include #include From e9837ff0cbf08183e7f6b2736458078e6c9665f8 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 17 Aug 2024 02:52:30 -0400 Subject: [PATCH 17/19] Stops Running cb_fast_tick when the watch debounce timer is defined as 0 --- movement/movement.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 9ebf8ecea..9d97ede9d 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -661,14 +661,14 @@ static void alarm_btn_action(bool pin_level) { } static void debounce_btn_press(uint8_t pin, uint8_t *debounce_ticks, uint16_t *down_timestamp, void (*function)(bool)) { - if (*debounce_ticks <= 1) { + if (*debounce_ticks == 0) { bool pin_level = watch_get_pin_level(pin); function(pin_level); *debounce_ticks = pin_level ? DEBOUNCE_TICKS_DOWN : DEBOUNCE_TICKS_UP; + if (*debounce_ticks != 0) _movement_enable_fast_tick_if_needed(); } else *down_timestamp = 0; - _movement_enable_fast_tick_if_needed(); } void cb_light_btn_interrupt(void) { From c6f2bff75e456af85fce4728db310320095ca9b5 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Fri, 23 Aug 2024 17:35:16 -0400 Subject: [PATCH 18/19] Code review edits --- movement/movement.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 9d97ede9d..b49ae7b07 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -23,8 +23,16 @@ */ #define MOVEMENT_LONG_PRESS_TICKS 64 -#define DEBOUNCE_TICKS_DOWN 0 // In terms of *7.8125ms -#define DEBOUNCE_TICKS_UP 0 // In terms of *7.8125ms +#define DEBOUNCE_TICKS_DOWN 0 +#define DEBOUNCE_TICKS_UP 0 +/* +DEBOUNCE_TICKS_DOWN and DEBOUNCE_TICKS_UP are in terms of fast_cb ticks after a button is pressed. +The logic is that pressed of a button are ignored until the cb_fast_tick function runs this variable amount of times. +Without modifying the code, the cb_fast_tick frequency is 128Hz, or 7.8125ms. +It is not suggested to set this value to one for debouncing, as the callback occurs asynchronously of the button's press, +meaning that if a button was pressed and 7ms passed since th elast time cb_fast_tick was called, then there will be only 812.5us +of debounce time. +*/ #include #include @@ -640,19 +648,21 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e } } +static movement_event_type_t btn_action(bool pin_level, int code, uint16_t *timestamp) { + _movement_reset_inactivity_countdown(); + return _figure_out_button_event(pin_level, code, timestamp); +} + static void light_btn_action(bool pin_level) { - _movement_reset_inactivity_countdown(); - event.event_type = _figure_out_button_event(pin_level, EVENT_LIGHT_BUTTON_DOWN, &movement_state.light_down_timestamp); + event.event_type = btn_action(pin_level, EVENT_LIGHT_BUTTON_DOWN, &movement_state.light_down_timestamp); } -static void mode_btn_action(bool pin_level) { - _movement_reset_inactivity_countdown(); - event.event_type = _figure_out_button_event(pin_level, EVENT_MODE_BUTTON_DOWN, &movement_state.mode_down_timestamp); +static void mode_btn_action(bool pin_level) { + event.event_type = btn_action(pin_level, EVENT_MODE_BUTTON_DOWN, &movement_state.mode_down_timestamp); } static void alarm_btn_action(bool pin_level) { - _movement_reset_inactivity_countdown(); - uint8_t event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); + uint8_t event_type = btn_action(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); if (movement_state.ignore_alarm_btn_after_sleep){ if (event_type == EVENT_ALARM_BUTTON_UP || event_type == EVENT_ALARM_LONG_UP) movement_state.ignore_alarm_btn_after_sleep = false; return; @@ -671,6 +681,12 @@ static void debounce_btn_press(uint8_t pin, uint8_t *debounce_ticks, uint16_t *d *down_timestamp = 0; } +static void movement_disable_if_debounce_complete(void) { + if (movement_state.debounce_ticks_light > 0 && --movement_state.debounce_ticks_light == 0) _movement_disable_fast_tick_if_possible(); + if (movement_state.debounce_ticks_alarm > 0 && --movement_state.debounce_ticks_alarm == 0) _movement_disable_fast_tick_if_possible(); + if (movement_state.debounce_ticks_mode > 0 && --movement_state.debounce_ticks_mode == 0) _movement_disable_fast_tick_if_possible(); +} + void cb_light_btn_interrupt(void) { debounce_btn_press(BTN_LIGHT, &movement_state.debounce_ticks_light, &movement_state.light_down_timestamp, light_btn_action); } @@ -693,9 +709,7 @@ void cb_alarm_fired(void) { } void cb_fast_tick(void) { - if (movement_state.debounce_ticks_light > 0 && --movement_state.debounce_ticks_light == 0) _movement_disable_fast_tick_if_possible(); - if (movement_state.debounce_ticks_alarm > 0 && --movement_state.debounce_ticks_alarm == 0) _movement_disable_fast_tick_if_possible(); - if (movement_state.debounce_ticks_mode > 0 && --movement_state.debounce_ticks_mode == 0) _movement_disable_fast_tick_if_possible(); + movement_disable_if_debounce_complete(); if (movement_state.debounce_ticks_light + movement_state.debounce_ticks_mode + movement_state.debounce_ticks_alarm == 0) movement_state.fast_ticks++; if (movement_state.light_ticks > 0) movement_state.light_ticks--; From d5a8c57c8256433c11ea1b5b88f0d4900f20d697 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Fri, 23 Aug 2024 22:25:02 -0400 Subject: [PATCH 19/19] Additional code review change --- movement/movement.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index b49ae7b07..c81e0a7fc 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -681,10 +681,15 @@ static void debounce_btn_press(uint8_t pin, uint8_t *debounce_ticks, uint16_t *d *down_timestamp = 0; } +static void disable_if_needed(uint8_t *ticks) { + if (*ticks > 0 && --*ticks == 0) + _movement_disable_fast_tick_if_possible(); +} + static void movement_disable_if_debounce_complete(void) { - if (movement_state.debounce_ticks_light > 0 && --movement_state.debounce_ticks_light == 0) _movement_disable_fast_tick_if_possible(); - if (movement_state.debounce_ticks_alarm > 0 && --movement_state.debounce_ticks_alarm == 0) _movement_disable_fast_tick_if_possible(); - if (movement_state.debounce_ticks_mode > 0 && --movement_state.debounce_ticks_mode == 0) _movement_disable_fast_tick_if_possible(); + disable_if_needed(&movement_state.debounce_ticks_light); + disable_if_needed(&movement_state.debounce_ticks_alarm); + disable_if_needed(&movement_state.debounce_ticks_mode); } void cb_light_btn_interrupt(void) {