From b8e1a0aa9c74a5dd0e8e87fd8ae36df9669b442b Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Sat, 31 Aug 2024 15:59:26 -0400 Subject: [PATCH 01/46] adding really long press for each button --- movement/movement.c | 40 +++++++++++++++++++++++++++++++--------- movement/movement.h | 8 +++++++- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index cb3dcf78e..da4c97d3e 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2022 Joey Castillo + * Copyright (c) 2022 Joey Castillo (edits by Patrick McGuire) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,7 @@ */ #define MOVEMENT_LONG_PRESS_TICKS 64 +#define MOVEMENT_REALLY_LONG_PRESS_TICKS 384 #include #include @@ -629,8 +630,11 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e *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; + if (diff < MOVEMENT_REALLY_LONG_PRESS_TICKS && diff > MOVEMENT_LONG_PRESS_TICKS) { + return button_down_event_type + 3; + } else if (diff > MOVEMENT_REALLY_LONG_PRESS_TICKS) { + return button_down_event_type + 5; + } else return button_down_event_type + 1; } } @@ -668,15 +672,33 @@ void cb_fast_tick(void) { // 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) + //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.light_down_timestamp > 0) { + if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_REALLY_LONG_PRESS_TICKS + 1) { + event.event_type = EVENT_LIGHT_REALLY_LONG_PRESS; + } else 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) + } + } + if (movement_state.mode_down_timestamp > 0) { + if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_REALLY_LONG_PRESS_TICKS + 1) { + event.event_type = EVENT_MODE_REALLY_LONG_PRESS; + } else 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) + } + } + if (movement_state.alarm_down_timestamp > 0) { + if (movement_state.fast_ticks - movement_state.alarm_down_timestamp == MOVEMENT_REALLY_LONG_PRESS_TICKS + 1) { + event.event_type = EVENT_ALARM_REALLY_LONG_PRESS; + } else if (movement_state.fast_ticks - movement_state.alarm_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) { event.event_type = EVENT_ALARM_LONG_PRESS; + } + } // this is just a fail-safe; fast tick should be disabled as soon as the button is up, the LED times out, and/or the alarm finishes. // but if for whatever reason it isn't, this forces the fast tick off after 20 seconds. if (movement_state.fast_ticks >= 128 * 20) { diff --git a/movement/movement.h b/movement/movement.h index 1dabfbc5b..4c28014e9 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2022 Joey Castillo + * Copyright (c) 2022 Joey Castillo (edits by Patrick McGuire) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -112,14 +112,20 @@ typedef enum { EVENT_LIGHT_BUTTON_UP, // The light button was pressed for less than half a second, and released. EVENT_LIGHT_LONG_PRESS, // The light button was held for over half a second, but not yet released. EVENT_LIGHT_LONG_UP, // The light button was held for over half a second, and released. + EVENT_LIGHT_REALLY_LONG_PRESS, // The light button was held for over 3 seconds, but not yet released. + EVENT_LIGHT_REALLY_LONG_UP, // The light button was held for over 3 second, and released. EVENT_MODE_BUTTON_DOWN, // The mode button has been pressed, but not yet released. EVENT_MODE_BUTTON_UP, // The mode button was pressed for less than half a second, and released. EVENT_MODE_LONG_PRESS, // The mode button was held for over half a second, but not yet released. EVENT_MODE_LONG_UP, // The mode button was held for over half a second, and released. NOTE: your watch face will resign immediately after receiving this event. + EVENT_MODE_REALLY_LONG_PRESS, // The mode button was held for over 3 seconds, but not yet released. + EVENT_MODE_REALLY_LONG_UP, // The mode button was held for over 3 seconds, and released. EVENT_ALARM_BUTTON_DOWN, // The alarm button has been pressed, but not yet released. EVENT_ALARM_BUTTON_UP, // The alarm button was pressed for less than half a second, and released. EVENT_ALARM_LONG_PRESS, // The alarm button was held for over half a second, but not yet released. EVENT_ALARM_LONG_UP, // The alarm button was held for over half a second, and released. + EVENT_ALARM_REALLY_LONG_PRESS, // The alarm button was held for over 3 seconds, but not yet released. + EVENT_ALARM_REALLY_LONG_UP, // The alarm button was held for over 3 seconds, and released. } movement_event_type_t; typedef struct { From 3ea870025bae524c888445d1a016043ebe3e629f Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Thu, 22 Aug 2024 20:46:47 -0400 Subject: [PATCH 02/46] 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 c12957d9c..7ea4141bf 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 56362d579ee3566e4a44f98159ec59100a8c7f54 Mon Sep 17 00:00:00 2001 From: Nicholas Rodrigues Lordello Date: Thu, 22 Aug 2024 14:53:17 +0200 Subject: [PATCH 03/46] 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 19a2cd452..acdcc8b10 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 8443504f45297a26403cd55e7342c15d842fdb01 Mon Sep 17 00:00:00 2001 From: Joseph Bryant Date: Sun, 18 Aug 2024 20:09:06 +0100 Subject: [PATCH 04/46] 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 da4c97d3e..9fceb8d27 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -202,7 +202,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 5fbe3140aa36e09e7e97dd31bc033d12a5059215 Mon Sep 17 00:00:00 2001 From: madhogs Date: Mon, 18 Mar 2024 18:01:05 +0000 Subject: [PATCH 05/46] 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 9fceb8d27..a17c6e936 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -96,6 +96,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 @@ -385,6 +410,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; @@ -407,10 +437,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 4c28014e9..81e0fbc15 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -248,6 +248,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 10a30af77..abceacf1c 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 5d6163bce2fcdc8f9dd9a289bface07cbbd2137a Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 07:39:51 -0400 Subject: [PATCH 06/46] Added debouncing --- movement/movement.c | 76 +++++++++++++++++++++++++-------------------- movement/movement.h | 1 + 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index a17c6e936..3c6b0dcb7 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -209,6 +209,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... @@ -248,16 +259,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; @@ -649,6 +672,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 @@ -663,6 +688,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_REALLY_LONG_PRESS_TICKS && diff > MOVEMENT_LONG_PRESS_TICKS) { return button_down_event_type + 3; @@ -701,37 +727,21 @@ 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.light_down_timestamp > 0) { - if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_REALLY_LONG_PRESS_TICKS + 1) { - event.event_type = EVENT_LIGHT_REALLY_LONG_PRESS; - } else 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_REALLY_LONG_PRESS_TICKS + 1) { - event.event_type = EVENT_MODE_REALLY_LONG_PRESS; - } else 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_REALLY_LONG_PRESS_TICKS + 1) { - event.event_type = EVENT_ALARM_REALLY_LONG_PRESS; - } else 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. diff --git a/movement/movement.h b/movement/movement.h index 81e0fbc15..c99d1a95b 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -275,6 +275,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 ea7de4f431f05168024d115b4959c50bbd615518 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 07:44:31 -0400 Subject: [PATCH 07/46] 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 3c6b0dcb7..1f5f5ed75 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -525,6 +525,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]); @@ -713,9 +714,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 c99d1a95b..660f8e7f1 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -279,6 +279,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 77c0b3d0d35f67863c2a71b64624846e54b0ba80 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 18:12:46 -0400 Subject: [PATCH 08/46] 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 1f5f5ed75..d22aca4d4 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -209,17 +209,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... @@ -440,6 +429,9 @@ void app_init(void) { movement_state.birthdate.bit.day = MOVEMENT_DEFAULT_BIRTHDATE_DAY; 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(); @@ -520,12 +512,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]); @@ -673,8 +665,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 @@ -689,7 +679,6 @@ 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_REALLY_LONG_PRESS_TICKS && diff > MOVEMENT_LONG_PRESS_TICKS) { return button_down_event_type + 3; @@ -699,29 +688,43 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e } } -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! @@ -733,23 +736,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 660f8e7f1..b8ade486e 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -275,11 +275,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 e2c3ce9447b00bf2a6951c375f3dea3432d279f6 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 18:24:58 -0400 Subject: [PATCH 09/46] 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 d22aca4d4..a9379faba 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -248,28 +248,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 b229f68a548cfb8a368de220b26c0d0920270283 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 20:13:54 -0400 Subject: [PATCH 10/46] 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 a9379faba..8bcd2dea7 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -125,6 +125,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]; @@ -195,6 +197,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; } @@ -417,9 +422,6 @@ void app_init(void) { movement_state.birthdate.bit.day = MOVEMENT_DEFAULT_BIRTHDATE_DAY; 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(); @@ -676,17 +678,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){ @@ -697,20 +702,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(); } @@ -724,34 +726,45 @@ void cb_alarm_fired(void) { } void cb_fast_tick(void) { - if (movement_state.debounce_ticks_light == 0) { - if (movement_state.debounce_prev_pin_light == watch_get_pin_level(BTN_LIGHT)) - light_btn_action(movement_state.debounce_prev_pin_light); - movement_state.debounce_ticks_light = -1; - } - else if (movement_state.debounce_ticks_light > 0) { - movement_state.debounce_ticks_light--; - return; - } - if (movement_state.debounce_ticks_alarm == 0) { - if (movement_state.debounce_prev_pin_alarm == watch_get_pin_level(BTN_ALARM)) - alarm_btn_action(movement_state.debounce_prev_pin_alarm); - movement_state.debounce_ticks_alarm = -1; - } - else if (movement_state.debounce_ticks_alarm > 0) { - movement_state.debounce_ticks_alarm--; - return; + // printf("%d \r\n", movement_state.fast_ticks); + if (movement_state.debounce_ticks_light > 0) movement_state.debounce_ticks_light--; + if (movement_state.debounce_ticks_alarm > 0) movement_state.debounce_ticks_alarm--; + if (movement_state.debounce_ticks_mode > 0) movement_state.debounce_ticks_mode--; + if (movement_state.debounce_btn_trig_light) { + movement_state.debounce_btn_trig_light = false; + if (movement_state.debounce_ticks_light == 0) { + light_btn_action(); + movement_state.debounce_ticks_light = DEBOUNCE_TICKS; + } + else { + movement_state.light_down_timestamp = 0; + _movement_disable_fast_tick_if_possible(); + } } - if (movement_state.debounce_ticks_mode == 0) { - if (movement_state.debounce_prev_pin_mode == watch_get_pin_level(BTN_MODE)) - mode_btn_action(movement_state.debounce_prev_pin_mode); - movement_state.debounce_ticks_mode = -1; + if (movement_state.debounce_btn_trig_alarm) { + movement_state.debounce_btn_trig_alarm = false; + if (movement_state.debounce_ticks_alarm == 0) { + alarm_btn_action(); + movement_state.debounce_ticks_alarm = DEBOUNCE_TICKS; + } + else { + movement_state.alarm_down_timestamp = 0; + _movement_disable_fast_tick_if_possible(); + } } - else if (movement_state.debounce_ticks_mode > 0) { - movement_state.debounce_ticks_mode--; - return; + if (movement_state.debounce_btn_trig_mode) { + movement_state.debounce_btn_trig_mode = false; + if (movement_state.debounce_ticks_mode == 0) { + mode_btn_action(); + movement_state.debounce_ticks_mode = DEBOUNCE_TICKS; + } + else { + movement_state.mode_down_timestamp = 0; + _movement_disable_fast_tick_if_possible(); + } } - movement_state.fast_ticks++; + if (movement_state.debounce_ticks_light + movement_state.debounce_ticks_mode + movement_state.debounce_ticks_alarm == 0) + movement_state.fast_ticks++; if (movement_state.light_ticks > 0) movement_state.light_ticks--; if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--; // check timestamps and auto-fire the long-press events diff --git a/movement/movement.h b/movement/movement.h index b8ade486e..ed94b6f97 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -278,12 +278,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 f1dda582a99abb0e0f1fb499798cff47aaa6b067 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 20:28:10 -0400 Subject: [PATCH 11/46] 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 8bcd2dea7..e4b5a0cf8 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -125,8 +125,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]; @@ -197,9 +195,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; } @@ -214,6 +209,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... @@ -254,15 +259,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; @@ -655,6 +660,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 @@ -669,6 +676,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_REALLY_LONG_PRESS_TICKS && diff > MOVEMENT_LONG_PRESS_TICKS) { return button_down_event_type + 3; @@ -678,43 +686,29 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e } } -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! @@ -726,59 +720,23 @@ void cb_alarm_fired(void) { } void cb_fast_tick(void) { - // printf("%d \r\n", movement_state.fast_ticks); - if (movement_state.debounce_ticks_light > 0) movement_state.debounce_ticks_light--; - if (movement_state.debounce_ticks_alarm > 0) movement_state.debounce_ticks_alarm--; - if (movement_state.debounce_ticks_mode > 0) movement_state.debounce_ticks_mode--; - if (movement_state.debounce_btn_trig_light) { - movement_state.debounce_btn_trig_light = false; - if (movement_state.debounce_ticks_light == 0) { - light_btn_action(); - movement_state.debounce_ticks_light = DEBOUNCE_TICKS; - } - else { - movement_state.light_down_timestamp = 0; - _movement_disable_fast_tick_if_possible(); - } - } - if (movement_state.debounce_btn_trig_alarm) { - movement_state.debounce_btn_trig_alarm = false; - if (movement_state.debounce_ticks_alarm == 0) { - alarm_btn_action(); - movement_state.debounce_ticks_alarm = DEBOUNCE_TICKS; - } - else { - movement_state.alarm_down_timestamp = 0; - _movement_disable_fast_tick_if_possible(); - } - } - if (movement_state.debounce_btn_trig_mode) { - movement_state.debounce_btn_trig_mode = false; - if (movement_state.debounce_ticks_mode == 0) { - mode_btn_action(); - movement_state.debounce_ticks_mode = DEBOUNCE_TICKS; - } - else { - movement_state.mode_down_timestamp = 0; - _movement_disable_fast_tick_if_possible(); - } + movement_state.fast_ticks++; + if (!movement_state.debounce_occurring) { + if (movement_state.light_ticks > 0) movement_state.light_ticks--; + if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--; + // check timestamps and auto-fire the long-press events + // Notice: is it possible that two or more buttons have an identical timestamp? In this case + // only one of these buttons would receive the long press event. Don't bother for now... + if (movement_state.light_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_LIGHT_LONG_PRESS; + if (movement_state.mode_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_MODE_LONG_PRESS; + if (movement_state.alarm_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.alarm_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_ALARM_LONG_PRESS; } - if (movement_state.debounce_ticks_light + movement_state.debounce_ticks_mode + movement_state.debounce_ticks_alarm == 0) - movement_state.fast_ticks++; - if (movement_state.light_ticks > 0) movement_state.light_ticks--; - if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--; - // check timestamps and auto-fire the long-press events - // Notice: is it possible that two or more buttons have an identical timestamp? In this case - // only one of these buttons would receive the long press event. Don't bother for now... - if (movement_state.light_down_timestamp > 0) - if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) - event.event_type = EVENT_LIGHT_LONG_PRESS; - if (movement_state.mode_down_timestamp > 0) - if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) - event.event_type = EVENT_MODE_LONG_PRESS; - if (movement_state.alarm_down_timestamp > 0) - if (movement_state.fast_ticks - movement_state.alarm_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) - event.event_type = EVENT_ALARM_LONG_PRESS; // this is just a fail-safe; fast tick should be disabled as soon as the button is up, the LED times out, and/or the alarm finishes. // but if for whatever reason it isn't, this forces the fast tick off after 20 seconds. if (movement_state.fast_ticks >= 128 * 20) { diff --git a/movement/movement.h b/movement/movement.h index ed94b6f97..cab4d5bf1 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -275,15 +275,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 e6defaaf0bd5cd33ad59a860c6da3a62b766f599 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 20:48:17 -0400 Subject: [PATCH 12/46] 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 e4b5a0cf8..d526667ac 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -125,6 +125,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]; @@ -195,6 +197,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; } @@ -209,16 +214,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... @@ -259,15 +254,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; @@ -660,8 +655,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 @@ -676,7 +669,6 @@ 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_REALLY_LONG_PRESS_TICKS && diff > MOVEMENT_LONG_PRESS_TICKS) { return button_down_event_type + 3; @@ -686,29 +678,40 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e } } -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! @@ -720,23 +723,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 cab4d5bf1..ed94b6f97 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -275,10 +275,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 4f5c28bff043b9ffea6e409b75bb52c5b6ae59f6 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 21:05:19 -0400 Subject: [PATCH 13/46] Cleaned up code --- movement/movement.c | 58 +++++++++++++-------------------------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index d526667ac..4c106e30c 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -722,55 +722,29 @@ void cb_alarm_fired(void) { movement_state.needs_background_tasks_handled = true; } -void cb_fast_tick(void) { - if (movement_state.debounce_ticks_light > 0) movement_state.debounce_ticks_light--; - if (movement_state.debounce_ticks_alarm > 0) movement_state.debounce_ticks_alarm--; - if (movement_state.debounce_ticks_mode > 0) movement_state.debounce_ticks_mode--; - if (movement_state.debounce_btn_trig_light) { - bool pin_level = watch_get_pin_level(BTN_LIGHT); - movement_state.debounce_btn_trig_light = false; - if (pin_level) { - light_btn_action(pin_level); - } - else if (movement_state.debounce_ticks_light == 0) { - light_btn_action(pin_level); - movement_state.debounce_ticks_light = DEBOUNCE_TICKS; - } - else { - movement_state.light_down_timestamp = 0; - _movement_disable_fast_tick_if_possible(); - } - } - if (movement_state.debounce_btn_trig_alarm) { - bool pin_level = watch_get_pin_level(BTN_ALARM); - movement_state.debounce_btn_trig_alarm = false; - if (pin_level) { - alarm_btn_action(pin_level); - } - else if (movement_state.debounce_ticks_alarm == 0) { - alarm_btn_action(pin_level); - movement_state.debounce_ticks_alarm = DEBOUNCE_TICKS; - } - else { - movement_state.alarm_down_timestamp = 0; - _movement_disable_fast_tick_if_possible(); - } - } - if (movement_state.debounce_btn_trig_mode) { - bool pin_level = watch_get_pin_level(BTN_MODE); - movement_state.debounce_btn_trig_mode = false; +static void debounce_btn_press(uint8_t pin, uint8_t *debounce_ticks, bool *debounce_btn_trig, uint16_t *down_timestamp, void (*function)(bool)) { + if (*debounce_ticks > 0) (*debounce_ticks)--; + if (*debounce_btn_trig) { + bool pin_level = watch_get_pin_level(pin); + *debounce_btn_trig = false; if (pin_level) { - mode_btn_action(pin_level); + function(pin_level); } - else if (movement_state.debounce_ticks_mode == 0) { - mode_btn_action(pin_level); - movement_state.debounce_ticks_mode = DEBOUNCE_TICKS; + else if (*debounce_ticks == 0) { + function(pin_level); + *debounce_ticks = DEBOUNCE_TICKS; } else { - movement_state.mode_down_timestamp = 0; + *down_timestamp = 0; _movement_disable_fast_tick_if_possible(); } } +} + +void cb_fast_tick(void) { + debounce_btn_press(BTN_LIGHT, &movement_state.debounce_ticks_light, &movement_state.debounce_btn_trig_light, &movement_state.light_down_timestamp, light_btn_action); + debounce_btn_press(BTN_ALARM, &movement_state.debounce_ticks_alarm, &movement_state.debounce_btn_trig_alarm, &movement_state.alarm_down_timestamp, alarm_btn_action); + debounce_btn_press(BTN_MODE, &movement_state.debounce_ticks_mode, &movement_state.debounce_btn_trig_mode, &movement_state.mode_down_timestamp, mode_btn_action); if (movement_state.debounce_ticks_light + movement_state.debounce_ticks_mode + movement_state.debounce_ticks_alarm == 0) movement_state.fast_ticks++; if (movement_state.light_ticks > 0) movement_state.light_ticks--; From 6a9c8bb08a2662fcac3be1241ac42bf2412aa063 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 21:43:32 -0400 Subject: [PATCH 14/46] 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 4c106e30c..ec0ebee7f 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -125,7 +125,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]; @@ -668,7 +668,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_REALLY_LONG_PRESS_TICKS && diff > MOVEMENT_LONG_PRESS_TICKS) { return button_down_event_type + 3; @@ -723,21 +722,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 f03d177494a9b8c813347573382807433d7cc2c1 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 29 Jul 2024 23:53:25 -0400 Subject: [PATCH 15/46] 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 ec0ebee7f..07d83aaa0 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -208,6 +208,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); @@ -697,18 +698,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(); } @@ -721,28 +732,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 ed94b6f97..956366f1d 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -281,9 +281,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 1686c58961422b56fcc35e3301fe09f807cc376a Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Tue, 30 Jul 2024 07:27:47 -0400 Subject: [PATCH 16/46] 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 07d83aaa0..cbdf4867b 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -706,21 +706,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) { @@ -733,9 +731,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 a2343c3f31fb5e431d308ad1415e87c109a9102d Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Wed, 31 Jul 2024 07:22:33 -0400 Subject: [PATCH 17/46] 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 cbdf4867b..65d60a4b3 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -197,9 +197,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; } @@ -423,6 +420,9 @@ void app_init(void) { movement_state.birthdate.bit.day = MOVEMENT_DEFAULT_BIRTHDATE_DAY; 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(); @@ -669,6 +669,7 @@ 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_REALLY_LONG_PRESS_TICKS && diff > MOVEMENT_LONG_PRESS_TICKS) { return button_down_event_type + 3; @@ -678,18 +679,21 @@ 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) { _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; @@ -698,27 +702,19 @@ static void alarm_btn_action(bool pin_level) { event.event_type = event_type; } -static void debounce_btn_press(uint8_t pin, uint8_t *debounce_ticks, uint16_t *down_timestamp, void (*function)(bool)) { - bool pin_level = watch_get_pin_level(pin); - if (*debounce_ticks <= 1) { - function(pin_level); - *debounce_ticks = DEBOUNCE_TICKS; - } - else - *down_timestamp = 0; - _movement_enable_fast_tick_if_needed(); -} - void cb_light_btn_interrupt(void) { - debounce_btn_press(BTN_LIGHT, &movement_state.debounce_ticks_light, &movement_state.light_down_timestamp, light_btn_action); + movement_state.debounce_ticks_light = DEBOUNCE_TICKS; + _movement_enable_fast_tick_if_needed(); } void cb_mode_btn_interrupt(void) { - debounce_btn_press(BTN_MODE, &movement_state.debounce_ticks_mode, &movement_state.mode_down_timestamp, mode_btn_action); + movement_state.debounce_ticks_mode = DEBOUNCE_TICKS; + _movement_enable_fast_tick_if_needed(); } void cb_alarm_btn_interrupt(void) { - debounce_btn_press(BTN_ALARM, &movement_state.debounce_ticks_alarm, &movement_state.alarm_down_timestamp, alarm_btn_action); + movement_state.debounce_ticks_alarm = DEBOUNCE_TICKS; + _movement_enable_fast_tick_if_needed(); } void cb_alarm_btn_extwake(void) { @@ -731,9 +727,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 e36543ff0551362e42b40ec0e2432c0b1286b65f Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Wed, 31 Jul 2024 07:25:09 -0400 Subject: [PATCH 18/46] 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 65d60a4b3..ec1f72de8 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -680,21 +680,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 f8a13d85f7a6aed19ac0aae385a4e99ef2b92e07 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Wed, 31 Jul 2024 07:33:25 -0400 Subject: [PATCH 19/46] 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 ec1f72de8..b216d29f9 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -24,6 +24,7 @@ #define MOVEMENT_LONG_PRESS_TICKS 64 #define MOVEMENT_REALLY_LONG_PRESS_TICKS 384 +#define DEBOUNCE_TICKS 1 // In terms of *7.8125ms #include #include @@ -125,8 +126,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 c3b0bc978d4df65212df30f8312ed3c74eed1336 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sun, 11 Aug 2024 11:00:08 -0400 Subject: [PATCH 20/46] 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 | 49 ++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index b216d29f9..0f12a243d 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -25,6 +25,8 @@ #define MOVEMENT_LONG_PRESS_TICKS 64 #define MOVEMENT_REALLY_LONG_PRESS_TICKS 384 #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 @@ -196,6 +198,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; } @@ -419,9 +424,6 @@ void app_init(void) { movement_state.birthdate.bit.day = MOVEMENT_DEFAULT_BIRTHDATE_DAY; 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(); @@ -668,7 +670,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_REALLY_LONG_PRESS_TICKS && diff > MOVEMENT_LONG_PRESS_TICKS) { return button_down_event_type + 3; @@ -678,22 +679,19 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e } } -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; @@ -701,19 +699,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) { @@ -726,12 +732,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 606da3d3e97146a8b5ed5c7cb342642b89479c08 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 17 Aug 2024 02:45:22 -0400 Subject: [PATCH 21/46] Set the debounce tick variables to 0 to make the face work the same as stock. --- movement/movement.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/movement/movement.c b/movement/movement.c index 0f12a243d..d1251a5fb 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -27,6 +27,8 @@ #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 +#define DEBOUNCE_TICKS_DOWN 0 // In terms of *7.8125ms +#define DEBOUNCE_TICKS_UP 0 // In terms of *7.8125ms #include #include From 49702a2eb5dee5e224580fbcb7b67c378cbc397d Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 17 Aug 2024 02:52:30 -0400 Subject: [PATCH 22/46] 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 d1251a5fb..76c9ad609 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -702,14 +702,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 3fb795b0ac04741b2b9aa3a8ea9b7e99ee107c76 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Fri, 23 Aug 2024 17:35:16 -0400 Subject: [PATCH 23/46] Code review edits --- movement/movement.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 76c9ad609..2fa0b2071 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -25,10 +25,17 @@ #define MOVEMENT_LONG_PRESS_TICKS 64 #define MOVEMENT_REALLY_LONG_PRESS_TICKS 384 #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 -#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. +*/ +>>>>>>> c6f2bff (Code review edits) #include #include @@ -681,19 +688,21 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e } } +static movement_event_type_t btn_action(bool pin_level, int code, uint16_t *timestamp) { + _movement_reset_inactivity_countdown(); + return _figure_out_button_event(pin_level, code, timestamp); +} + static void light_btn_action(bool pin_level) { - _movement_reset_inactivity_countdown(); - event.event_type = _figure_out_button_event(pin_level, EVENT_LIGHT_BUTTON_DOWN, &movement_state.light_down_timestamp); + event.event_type = btn_action(pin_level, EVENT_LIGHT_BUTTON_DOWN, &movement_state.light_down_timestamp); } -static void mode_btn_action(bool pin_level) { - _movement_reset_inactivity_countdown(); - event.event_type = _figure_out_button_event(pin_level, EVENT_MODE_BUTTON_DOWN, &movement_state.mode_down_timestamp); +static void mode_btn_action(bool pin_level) { + event.event_type = btn_action(pin_level, EVENT_MODE_BUTTON_DOWN, &movement_state.mode_down_timestamp); } static void alarm_btn_action(bool pin_level) { - _movement_reset_inactivity_countdown(); - uint8_t event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); + uint8_t event_type = btn_action(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); if (movement_state.ignore_alarm_btn_after_sleep){ if (event_type == EVENT_ALARM_BUTTON_UP || event_type == EVENT_ALARM_LONG_UP) movement_state.ignore_alarm_btn_after_sleep = false; return; @@ -712,6 +721,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); } @@ -734,9 +749,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 b9ac6497df2d3ff03cbd0cfb9e6518324c3bcb15 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Fri, 23 Aug 2024 22:25:02 -0400 Subject: [PATCH 24/46] 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 2fa0b2071..14faf4713 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -721,10 +721,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 2af59b2e9502ecbe45df5dd5884d4ef647e8f3ed 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 25/46] 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 cc21a5a8f..e0f21af10 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 d39479582fa37cd2c17d9776305f9ed2cd395794 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 26/46] 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 e0f21af10..27c1d3971 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 6ca759a33ebdb980db0db6af6b4d19276d0bf17e Mon Sep 17 00:00:00 2001 From: Joseph Bryant Date: Sun, 18 Aug 2024 21:50:41 +0100 Subject: [PATCH 27/46] 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 be04040e3..6ae3d935b 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 b0c2652c8e5339648bfd728b25d459fa0417e5bf Mon Sep 17 00:00:00 2001 From: Joseph Bryant Date: Sun, 18 Aug 2024 22:03:05 +0100 Subject: [PATCH 28/46] 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 6ae3d935b..b48ef595a 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 71e2f23533ca07b04b02d5c01b69f74e9b7bdf2e Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 10 Aug 2024 06:38:46 -0400 Subject: [PATCH 29/46] 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 eab5cd8d3..66b40c423 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 a32fb3e49a8831e7be0384b062c165ed003f78bb Mon Sep 17 00:00:00 2001 From: Struan Date: Wed, 7 Aug 2024 22:24:57 -0600 Subject: [PATCH 30/46] 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 fbe8cbb14..166b26e11 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 10afd4173422c65f34c9123112555c86d250bb1c Mon Sep 17 00:00:00 2001 From: Christian Buschau Date: Sat, 3 Aug 2024 12:22:15 +0200 Subject: [PATCH 31/46] 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 27601edcc..d9bf0f7c8 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 cc1077aa2..9992bbf83 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 a8c88e44a..4b4be644d 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 166b26e11..269612f73 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, 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}; 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 5c721058b604b601af52eaa4afcfbec05d5c3aad Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 3 Aug 2024 11:20:25 -0400 Subject: [PATCH 32/46] 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 ef27ffef1..f97924742 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 d9bf0f7c8..4429611ea 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 9992bbf83..74ed35b73 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 4b4be644d..02cbb17de 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 269612f73..c760fd9b5 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 38fe949964e60a7a8c4201c1f8d2c739778e5bfe Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 10 Aug 2024 07:40:52 -0400 Subject: [PATCH 33/46] 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 f97924742..8d6c1db9b 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 4429611ea..aa65321e5 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 74ed35b73..99b0f87fd 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 02cbb17de..503dffc99 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 c760fd9b5..8ba56cba9 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 64b3bb791..c00791e76 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 e2326d131..5533e1966 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 90102f60643c695520c92a89468e26f12819c757 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 3 Aug 2024 11:38:45 -0400 Subject: [PATCH 34/46] 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 ad2f53394..98c7103fb 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 0348d178dea19418f3663f838378a881d6d01b45 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 3 Aug 2024 11:42:42 -0400 Subject: [PATCH 35/46] 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 98c7103fb..fbf60cfee 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 0fa45e16595051b505ffdb75d74980b6f4a583f7 Mon Sep 17 00:00:00 2001 From: Robert Masen Date: Fri, 2 Aug 2024 18:20:44 -0500 Subject: [PATCH 36/46] 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 73bdef410..8ce593454 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 29fbed038..9cdb29028 100644 --- a/watch-library/simulator/shell.html +++ b/watch-library/simulator/shell.html @@ -905,6 +905,11 @@

