From 524098b9258232964d7756d4d44f16b006d340bf Mon Sep 17 00:00:00 2001 From: madhogs Date: Mon, 18 Mar 2024 18:01:05 +0000 Subject: [PATCH 01/43] add the ability to set location and birthdate in movement config --- movement/movement.c | 34 ++++++++++++++++++++++++++++++++++ movement/movement.h | 2 ++ movement/movement_config.h | 30 +++++++++++++++++++++++------- 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 0b292a15..ec14838d 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -95,6 +95,31 @@ #define MOVEMENT_DEFAULT_LED_DURATION 1 #endif +// Default to no set location latitude +#ifndef MOVEMENT_DEFAULT_LATITUDE +#define MOVEMENT_DEFAULT_LATITUDE 0 +#endif + +// Default to no set location longitude +#ifndef MOVEMENT_DEFAULT_LONGITUDE +#define MOVEMENT_DEFAULT_LONGITUDE 0 +#endif + +// Default to no set birthdate year +#ifndef MOVEMENT_DEFAULT_BIRTHDATE_YEAR +#define MOVEMENT_DEFAULT_BIRTHDATE_YEAR 0 +#endif + +// Default to no set birthdate month +#ifndef MOVEMENT_DEFAULT_BIRTHDATE_MONTH +#define MOVEMENT_DEFAULT_BIRTHDATE_MONTH 0 +#endif + +// Default to no set birthdate day +#ifndef MOVEMENT_DEFAULT_BIRTHDATE_DAY +#define MOVEMENT_DEFAULT_BIRTHDATE_DAY 0 +#endif + #if __EMSCRIPTEN__ #include #endif @@ -384,6 +409,11 @@ void app_init(void) { movement_state.settings.bit.to_interval = MOVEMENT_DEFAULT_TIMEOUT_INTERVAL; movement_state.settings.bit.le_interval = MOVEMENT_DEFAULT_LOW_ENERGY_INTERVAL; movement_state.settings.bit.led_duration = MOVEMENT_DEFAULT_LED_DURATION; + movement_state.location.bit.latitude = MOVEMENT_DEFAULT_LATITUDE; + movement_state.location.bit.longitude = MOVEMENT_DEFAULT_LONGITUDE; + movement_state.birthdate.bit.year = MOVEMENT_DEFAULT_BIRTHDATE_YEAR; + movement_state.birthdate.bit.month = MOVEMENT_DEFAULT_BIRTHDATE_MONTH; + movement_state.birthdate.bit.day = MOVEMENT_DEFAULT_BIRTHDATE_DAY; movement_state.light_ticks = -1; movement_state.alarm_ticks = -1; movement_state.next_available_backup_register = 4; @@ -406,10 +436,14 @@ void app_init(void) { void app_wake_from_backup(void) { movement_state.settings.reg = watch_get_backup_data(0); + movement_state.location.reg = watch_get_backup_data(1); + movement_state.birthdate.reg = watch_get_backup_data(2); } void app_setup(void) { watch_store_backup_data(movement_state.settings.reg, 0); + watch_store_backup_data(movement_state.location.reg, 1); + watch_store_backup_data(movement_state.birthdate.reg, 2); static bool is_first_launch = true; diff --git a/movement/movement.h b/movement/movement.h index 1dabfbc5..35600091 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -242,6 +242,8 @@ typedef struct { typedef struct { // properties stored in BACKUP register movement_settings_t settings; + movement_location_t location; + movement_birthdate_t birthdate; // transient properties int16_t current_face_idx; diff --git a/movement/movement_config.h b/movement/movement_config.h index 10a30af7..abceacf1 100644 --- a/movement/movement_config.h +++ b/movement/movement_config.h @@ -76,15 +76,15 @@ const watch_face_t watch_faces[] = { /* Set the timeout before switching to low energy mode * Valid values are: * 0: Never - * 1: 1 hour - * 2: 2 hours - * 3: 6 hours - * 4: 12 hours - * 5: 1 day - * 6: 2 days + * 1: 10 mins + * 2: 1 hour + * 3: 2 hours + * 4: 6 hours + * 5: 12 hours + * 6: 1 day * 7: 7 days */ -#define MOVEMENT_DEFAULT_LOW_ENERGY_INTERVAL 1 +#define MOVEMENT_DEFAULT_LOW_ENERGY_INTERVAL 2 /* Set the led duration * Valid values are: @@ -95,4 +95,20 @@ const watch_face_t watch_faces[] = { */ #define MOVEMENT_DEFAULT_LED_DURATION 1 +/* The latitude and longitude used for the wearers location + * Set signed values in 1/100ths of a degree + */ +#define MOVEMENT_DEFAULT_LATITUDE 0 +#define MOVEMENT_DEFAULT_LONGITUDE 0 + +/* The wearers birthdate + * Valid values: + * Year: 1 - 4095 + * Month: 1 - 12 + * Day: 1 - 31 + */ +#define MOVEMENT_DEFAULT_BIRTHDATE_YEAR 0 +#define MOVEMENT_DEFAULT_BIRTHDATE_MONTH 0 +#define MOVEMENT_DEFAULT_BIRTHDATE_DAY 0 + #endif // MOVEMENT_CONFIG_H_ From b923d506526382c74149c5f49e6395279d56bd3f Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 8 Jul 2024 18:32:41 -0400 Subject: [PATCH 02/43] CLOCK_FACE_24H_ONLY hides the preference to change the setting and defaults the mode to 24Hr mode --- movement/movement.c | 4 ++++ movement/watch_faces/clock/clock_face.c | 5 ----- movement/watch_faces/settings/preferences_face.c | 4 +++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index cb3dcf78..2ca2eb98 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -377,7 +377,11 @@ void app_init(void) { memset(&movement_state, 0, sizeof(movement_state)); +#ifdef CLOCK_FACE_24H_ONLY + movement_state.settings.bit.clock_mode_24h = true; +#else movement_state.settings.bit.clock_mode_24h = MOVEMENT_DEFAULT_24H_MODE; +#endif movement_state.settings.bit.led_red_color = MOVEMENT_DEFAULT_RED_COLOR; movement_state.settings.bit.led_green_color = MOVEMENT_DEFAULT_GREEN_COLOR; movement_state.settings.bit.button_should_sound = MOVEMENT_DEFAULT_BUTTON_SOUND; diff --git a/movement/watch_faces/clock/clock_face.c b/movement/watch_faces/clock/clock_face.c index eab5cd8d..0e3a5959 100644 --- a/movement/watch_faces/clock/clock_face.c +++ b/movement/watch_faces/clock/clock_face.c @@ -42,10 +42,6 @@ #define CLOCK_FACE_LOW_BATTERY_VOLTAGE_THRESHOLD 2200 #endif -#ifndef CLOCK_FACE_24H_ONLY -#define CLOCK_FACE_24H_ONLY 0 -#endif - typedef struct { struct { watch_date_time previous; @@ -57,7 +53,6 @@ typedef struct { } clock_state_t; static bool clock_is_in_24h_mode(movement_settings_t *settings) { - if (CLOCK_FACE_24H_ONLY) { return true; } return settings->bit.clock_mode_24h; } diff --git a/movement/watch_faces/settings/preferences_face.c b/movement/watch_faces/settings/preferences_face.c index c96e8d1f..2d4de9d4 100644 --- a/movement/watch_faces/settings/preferences_face.c +++ b/movement/watch_faces/settings/preferences_face.c @@ -99,7 +99,9 @@ bool preferences_face_loop(movement_event_t event, movement_settings_t *settings default: return movement_default_loop_handler(event, settings); } - +#ifdef CLOCK_FACE_24H_ONLY + if (current_page == 0) current_page++; // Skips past 12/24HR mode +#endif watch_display_string((char *)preferences_face_titles[current_page], 0); // blink active setting on even-numbered quarter-seconds From 7f6a9e5c9bdb04fa23a780da173594a4f7153bea Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 8 Jul 2024 18:33:17 -0400 Subject: [PATCH 03/43] Typo fix on PREFERENCES_FACE_NUM_PREFERENCES --- movement/watch_faces/settings/preferences_face.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/movement/watch_faces/settings/preferences_face.c b/movement/watch_faces/settings/preferences_face.c index 2d4de9d4..22979773 100644 --- a/movement/watch_faces/settings/preferences_face.c +++ b/movement/watch_faces/settings/preferences_face.c @@ -26,8 +26,8 @@ #include "preferences_face.h" #include "watch.h" -#define PREFERENCES_FACE_NUM_PREFEFENCES (7) -const char preferences_face_titles[PREFERENCES_FACE_NUM_PREFEFENCES][11] = { +#define PREFERENCES_FACE_NUM_PREFERENCES (7) +const char preferences_face_titles[PREFERENCES_FACE_NUM_PREFERENCES][11] = { "CL ", // Clock: 12 or 24 hour "BT Beep ", // Buttons: should they beep? "TO ", // Timeout: how long before we snap back to the clock face? @@ -65,7 +65,7 @@ bool preferences_face_loop(movement_event_t event, movement_settings_t *settings movement_move_to_next_face(); return false; case EVENT_LIGHT_BUTTON_DOWN: - current_page = (current_page + 1) % PREFERENCES_FACE_NUM_PREFEFENCES; + current_page = (current_page + 1) % PREFERENCES_FACE_NUM_PREFERENCES; *((uint8_t *)context) = current_page; break; case EVENT_ALARM_BUTTON_UP: From 2afc2c6721a526d2b5beebb9b266aef79ea04a20 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Wed, 10 Jul 2024 07:22:55 -0400 Subject: [PATCH 04/43] isolating this bit of complexity in movement function; Add ifdefs in clock faces for DCE --- movement/movement.c | 15 +++++++++------ movement/watch_faces/clock/clock_face.c | 4 ++++ movement/watch_faces/clock/simple_clock_face.c | 6 ++++++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 2ca2eb98..7363a8b9 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -328,6 +328,14 @@ static void end_buzzing_and_disable_buzzer(void) { watch_disable_buzzer(); } +static void set_initial_clock_mode(void) { +#ifdef CLOCK_FACE_24H_ONLY + movement_state.settings.bit.clock_mode_24h = true; +#else + movement_state.settings.bit.clock_mode_24h = MOVEMENT_DEFAULT_24H_MODE; +#endif +} + void movement_play_signal(void) { void *maybe_disable_buzzer = end_buzzing_and_disable_buzzer; if (watch_is_buzzer_or_led_enabled()) { @@ -376,12 +384,7 @@ void app_init(void) { #endif memset(&movement_state, 0, sizeof(movement_state)); - -#ifdef CLOCK_FACE_24H_ONLY - movement_state.settings.bit.clock_mode_24h = true; -#else - movement_state.settings.bit.clock_mode_24h = MOVEMENT_DEFAULT_24H_MODE; -#endif + set_initial_clock_mode(); movement_state.settings.bit.led_red_color = MOVEMENT_DEFAULT_RED_COLOR; movement_state.settings.bit.led_green_color = MOVEMENT_DEFAULT_GREEN_COLOR; movement_state.settings.bit.button_should_sound = MOVEMENT_DEFAULT_BUTTON_SOUND; diff --git a/movement/watch_faces/clock/clock_face.c b/movement/watch_faces/clock/clock_face.c index 0e3a5959..8b294c40 100644 --- a/movement/watch_faces/clock/clock_face.c +++ b/movement/watch_faces/clock/clock_face.c @@ -53,7 +53,11 @@ typedef struct { } clock_state_t; static bool clock_is_in_24h_mode(movement_settings_t *settings) { +#ifdef CLOCK_FACE_24H_ONLY + return true; +#else return settings->bit.clock_mode_24h; +#endif } static void clock_indicate(WatchIndicatorSegment indicator, bool on) { diff --git a/movement/watch_faces/clock/simple_clock_face.c b/movement/watch_faces/clock/simple_clock_face.c index fbc2c4b3..ac4ec2ee 100644 --- a/movement/watch_faces/clock/simple_clock_face.c +++ b/movement/watch_faces/clock/simple_clock_face.c @@ -51,7 +51,11 @@ void simple_clock_face_activate(movement_settings_t *settings, void *context) { if (watch_tick_animation_is_running()) watch_stop_tick_animation(); +#ifdef CLOCK_FACE_24H_ONLY + watch_set_indicator(WATCH_INDICATOR_24H); +#else if (settings->bit.clock_mode_24h) watch_set_indicator(WATCH_INDICATOR_24H); +#endif // handle chime indicator if (state->signal_enabled) watch_set_indicator(WATCH_INDICATOR_BELL); @@ -106,6 +110,7 @@ bool simple_clock_face_loop(movement_event_t event, movement_settings_t *setting sprintf(buf, "%02d%02d", date_time.unit.minute, date_time.unit.second); } else { // other stuff changed; let's do it all. +#ifndef CLOCK_FACE_24H_ONLY if (!settings->bit.clock_mode_24h) { // if we are in 12 hour mode, do some cleanup. if (date_time.unit.hour < 12) { @@ -116,6 +121,7 @@ bool simple_clock_face_loop(movement_event_t event, movement_settings_t *setting date_time.unit.hour %= 12; if (date_time.unit.hour == 0) date_time.unit.hour = 12; } +#endif pos = 0; if (event.event_type == EVENT_LOW_ENERGY_UPDATE) { if (!watch_tick_animation_is_running()) watch_start_tick_animation(500); From 4375ca37e0ccfd60602cade0a571c363c80c58c1 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 07:39:51 -0400 Subject: [PATCH 05/43] 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 cb3dcf78..cfe914ab 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 1dabfbc5..56dfc7dc 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 06/43] 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 cfe914ab..87110da4 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 56dfc7dc..1af89753 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 07/43] 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 87110da4..9f6f2959 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 1af89753..3601d48c 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 08/43] 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 9f6f2959..6bcbf635 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 09/43] 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 6bcbf635..f6657923 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; + // 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(); + } } - else if (movement_state.debounce_ticks_light > 0) { - movement_state.debounce_ticks_light--; - return; + 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_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; + 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(); + } } - 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.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 3601d48c..81e55ab2 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 10/43] 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 f6657923..a9ff2fa2 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(); - } + 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_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(); - } - } - 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 81e55ab2..5829ba85 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 11/43] 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 a9ff2fa2..1c043fc2 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 5829ba85..81e55ab2 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 12/43] Cleaned up code --- movement/movement.c | 70 ++++++++++++++------------------------------- 1 file changed, 22 insertions(+), 48 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 1c043fc2..7b938927 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; } +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) { + function(pin_level); + } + else if (*debounce_ticks == 0) { + function(pin_level); + *debounce_ticks = DEBOUNCE_TICKS; + } + else { + *down_timestamp = 0; + _movement_disable_fast_tick_if_possible(); + } + } +} + 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; - 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(); - } - } + 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 13/43] 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 7b938927..2ce67a8b 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 14/43] 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 2ce67a8b..01047671 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 81e55ab2..67ff2fe5 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 15/43] 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 01047671..c0835da8 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 16/43] 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 c0835da8..a4ca19a4 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; +void cb_light_btn_interrupt(void) { + movement_state.debounce_ticks_light = DEBOUNCE_TICKS; _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) { - 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 17/43] 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 a4ca19a4..33e7415d 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 18/43] 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 33e7415d..d364de54 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 ccf99a9727014dc504b6e62d12990ab96d3360b2 Mon Sep 17 00:00:00 2001 From: Robert Masen Date: Fri, 2 Aug 2024 18:20:44 -0500 Subject: [PATCH 19/43] add temp input to simulator --- .../shared/driver/thermistor_driver.c | 11 ++++++++- watch-library/simulator/shell.html | 23 ++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/watch-library/shared/driver/thermistor_driver.c b/watch-library/shared/driver/thermistor_driver.c index 73bdef41..8ce59345 100644 --- a/watch-library/shared/driver/thermistor_driver.c +++ b/watch-library/shared/driver/thermistor_driver.c @@ -45,7 +45,15 @@ void thermistor_driver_disable(void) { // Disable the enable pin's output circuitry. watch_disable_digital_output(THERMISTOR_ENABLE_PIN); } - +#if __EMSCRIPTEN__ +#include +float thermistor_driver_get_temperature(void) +{ + return EM_ASM_DOUBLE({ + return temp_c || 25.0; + }); +} +#else float thermistor_driver_get_temperature(void) { // set the enable pin to the level that powers the thermistor circuit. watch_set_pin_level(THERMISTOR_ENABLE_PIN, THERMISTOR_ENABLE_VALUE); @@ -56,3 +64,4 @@ float thermistor_driver_get_temperature(void) { return watch_utility_thermistor_temperature(value, THERMISTOR_HIGH_SIDE, THERMISTOR_B_COEFFICIENT, THERMISTOR_NOMINAL_TEMPERATURE, THERMISTOR_NOMINAL_RESISTANCE, THERMISTOR_SERIES_RESISTANCE); } +#endif diff --git a/watch-library/simulator/shell.html b/watch-library/simulator/shell.html index 29fbed03..9cdb2902 100644 --- a/watch-library/simulator/shell.html +++ b/watch-library/simulator/shell.html @@ -905,6 +905,11 @@
+

