From 36117ca20770c7c8815507b1c2e72677f4d49011 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 20:48:17 -0400 Subject: [PATCH] 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 a9ff2fa..1c043fc 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 5829ba8..81e55ab 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?)