Location

+

Temp.

+
+ C + +
@@ -962,6 +967,7 @@

Location

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 @@

Location

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 ba505c4eca75679bf194dccbd20c52a68922ec95 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 8 Jul 2024 18:32:41 -0400 Subject: [PATCH 37/46] 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 14faf4713..4ccbf5b8a 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -419,7 +419,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 66b40c423..badcdfb9b 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 c96e8d1fd..2d4de9d45 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 740089795126927f5dda7a2e3b7a754bba30949b Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 8 Jul 2024 18:33:17 -0400 Subject: [PATCH 38/46] 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 2d4de9d45..22979773e 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 7acc9372b11b70867afa8c219614d8b044fffe95 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Wed, 10 Jul 2024 07:22:55 -0400 Subject: [PATCH 39/46] 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 4ccbf5b8a..603cd5f6c 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -370,6 +370,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()) { @@ -418,12 +426,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 badcdfb9b..20a02e7dc 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 fbc2c4b3e..ac4ec2ee5 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 b10fa82b27d3608279c524c058e2300929ef0c5d Mon Sep 17 00:00:00 2001 From: Joseph Bryant Date: Fri, 30 Aug 2024 07:23:28 +0100 Subject: [PATCH 40/46] 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 efdad6dda..a25b667b0 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 8a12a9dfda399b99bd268b468311888d77bd6218 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Mon, 26 Aug 2024 21:40:56 -0400 Subject: [PATCH 41/46] 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 7ea4141bf..3f15c52c7 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 9876778a656ebbd557e33dbd160a783533792644 Mon Sep 17 00:00:00 2001 From: Metehan <99metehanarslan@gmail.com> Date: Mon, 2 Sep 2024 02:11:27 +0300 Subject: [PATCH 42/46] 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 27c1d3971..657285256 100644 --- a/movement/movement_custom_signal_tunes.h +++ b/movement/movement_custom_signal_tunes.h @@ -83,4 +83,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_ From b344b19302d314a0a367ab02868eed8ec9b4af55 Mon Sep 17 00:00:00 2001 From: Metehan <99metehanarslan@gmail.com> Date: Sun, 1 Sep 2024 02:33:05 +0300 Subject: [PATCH 43/46] 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 657285256..d9032a48f 100644 --- a/movement/movement_custom_signal_tunes.h +++ b/movement/movement_custom_signal_tunes.h @@ -100,4 +100,21 @@ int8_t signal_tune[] = { }; #endif // SIGNAL_TUNE_POWER_RANGERS +#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 fe4a6a3d53654fb1489b5dad13654e643146fec6 Mon Sep 17 00:00:00 2001 From: Metehan <99metehanarslan@gmail.com> Date: Mon, 2 Sep 2024 00:03:21 +0300 Subject: [PATCH 44/46] 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 d9032a48f..2f7ba4011 100644 --- a/movement/movement_custom_signal_tunes.h +++ b/movement/movement_custom_signal_tunes.h @@ -102,17 +102,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 d818a2e8f528ec17d274dc960afaf2977d29d4c2 Mon Sep 17 00:00:00 2001 From: Alex Maestas Date: Wed, 4 Sep 2024 20:10:37 +0000 Subject: [PATCH 45/46] bump to the newer upload-artifact github action --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6b4fc7939..84d179a6d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ on: env: COLOR: BLUE -jobs: +jobs: build: container: image: ghcr.io/armmbed/mbed-os-env:latest @@ -29,7 +29,7 @@ jobs: run: make working-directory: 'movement/make' - name: Upload UF2 - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: watch.uf2 path: movement/make/build/watch.uf2 @@ -52,7 +52,7 @@ jobs: cp watch.html index.html tar -czf simulator.tar.gz index.html watch.wasm watch.js - name: Upload simulator build - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: simulator.tar.gz path: movement/make/build-sim/simulator.tar.gz From 9c60842b246fe05d39c6df16ac7294ee62fbd689 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Sat, 31 Aug 2024 15:59:26 -0400 Subject: [PATCH 46/46] adding really long press for each button --- movement/movement.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 603cd5f6c..b2e3066e9 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -24,7 +24,6 @@ #define MOVEMENT_LONG_PRESS_TICKS 64 #define MOVEMENT_REALLY_LONG_PRESS_TICKS 384 -#define DEBOUNCE_TICKS 1 // In terms of *7.8125ms #define DEBOUNCE_TICKS_DOWN 0 #define DEBOUNCE_TICKS_UP 0 /* @@ -35,7 +34,6 @@ It is not suggested to set this value to one for debouncing, as the callback occ 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. */ ->>>>>>> c6f2bff (Code review edits) #include #include @@ -769,15 +767,33 @@ void cb_fast_tick(void) { // 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) + //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.light_down_timestamp > 0) { + if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_REALLY_LONG_PRESS_TICKS + 1) { + event.event_type = EVENT_LIGHT_REALLY_LONG_PRESS; + } else 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) + } + } + if (movement_state.mode_down_timestamp > 0) { + if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_REALLY_LONG_PRESS_TICKS + 1) { + event.event_type = EVENT_MODE_REALLY_LONG_PRESS; + } else 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) + } + } + if (movement_state.alarm_down_timestamp > 0) { + if (movement_state.fast_ticks - movement_state.alarm_down_timestamp == MOVEMENT_REALLY_LONG_PRESS_TICKS + 1) { + event.event_type = EVENT_ALARM_REALLY_LONG_PRESS; + } else 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) {