Temp.

+
+ C + +
@@ -962,6 +967,7 @@ lat = 0; lon = 0; tx = ""; + temp_c = 25.0; function updateLocation(location) { lat = Math.round(location.coords.latitude * 100); lon = Math.round(location.coords.longitude * 100); @@ -1038,10 +1044,25 @@ document.getElementById(skin).checked = true; setSkin(skin); } + + function setTemp() { + let tempInput = document.getElementById("temp-c"); + if (!tempInput) { + return console.warn("no input found"); + } + if (tempInput.value == "") { + return console.warn("no value in input"); + } + + try { + temp_c = Number.parseFloat(tempInput.value); + } catch (e) { + return console.warn("input value is not a valid float:", tempInput.value, e); + } + } loadPrefs(); {{{ SCRIPT }}} - From db165bec30ab114a5da838278d095094b18d5291 Mon Sep 17 00:00:00 2001 From: Christian Buschau Date: Sat, 3 Aug 2024 12:22:15 +0200 Subject: [PATCH 20/43] Fix all days in a month --- movement/watch_faces/complication/day_one_face.c | 2 +- movement/watch_faces/complication/time_left_face.c | 2 +- movement/watch_faces/settings/set_time_face.c | 2 +- movement/watch_faces/settings/set_time_hackwatch_face.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/movement/watch_faces/complication/day_one_face.c b/movement/watch_faces/complication/day_one_face.c index 27601edc..d9bf0f7c 100644 --- a/movement/watch_faces/complication/day_one_face.c +++ b/movement/watch_faces/complication/day_one_face.c @@ -27,7 +27,7 @@ #include "day_one_face.h" #include "watch.h" -static const uint8_t days_in_month[12] = {31, 29, 31, 30, 31, 30, 30, 31, 30, 31, 30, 31}; +static const uint8_t days_in_month[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; static uint32_t _day_one_face_juliandaynum(uint16_t year, uint16_t month, uint16_t day) { // from here: https://en.wikipedia.org/wiki/Julian_day#Julian_day_number_calculation diff --git a/movement/watch_faces/complication/time_left_face.c b/movement/watch_faces/complication/time_left_face.c index cc1077aa..9992bbf8 100644 --- a/movement/watch_faces/complication/time_left_face.c +++ b/movement/watch_faces/complication/time_left_face.c @@ -158,7 +158,7 @@ static void _draw(time_left_state_t *state, uint8_t subsecond) { /// @brief handle short or long pressing the alarm button static void _handle_alarm_button(time_left_state_t *state) { - const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 30, 31, 30, 31, 30, 31}; + const uint8_t days_in_month[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; uint32_t tmp_day; switch (state->current_page) { case TIME_LEFT_FACE_SETTINGS_STATE: // birth year diff --git a/movement/watch_faces/settings/set_time_face.c b/movement/watch_faces/settings/set_time_face.c index a8c88e44..4b4be644 100644 --- a/movement/watch_faces/settings/set_time_face.c +++ b/movement/watch_faces/settings/set_time_face.c @@ -33,7 +33,7 @@ static bool _quick_ticks_running; static void _handle_alarm_button(movement_settings_t *settings, watch_date_time date_time, uint8_t current_page) { // handles short or long pressing of the alarm button - const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + const uint8_t days_in_month[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; switch (current_page) { case 0: // hour diff --git a/movement/watch_faces/settings/set_time_hackwatch_face.c b/movement/watch_faces/settings/set_time_hackwatch_face.c index fbe8cbb1..269612f7 100644 --- a/movement/watch_faces/settings/set_time_hackwatch_face.c +++ b/movement/watch_faces/settings/set_time_hackwatch_face.c @@ -47,7 +47,7 @@ void set_time_hackwatch_face_activate(movement_settings_t *settings, void *conte bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { uint8_t current_page = *((uint8_t *)context); - const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 30, 31, 30, 31, 30, 31}; + const uint8_t days_in_month[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (event.subsecond == 15) // Delay displayed time update by ~0.5 seconds, to align phase exactly to main clock at 1Hz date_time_settings = watch_rtc_get_date_time(); From 6ae5dfef708ed3f9ec1348d20f0b48f5f1915fcf Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 3 Aug 2024 11:20:25 -0400 Subject: [PATCH 21/43] Leap Years Now Handled Dynamically --- apps/beats-time/app.c | 8 +++--- .../watch_faces/complication/day_one_face.c | 8 +++--- .../watch_faces/complication/time_left_face.c | 26 ++++++------------- movement/watch_faces/settings/set_time_face.c | 14 ++++------ .../settings/set_time_hackwatch_face.c | 14 ++++------ 5 files changed, 25 insertions(+), 45 deletions(-) diff --git a/apps/beats-time/app.c b/apps/beats-time/app.c index ef27ffef..f9792474 100644 --- a/apps/beats-time/app.c +++ b/apps/beats-time/app.c @@ -2,6 +2,7 @@ #include #include #include "watch.h" +#include "watch_utility.h" const int8_t UTC_OFFSET = 4; // set to your current UTC offset to see correct beats time const uint8_t BEAT_REFRESH_FREQUENCY = 8; @@ -224,13 +225,10 @@ void set_time_mode_handle_secondary_button(void) { break; case 5: // day date_time.unit.day = date_time.unit.day + 1; - // can't set to the 29th on a leap year. if it's february 29, set to 11:59 on the 28th. - // and it should roll over. - if (date_time.unit.day > days_in_month[date_time.unit.month - 1]) { - date_time.unit.day = 1; - } break; } + if (date_time.unit.day > days_in_month[date_time.unit.month - 1] + (is_leap(date_time.unit.year) && date_time.unit.month == 2)) + date_time.unit.day = 1; watch_rtc_set_date_time(date_time); } diff --git a/movement/watch_faces/complication/day_one_face.c b/movement/watch_faces/complication/day_one_face.c index d9bf0f7c..4429611e 100644 --- a/movement/watch_faces/complication/day_one_face.c +++ b/movement/watch_faces/complication/day_one_face.c @@ -26,8 +26,9 @@ #include #include "day_one_face.h" #include "watch.h" +#include "watch_utility.h" -static const uint8_t days_in_month[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +static const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; static uint32_t _day_one_face_juliandaynum(uint16_t year, uint16_t month, uint16_t day) { // from here: https://en.wikipedia.org/wiki/Julian_day#Julian_day_number_calculation @@ -66,13 +67,12 @@ static void _day_one_face_increment(day_one_state_t *state) { break; case PAGE_DAY: state->birth_day = state->birth_day + 1; - if (state->birth_day == 0 || state->birth_day > days_in_month[state->birth_month - 1]) { - state->birth_day = 1; - } break; default: break; } + if (state->birth_day == 0 || state->birth_day > (days_in_month[state->birth_month - 1] + (is_leap(state->birth_year) && state->birth_month == 2))) + state->birth_day = 1; } void day_one_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) { diff --git a/movement/watch_faces/complication/time_left_face.c b/movement/watch_faces/complication/time_left_face.c index 9992bbf8..74ed35b7 100644 --- a/movement/watch_faces/complication/time_left_face.c +++ b/movement/watch_faces/complication/time_left_face.c @@ -27,6 +27,7 @@ #include "time_left_face.h" #include "watch.h" #include "watch_private_display.h" +#include "watch_utility.h" const char _state_titles[][3] = {{'D', 'L', ' '}, {'D', 'L', ' '}, {'D', 'A', ' '}, {'D', 'A', ' '}, {'Y', 'R', 'b'}, {'M', 'O', 'b'}, {'D', 'A', 'b'}, {'Y', 'R', 'd'}, {'M', 'O', 'd'}, {'D', 'A', 'd'}}; @@ -158,8 +159,7 @@ static void _draw(time_left_state_t *state, uint8_t subsecond) { /// @brief handle short or long pressing the alarm button static void _handle_alarm_button(time_left_state_t *state) { - const uint8_t days_in_month[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - uint32_t tmp_day; + const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; switch (state->current_page) { case TIME_LEFT_FACE_SETTINGS_STATE: // birth year state->birth_date.bit.year++; @@ -169,14 +169,7 @@ static void _handle_alarm_button(time_left_state_t *state) { state->birth_date.bit.month = (state->birth_date.bit.month % 12) + 1; break; case TIME_LEFT_FACE_SETTINGS_STATE + 2: // birth day - tmp_day = state->birth_date.bit.day; // use a temporary variable to avoid messing up the months - tmp_day++; - // handle February 29th on a leap year - if (((tmp_day > days_in_month[state->birth_date.bit.month - 1]) && (state->birth_date.bit.month != 2 || (state->birth_date.bit.year % 4) != 0)) - || (state->birth_date.bit.month == 2 && (state->birth_date.bit.year % 4) == 0 && tmp_day > 29)) { - tmp_day = 1; - } - state->birth_date.bit.day = tmp_day; + state->birth_date.bit.day++; break; case TIME_LEFT_FACE_SETTINGS_STATE + 3: // target year state->target_date.bit.year++; @@ -186,16 +179,13 @@ static void _handle_alarm_button(time_left_state_t *state) { state->target_date.bit.month = (state->target_date.bit.month % 12) + 1; break; case TIME_LEFT_FACE_SETTINGS_STATE + 5: // target day - tmp_day = state->target_date.bit.day; - tmp_day++; - // handle February 29th on a leap year - if (((tmp_day > days_in_month[state->target_date.bit.month - 1]) && (state->target_date.bit.month != 2 || (state->target_date.bit.year % 4) != 0)) - || (state->target_date.bit.month == 2 && (state->target_date.bit.year % 4) == 0 && tmp_day > 29)) { - tmp_day = 1; - } - state->target_date.bit.day = tmp_day; + state->target_date.bit.day++; break; } + if (state->birth_date.bit.day > (days_in_month[state->birth_date.bit.month - 1] + (is_leap(state->birth_date.bit.year) && state->birth_date.bit.month == 2))) + state->birth_date.bit.day = 1; + if (state->target_date.bit.day > (days_in_month[state->target_date.bit.month - 1] + (is_leap(state->target_date.bit.year) && state->target_date.bit.month == 2))) + state->target_date.bit.day = 1; } static void _initiate_setting(time_left_state_t *state) { diff --git a/movement/watch_faces/settings/set_time_face.c b/movement/watch_faces/settings/set_time_face.c index 4b4be644..02cbb17d 100644 --- a/movement/watch_faces/settings/set_time_face.c +++ b/movement/watch_faces/settings/set_time_face.c @@ -25,6 +25,7 @@ #include #include "set_time_face.h" #include "watch.h" +#include "watch_utility.h" #define SET_TIME_FACE_NUM_SETTINGS (7) const char set_time_face_titles[SET_TIME_FACE_NUM_SETTINGS][3] = {"HR", "M1", "SE", "YR", "MO", "DA", "ZO"}; @@ -33,7 +34,7 @@ static bool _quick_ticks_running; static void _handle_alarm_button(movement_settings_t *settings, watch_date_time date_time, uint8_t current_page) { // handles short or long pressing of the alarm button - const uint8_t days_in_month[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; switch (current_page) { case 0: // hour @@ -52,14 +53,7 @@ static void _handle_alarm_button(movement_settings_t *settings, watch_date_time date_time.unit.month = (date_time.unit.month % 12) + 1; break; case 5: { // day - uint32_t tmp_day = date_time.unit.day; // use a temporary variable to avoid messing up the months - tmp_day = tmp_day + 1; - // handle February 29th on a leap year - if (((tmp_day > days_in_month[date_time.unit.month - 1]) && (date_time.unit.month != 2 || (date_time.unit.year % 4) != 0)) - || (date_time.unit.month == 2 && (date_time.unit.year % 4) == 0 && tmp_day > 29)) { - tmp_day = 1; - } - date_time.unit.day = tmp_day; + date_time.unit.day = date_time.unit.day + 1; break; } case 6: // time zone @@ -67,6 +61,8 @@ static void _handle_alarm_button(movement_settings_t *settings, watch_date_time if (settings->bit.time_zone > 40) settings->bit.time_zone = 0; break; } + if (date_time.unit.day > (days_in_month[date_time.unit.month - 1] + (is_leap(date_time.unit.year) &&date_time.unit.month == 2))) + date_time.unit.day = 1; watch_rtc_set_date_time(date_time); } diff --git a/movement/watch_faces/settings/set_time_hackwatch_face.c b/movement/watch_faces/settings/set_time_hackwatch_face.c index 269612f7..c760fd9b 100644 --- a/movement/watch_faces/settings/set_time_hackwatch_face.c +++ b/movement/watch_faces/settings/set_time_hackwatch_face.c @@ -26,6 +26,7 @@ #include #include "set_time_hackwatch_face.h" #include "watch.h" +#include "watch_utility.h" char set_time_hackwatch_face_titles[][3] = {"HR", "M1", "SE", "YR", "MO", "DA", "ZO"}; #define set_time_hackwatch_face_NUM_SETTINGS (sizeof(set_time_hackwatch_face_titles) / sizeof(*set_time_hackwatch_face_titles)) @@ -47,7 +48,7 @@ void set_time_hackwatch_face_activate(movement_settings_t *settings, void *conte bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { uint8_t current_page = *((uint8_t *)context); - const uint8_t days_in_month[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (event.subsecond == 15) // Delay displayed time update by ~0.5 seconds, to align phase exactly to main clock at 1Hz date_time_settings = watch_rtc_get_date_time(); @@ -119,10 +120,8 @@ bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *s break; case 5: // day date_time_settings.unit.day = date_time_settings.unit.day - 2; - // can't set to the 29th on a leap year. if it's february 29, set to 11:59 on the 28th. - // and it should roll over. if (date_time_settings.unit.day == 0) { - date_time_settings.unit.day = days_in_month[date_time_settings.unit.month - 1]; + date_time_settings.unit.day = days_in_month[date_time_settings.unit.month - 1] + (is_leap(date_time_settings.unit.year) && date_time_settings.unit.month == 2); } else date_time_settings.unit.day++; break; @@ -167,17 +166,14 @@ bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *s break; case 5: // day date_time_settings.unit.day = date_time_settings.unit.day + 1; - // can't set to the 29th on a leap year. if it's february 29, set to 11:59 on the 28th. - // and it should roll over. - if (date_time_settings.unit.day > days_in_month[date_time_settings.unit.month - 1]) { - date_time_settings.unit.day = 1; - } break; case 6: // time zone settings->bit.time_zone++; if (settings->bit.time_zone > 40) settings->bit.time_zone = 0; break; } + if (date_time_settings.unit.day > (days_in_month[date_time_settings.unit.month - 1] + (is_leap(date_time_settings.unit.year) && date_time_settings.unit.month == 2))) + date_time_settings.unit.day = 1; if (current_page != 2) // Do not set time when we are at seconds, it was already set previously watch_rtc_set_date_time(date_time_settings); //TODO: Do not update whole RTC, just what we are changing From 84f0db06549418c3d1a3bf1cf6ada00bcb0a2747 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 3 Aug 2024 11:38:45 -0400 Subject: [PATCH 22/43] Fix to remove compiler complaint --- movement/watch_faces/complication/sunrise_sunset_face.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/movement/watch_faces/complication/sunrise_sunset_face.c b/movement/watch_faces/complication/sunrise_sunset_face.c index ad2f5339..98c7103f 100644 --- a/movement/watch_faces/complication/sunrise_sunset_face.c +++ b/movement/watch_faces/complication/sunrise_sunset_face.c @@ -49,7 +49,7 @@ static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_s double rise, set, minutes, seconds; bool show_next_match = false; movement_location_t movement_location; - if (state->longLatToUse == 0) + if (state->longLatToUse == 0 || _location_count <= 1) movement_location = (movement_location_t) watch_get_backup_data(1); else{ movement_location.bit.latitude = longLatPresets[state->longLatToUse].latitude; From 51176344dc5ea5393386dd609b92fddbddb895eb Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 3 Aug 2024 11:42:42 -0400 Subject: [PATCH 23/43] Made it so the code works with a completely empty preset list --- movement/watch_faces/complication/sunrise_sunset_face.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/movement/watch_faces/complication/sunrise_sunset_face.c b/movement/watch_faces/complication/sunrise_sunset_face.c index 98c7103f..fbf60cfe 100644 --- a/movement/watch_faces/complication/sunrise_sunset_face.c +++ b/movement/watch_faces/complication/sunrise_sunset_face.c @@ -359,7 +359,7 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti _sunrise_sunset_face_update_location_register(state); } _sunrise_sunset_face_update_settings_display(event, context); - } else if (_location_count == 1) { + } else if (_location_count <= 1) { movement_illuminate_led(); } if (state->page == 0) { @@ -368,7 +368,7 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti } break; case EVENT_LIGHT_LONG_PRESS: - if (_location_count == 1) break; + if (_location_count <= 1) break; else if (!state->page) movement_illuminate_led(); break; case EVENT_LIGHT_BUTTON_UP: From 1da9d0aefe1010f9f4ac6825017410b56d9249bc Mon Sep 17 00:00:00 2001 From: Struan Date: Wed, 7 Aug 2024 22:24:57 -0600 Subject: [PATCH 24/43] fix: july has 31 days --- movement/watch_faces/settings/set_time_hackwatch_face.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/movement/watch_faces/settings/set_time_hackwatch_face.c b/movement/watch_faces/settings/set_time_hackwatch_face.c index fbe8cbb1..166b26e1 100644 --- a/movement/watch_faces/settings/set_time_hackwatch_face.c +++ b/movement/watch_faces/settings/set_time_hackwatch_face.c @@ -47,7 +47,7 @@ void set_time_hackwatch_face_activate(movement_settings_t *settings, void *conte bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { uint8_t current_page = *((uint8_t *)context); - const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 30, 31, 30, 31, 30, 31}; + const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (event.subsecond == 15) // Delay displayed time update by ~0.5 seconds, to align phase exactly to main clock at 1Hz date_time_settings = watch_rtc_get_date_time(); From f85a7f2c780144223ef07a058437a6392aa51d25 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 10 Aug 2024 06:38:46 -0400 Subject: [PATCH 25/43] Swapped the bell and alarm icon on the clock face to match Casio's doc --- movement/watch_faces/clock/clock_face.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/movement/watch_faces/clock/clock_face.c b/movement/watch_faces/clock/clock_face.c index eab5cd8d..66b40c42 100644 --- a/movement/watch_faces/clock/clock_face.c +++ b/movement/watch_faces/clock/clock_face.c @@ -70,11 +70,11 @@ static void clock_indicate(WatchIndicatorSegment indicator, bool on) { } static void clock_indicate_alarm(movement_settings_t *settings) { - clock_indicate(WATCH_INDICATOR_BELL, settings->bit.alarm_enabled); + clock_indicate(WATCH_INDICATOR_SIGNAL, settings->bit.alarm_enabled); } static void clock_indicate_time_signal(clock_state_t *clock) { - clock_indicate(WATCH_INDICATOR_SIGNAL, clock->time_signal_enabled); + clock_indicate(WATCH_INDICATOR_BELL, clock->time_signal_enabled); } static void clock_indicate_24h(movement_settings_t *settings) { From 09576807eb1095ae5d0789ca8dd82e5afe1e7db3 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 10 Aug 2024 07:40:52 -0400 Subject: [PATCH 26/43] Made the days_in_month its own function --- apps/beats-time/app.c | 3 +-- movement/watch_faces/complication/day_one_face.c | 4 +--- movement/watch_faces/complication/time_left_face.c | 5 ++--- movement/watch_faces/settings/set_time_face.c | 3 +-- movement/watch_faces/settings/set_time_hackwatch_face.c | 5 ++--- watch-library/shared/watch/watch_utility.c | 8 ++++++++ watch-library/shared/watch/watch_utility.h | 6 ++++++ 7 files changed, 21 insertions(+), 13 deletions(-) diff --git a/apps/beats-time/app.c b/apps/beats-time/app.c index f9792474..8d6c1db9 100644 --- a/apps/beats-time/app.c +++ b/apps/beats-time/app.c @@ -204,7 +204,6 @@ void set_time_mode_handle_primary_button(void) { void set_time_mode_handle_secondary_button(void) { watch_date_time date_time = watch_rtc_get_date_time(); - const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 30, 31, 30, 31, 30, 31}; switch (application_state.page) { case 0: // hour @@ -227,7 +226,7 @@ void set_time_mode_handle_secondary_button(void) { date_time.unit.day = date_time.unit.day + 1; break; } - if (date_time.unit.day > days_in_month[date_time.unit.month - 1] + (is_leap(date_time.unit.year) && date_time.unit.month == 2)) + if (date_time.unit.day > days_in_month(date_time.unit.month, date_time.unit.year + WATCH_RTC_REFERENCE_YEAR)) date_time.unit.day = 1; watch_rtc_set_date_time(date_time); } diff --git a/movement/watch_faces/complication/day_one_face.c b/movement/watch_faces/complication/day_one_face.c index 4429611e..aa65321e 100644 --- a/movement/watch_faces/complication/day_one_face.c +++ b/movement/watch_faces/complication/day_one_face.c @@ -28,8 +28,6 @@ #include "watch.h" #include "watch_utility.h" -static const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - static uint32_t _day_one_face_juliandaynum(uint16_t year, uint16_t month, uint16_t day) { // from here: https://en.wikipedia.org/wiki/Julian_day#Julian_day_number_calculation return (1461 * (year + 4800 + (month - 14) / 12)) / 4 + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12 - (3 * ((year + 4900 + (month - 14) / 12) / 100))/4 + day - 32075; @@ -71,7 +69,7 @@ static void _day_one_face_increment(day_one_state_t *state) { default: break; } - if (state->birth_day == 0 || state->birth_day > (days_in_month[state->birth_month - 1] + (is_leap(state->birth_year) && state->birth_month == 2))) + if (state->birth_day == 0 || state->birth_day > days_in_month(state->birth_month, state->birth_year)) state->birth_day = 1; } diff --git a/movement/watch_faces/complication/time_left_face.c b/movement/watch_faces/complication/time_left_face.c index 74ed35b7..99b0f87f 100644 --- a/movement/watch_faces/complication/time_left_face.c +++ b/movement/watch_faces/complication/time_left_face.c @@ -159,7 +159,6 @@ static void _draw(time_left_state_t *state, uint8_t subsecond) { /// @brief handle short or long pressing the alarm button static void _handle_alarm_button(time_left_state_t *state) { - const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; switch (state->current_page) { case TIME_LEFT_FACE_SETTINGS_STATE: // birth year state->birth_date.bit.year++; @@ -182,9 +181,9 @@ static void _handle_alarm_button(time_left_state_t *state) { state->target_date.bit.day++; break; } - if (state->birth_date.bit.day > (days_in_month[state->birth_date.bit.month - 1] + (is_leap(state->birth_date.bit.year) && state->birth_date.bit.month == 2))) + if (state->birth_date.bit.day > days_in_month(state->birth_date.bit.month, state->birth_date.bit.year)) state->birth_date.bit.day = 1; - if (state->target_date.bit.day > (days_in_month[state->target_date.bit.month - 1] + (is_leap(state->target_date.bit.year) && state->target_date.bit.month == 2))) + if (state->target_date.bit.day > days_in_month(state->target_date.bit.month, state->birth_date.bit.year)) state->target_date.bit.day = 1; } diff --git a/movement/watch_faces/settings/set_time_face.c b/movement/watch_faces/settings/set_time_face.c index 02cbb17d..503dffc9 100644 --- a/movement/watch_faces/settings/set_time_face.c +++ b/movement/watch_faces/settings/set_time_face.c @@ -34,7 +34,6 @@ static bool _quick_ticks_running; static void _handle_alarm_button(movement_settings_t *settings, watch_date_time date_time, uint8_t current_page) { // handles short or long pressing of the alarm button - const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; switch (current_page) { case 0: // hour @@ -61,7 +60,7 @@ static void _handle_alarm_button(movement_settings_t *settings, watch_date_time if (settings->bit.time_zone > 40) settings->bit.time_zone = 0; break; } - if (date_time.unit.day > (days_in_month[date_time.unit.month - 1] + (is_leap(date_time.unit.year) &&date_time.unit.month == 2))) + if (date_time.unit.day > days_in_month(date_time.unit.month, date_time.unit.year + WATCH_RTC_REFERENCE_YEAR)) date_time.unit.day = 1; watch_rtc_set_date_time(date_time); } diff --git a/movement/watch_faces/settings/set_time_hackwatch_face.c b/movement/watch_faces/settings/set_time_hackwatch_face.c index c760fd9b..8ba56cba 100644 --- a/movement/watch_faces/settings/set_time_hackwatch_face.c +++ b/movement/watch_faces/settings/set_time_hackwatch_face.c @@ -48,7 +48,6 @@ void set_time_hackwatch_face_activate(movement_settings_t *settings, void *conte bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { uint8_t current_page = *((uint8_t *)context); - const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (event.subsecond == 15) // Delay displayed time update by ~0.5 seconds, to align phase exactly to main clock at 1Hz date_time_settings = watch_rtc_get_date_time(); @@ -121,7 +120,7 @@ bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *s case 5: // day date_time_settings.unit.day = date_time_settings.unit.day - 2; if (date_time_settings.unit.day == 0) { - date_time_settings.unit.day = days_in_month[date_time_settings.unit.month - 1] + (is_leap(date_time_settings.unit.year) && date_time_settings.unit.month == 2); + date_time_settings.unit.day = days_in_month(date_time_settings.unit.month, date_time_settings.unit.year + WATCH_RTC_REFERENCE_YEAR); } else date_time_settings.unit.day++; break; @@ -172,7 +171,7 @@ bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *s if (settings->bit.time_zone > 40) settings->bit.time_zone = 0; break; } - if (date_time_settings.unit.day > (days_in_month[date_time_settings.unit.month - 1] + (is_leap(date_time_settings.unit.year) && date_time_settings.unit.month == 2))) + if (date_time_settings.unit.day > days_in_month(date_time_settings.unit.month, date_time_settings.unit.year + WATCH_RTC_REFERENCE_YEAR)) date_time_settings.unit.day = 1; if (current_page != 2) // Do not set time when we are at seconds, it was already set previously watch_rtc_set_date_time(date_time_settings); diff --git a/watch-library/shared/watch/watch_utility.c b/watch-library/shared/watch/watch_utility.c index 64b3bb79..c00791e7 100644 --- a/watch-library/shared/watch/watch_utility.c +++ b/watch-library/shared/watch/watch_utility.c @@ -315,3 +315,11 @@ uint32_t watch_utility_offset_timestamp(uint32_t now, int8_t hours, int8_t minut new += seconds; return new; } + +uint8_t days_in_month(uint8_t month, uint16_t year) { + static const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + uint8_t days = days_in_month[month - 1]; + if (month == 2 && is_leap(year)) + days += 1; + return days; +} diff --git a/watch-library/shared/watch/watch_utility.h b/watch-library/shared/watch/watch_utility.h index e2326d13..5533e196 100644 --- a/watch-library/shared/watch/watch_utility.h +++ b/watch-library/shared/watch/watch_utility.h @@ -164,4 +164,10 @@ float watch_utility_thermistor_temperature(uint16_t value, bool highside, float */ uint32_t watch_utility_offset_timestamp(uint32_t now, int8_t hours, int8_t minutes, int8_t seconds); +/** @brief Returns the number of days in a month. It also handles Leap Years for February. + * @param month The month of the date (1-12) + * @param year The year of the date (ex. 2022) + */ +uint8_t days_in_month(uint8_t month, uint16_t year); + #endif From 9861da84c389c43639d85b39833c51e434152660 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sun, 11 Aug 2024 11:00:08 -0400 Subject: [PATCH 27/43] 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 d364de54..2a45f8ae 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 28/43] 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 2a45f8ae..9ebf8ece 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 29/43] 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 9ebf8ece..9d97ede9 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 20b4a32835d6b8aedda40cb49025cf3fb78beebe Mon Sep 17 00:00:00 2001 From: Joseph Bryant Date: Sun, 18 Aug 2024 20:09:06 +0100 Subject: [PATCH 30/43] make sure we don't miss our scheduled tasks --- movement/movement.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/movement/movement.c b/movement/movement.c index cb3dcf78..67d53600 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -201,7 +201,7 @@ static void _movement_handle_scheduled_tasks(void) { for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) { if (scheduled_tasks[i].reg) { - if (scheduled_tasks[i].reg == date_time.reg) { + if (scheduled_tasks[i].reg <= date_time.reg) { scheduled_tasks[i].reg = 0; movement_event_t background_event = { EVENT_BACKGROUND_TASK, 0 }; watch_faces[i].loop(background_event, &movement_state.settings, watch_face_contexts[i]); From dcd4d12c0ab55aea50fc93f4de390a815d4ff6f5 Mon Sep 17 00:00:00 2001 From: Joseph Bryant Date: Sun, 18 Aug 2024 21:50:41 +0100 Subject: [PATCH 31/43] avoid delta overflow in countdown draw --- movement/watch_faces/complication/countdown_face.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/movement/watch_faces/complication/countdown_face.c b/movement/watch_faces/complication/countdown_face.c index be04040e..6ae3d935 100644 --- a/movement/watch_faces/complication/countdown_face.c +++ b/movement/watch_faces/complication/countdown_face.c @@ -87,7 +87,10 @@ static void draw(countdown_state_t *state, uint8_t subsecond) { switch (state->mode) { case cd_running: - delta = state->target_ts - state->now_ts; + if (state->target_ts <= state->now_ts) + delta = 0; + else + delta = state->target_ts - state->now_ts; result = div(delta, 60); state->seconds = result.rem; result = div(result.quot, 60); From e2c5babb2c7cd0141a5a78e9f94458804bbd9764 Mon Sep 17 00:00:00 2001 From: Joseph Bryant Date: Sun, 18 Aug 2024 22:03:05 +0100 Subject: [PATCH 32/43] don't change the bell indicator from within background task --- movement/watch_faces/complication/countdown_face.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/movement/watch_faces/complication/countdown_face.c b/movement/watch_faces/complication/countdown_face.c index 6ae3d935..b48ef595 100644 --- a/movement/watch_faces/complication/countdown_face.c +++ b/movement/watch_faces/complication/countdown_face.c @@ -100,6 +100,7 @@ static void draw(countdown_state_t *state, uint8_t subsecond) { break; case cd_reset: case cd_paused: + watch_clear_indicator(WATCH_INDICATOR_BELL); sprintf(buf, "CD %2d%02d%02d", state->hours, state->minutes, state->seconds); break; case cd_setting: @@ -133,7 +134,6 @@ static void pause(countdown_state_t *state) { static void reset(countdown_state_t *state) { state->mode = cd_reset; movement_cancel_background_task(); - watch_clear_indicator(WATCH_INDICATOR_BELL); load_countdown(state); } From a4fc048f94c8b35618b74c86336cbc51d5c09da1 Mon Sep 17 00:00:00 2001 From: Nicholas Rodrigues Lordello Date: Thu, 22 Aug 2024 14:53:17 +0200 Subject: [PATCH 33/43] Update TOTP Face Documentation The TOTP face header file documentation contained outdated instructions for configuring the complication with TOTP credentials. This PR updates the documentation to match what is expected in `totp_face.c`. --- movement/watch_faces/complication/totp_face.h | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/movement/watch_faces/complication/totp_face.h b/movement/watch_faces/complication/totp_face.h index 19a2cd45..acdcc8b1 100644 --- a/movement/watch_faces/complication/totp_face.h +++ b/movement/watch_faces/complication/totp_face.h @@ -48,15 +48,19 @@ * o SHA512 * * Instructions: - * o Find your secret key(s) and convert them to the required format. - * o Use https://cryptii.com/pipes/base32-to-hex to convert base32 to hex - * o Use https://github.com/susam/mintotp to generate test codes for verification - * o Edit global variables in "totp_face.c" to configure your stored keys: - * o "keys", "key_sizes", "timesteps", and "algorithms" set the - * cryptographic parameters for each secret key. - * o "labels" sets the two-letter label for each key - * (This replaces the day-of-week indicator) - * o Once finished, remove the two provided examples. + * o Find your secret key(s). + * o Use https://github.com/susam/mintotp to generate test codes for + * verification + * o Edit global `credentials` variable in "totp_face.c" to configure your + * TOTP credentials. The file includes two examples that you can use as a + * reference. Credentials are added with the `CREDENTIAL` macro in the form + * `CREDENTIAL(label, key, algorithm, timestep)` where: + * o `label` is a 2 character label that is displayed in the weekday digits + * to identify the TOTP credential. + * o `key` is a string with the base32 encoded secret. + * o `algorithm` is one of the supported hashing algorithms listed above. + * o `timestep` is how often the TOTP refreshes in seconds. This is usually + * 30 seconds. * * If you have more than one secret key, press ALARM to cycle through them. * Press LIGHT to cycle in the other direction or keep it pressed longer to From 9640f452cd815f9133a6c1de8f474b8dc769f66d Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Thu, 22 Aug 2024 20:46:47 -0400 Subject: [PATCH 34/43] Made the T and Y characters look more unique on the 4 and 6 position --- watch-library/shared/watch/watch_private_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/watch-library/shared/watch/watch_private_display.c b/watch-library/shared/watch/watch_private_display.c index c12957d9..7ea4141b 100644 --- a/watch-library/shared/watch/watch_private_display.c +++ b/watch-library/shared/watch/watch_private_display.c @@ -43,6 +43,8 @@ void watch_display_character(uint8_t character, uint8_t position) { else if (character == 'M' || character == 'm' || character == 'N') character = 'n'; // M and uppercase N need to be lowercase n else if (character == 'c') character = 'C'; // C needs to be uppercase else if (character == 'J') character = 'j'; // same + else if (character == 't' || character == 'T') character = '+'; // t in those locations looks like E + else if (character == 'y' || character == 'Y') character = '4'; // t in those locations looks like g else if (character == 'v' || character == 'V' || character == 'U' || character == 'W' || character == 'w') character = 'u'; // bottom segment duplicated, so show in top half } else { if (character == 'u') character = 'v'; // we can use the bottom segment; move to lower half From c6f2bff75e456af85fce4728db310320095ca9b5 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Fri, 23 Aug 2024 17:35:16 -0400 Subject: [PATCH 35/43] Code review edits --- movement/movement.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 9d97ede9..b49ae7b0 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 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 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 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 light_btn_action(bool pin_level) { + event.event_type = btn_action(pin_level, EVENT_LIGHT_BUTTON_DOWN, &movement_state.light_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 36/43] 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 b49ae7b0..c81e0a7f 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) { From fe259ee526088109bb018e29e0c0f89c406b8aea Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 26 Aug 2024 21:40:56 -0400 Subject: [PATCH 37/43] Comment change --- watch-library/shared/watch/watch_private_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/watch-library/shared/watch/watch_private_display.c b/watch-library/shared/watch/watch_private_display.c index 7ea4141b..3f15c52c 100644 --- a/watch-library/shared/watch/watch_private_display.c +++ b/watch-library/shared/watch/watch_private_display.c @@ -43,8 +43,8 @@ void watch_display_character(uint8_t character, uint8_t position) { else if (character == 'M' || character == 'm' || character == 'N') character = 'n'; // M and uppercase N need to be lowercase n else if (character == 'c') character = 'C'; // C needs to be uppercase else if (character == 'J') character = 'j'; // same - else if (character == 't' || character == 'T') character = '+'; // t in those locations looks like E - else if (character == 'y' || character == 'Y') character = '4'; // t in those locations looks like g + else if (character == 't' || character == 'T') character = '+'; // t in those locations looks like E otherwise + else if (character == 'y' || character == 'Y') character = '4'; // y in those locations looks like g otherwise else if (character == 'v' || character == 'V' || character == 'U' || character == 'W' || character == 'w') character = 'u'; // bottom segment duplicated, so show in top half } else { if (character == 'u') character = 'v'; // we can use the bottom segment; move to lower half From 77fb6202c9637d83aef7ebdececd0ffb34157bca Mon Sep 17 00:00:00 2001 From: metehan-arslan <44465987+metehan-arslan@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:56:36 +0300 Subject: [PATCH 38/43] Update SIGNAL_TUNE_KIM_POSSIBLE notes --- movement/movement_custom_signal_tunes.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/movement/movement_custom_signal_tunes.h b/movement/movement_custom_signal_tunes.h index cc21a5a8..e0f21af1 100644 --- a/movement/movement_custom_signal_tunes.h +++ b/movement/movement_custom_signal_tunes.h @@ -70,16 +70,15 @@ int8_t signal_tune[] = { #ifdef SIGNAL_TUNE_KIM_POSSIBLE int8_t signal_tune[] = { BUZZER_NOTE_G7, 6, - BUZZER_NOTE_REST, 1, - BUZZER_NOTE_G4, 3, + BUZZER_NOTE_G4, 2, BUZZER_NOTE_REST, 5, BUZZER_NOTE_G7, 6, - BUZZER_NOTE_REST, 1, - BUZZER_NOTE_G4, 3, + BUZZER_NOTE_G4, 2, BUZZER_NOTE_REST, 5, BUZZER_NOTE_A7SHARP_B7FLAT, 6, BUZZER_NOTE_REST, 2, - BUZZER_NOTE_G7, 6, + BUZZER_NOTE_G7, 6, + BUZZER_NOTE_G4, 2, 0 }; #endif // SIGNAL_TUNE_KIM_POSSIBLE From 2a194dfa699487c4814ada4da31f1711afba7ea4 Mon Sep 17 00:00:00 2001 From: metehan-arslan <44465987+metehan-arslan@users.noreply.github.com> Date: Wed, 28 Aug 2024 20:40:32 +0000 Subject: [PATCH 39/43] style: remove extra whitespace --- movement/movement_custom_signal_tunes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/movement/movement_custom_signal_tunes.h b/movement/movement_custom_signal_tunes.h index e0f21af1..27c1d397 100644 --- a/movement/movement_custom_signal_tunes.h +++ b/movement/movement_custom_signal_tunes.h @@ -77,7 +77,7 @@ int8_t signal_tune[] = { BUZZER_NOTE_REST, 5, BUZZER_NOTE_A7SHARP_B7FLAT, 6, BUZZER_NOTE_REST, 2, - BUZZER_NOTE_G7, 6, + BUZZER_NOTE_G7, 6, BUZZER_NOTE_G4, 2, 0 }; From cae5d8a33f5e7aa248b07e7a1b59fbc60b8c5a3b Mon Sep 17 00:00:00 2001 From: Joseph Bryant Date: Fri, 30 Aug 2024 07:23:28 +0100 Subject: [PATCH 40/43] wait for RTC SYNCBUSY in watch_register_extwake_callback --- watch-library/hardware/watch/watch_deepsleep.c | 1 + 1 file changed, 1 insertion(+) diff --git a/watch-library/hardware/watch/watch_deepsleep.c b/watch-library/hardware/watch/watch_deepsleep.c index efdad6dd..a25b667b 100644 --- a/watch-library/hardware/watch/watch_deepsleep.c +++ b/watch-library/hardware/watch/watch_deepsleep.c @@ -77,6 +77,7 @@ void watch_register_extwake_callback(uint8_t pin, ext_irq_cb_t callback, bool le RTC->MODE2.TAMPCTRL.reg = config; // re-enable the RTC RTC->MODE2.CTRLA.bit.ENABLE = 1; + while (RTC->MODE2.SYNCBUSY.bit.ENABLE); // wait for RTC to be enabled NVIC_ClearPendingIRQ(RTC_IRQn); NVIC_EnableIRQ(RTC_IRQn); From 6f7693e880878ee348b951e58dd5387a4e7e735b Mon Sep 17 00:00:00 2001 From: Metehan <99metehanarslan@gmail.com> Date: Sun, 1 Sep 2024 02:33:05 +0300 Subject: [PATCH 41/43] add layla tune --- movement/movement_custom_signal_tunes.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/movement/movement_custom_signal_tunes.h b/movement/movement_custom_signal_tunes.h index cc21a5a8..d069a3fd 100644 --- a/movement/movement_custom_signal_tunes.h +++ b/movement/movement_custom_signal_tunes.h @@ -84,4 +84,21 @@ int8_t signal_tune[] = { }; #endif // SIGNAL_TUNE_KIM_POSSIBLE +#ifdef SIGNAL_TUNE_LAYLA +int8_t signal_tune[] = { + BUZZER_NOTE_A6, 4, + BUZZER_NOTE_REST, 1, + BUZZER_NOTE_C7, 5, + BUZZER_NOTE_REST, 2, + BUZZER_NOTE_D7, 5, + BUZZER_NOTE_REST, 1, + BUZZER_NOTE_F7, 5, + BUZZER_NOTE_REST, 1, + BUZZER_NOTE_D7, 5, + BUZZER_NOTE_REST, 2, + BUZZER_NOTE_D7, 15, + 0 +}; +#endif // SIGNAL_TUNE_LAYLA + #endif // MOVEMENT_CUSTOM_SIGNAL_TUNES_H_ From 6268ce4381e68febae1f903fef1f5b637ddb395b Mon Sep 17 00:00:00 2001 From: Metehan <99metehanarslan@gmail.com> Date: Mon, 2 Sep 2024 00:03:21 +0300 Subject: [PATCH 42/43] update layla tune --- movement/movement_custom_signal_tunes.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/movement/movement_custom_signal_tunes.h b/movement/movement_custom_signal_tunes.h index d069a3fd..20c72352 100644 --- a/movement/movement_custom_signal_tunes.h +++ b/movement/movement_custom_signal_tunes.h @@ -86,17 +86,19 @@ int8_t signal_tune[] = { #ifdef SIGNAL_TUNE_LAYLA int8_t signal_tune[] = { - BUZZER_NOTE_A6, 4, + BUZZER_NOTE_A6, 5, BUZZER_NOTE_REST, 1, BUZZER_NOTE_C7, 5, - BUZZER_NOTE_REST, 2, + BUZZER_NOTE_REST, 1, BUZZER_NOTE_D7, 5, BUZZER_NOTE_REST, 1, BUZZER_NOTE_F7, 5, BUZZER_NOTE_REST, 1, BUZZER_NOTE_D7, 5, - BUZZER_NOTE_REST, 2, - BUZZER_NOTE_D7, 15, + BUZZER_NOTE_REST, 1, + BUZZER_NOTE_C7, 5, + BUZZER_NOTE_REST, 1, + BUZZER_NOTE_D7, 20, 0 }; #endif // SIGNAL_TUNE_LAYLA From 696f7f12ec1ca58aff02d6908f85bb47dd8fd4fd Mon Sep 17 00:00:00 2001 From: Metehan <99metehanarslan@gmail.com> Date: Mon, 2 Sep 2024 02:11:27 +0300 Subject: [PATCH 43/43] add power rangers tune --- movement/movement_custom_signal_tunes.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/movement/movement_custom_signal_tunes.h b/movement/movement_custom_signal_tunes.h index cc21a5a8..39ec3f17 100644 --- a/movement/movement_custom_signal_tunes.h +++ b/movement/movement_custom_signal_tunes.h @@ -84,4 +84,21 @@ int8_t signal_tune[] = { }; #endif // SIGNAL_TUNE_KIM_POSSIBLE +#ifdef SIGNAL_TUNE_POWER_RANGERS +int8_t signal_tune[] = { + BUZZER_NOTE_D8, 6, + BUZZER_NOTE_REST, 8, + BUZZER_NOTE_D8, 6, + BUZZER_NOTE_REST, 8, + BUZZER_NOTE_C8, 6, + BUZZER_NOTE_REST, 2, + BUZZER_NOTE_D8, 6, + BUZZER_NOTE_REST, 8, + BUZZER_NOTE_F8, 6, + BUZZER_NOTE_REST, 8, + BUZZER_NOTE_D8, 6, + 0 +}; +#endif // SIGNAL_TUNE_POWER_RANGERS + #endif // MOVEMENT_CUSTOM_SIGNAL_TUNES_H_