From 2ce07f9539eaa2b20c69d078052a9b90e1ae1f67 Mon Sep 17 00:00:00 2001 From: "R. Alex Barbieri" <> Date: Sat, 27 Apr 2024 13:33:32 -0500 Subject: [PATCH 01/11] add blinking to DST toggle in settings page --- movement/watch_faces/settings/set_time_face.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/movement/watch_faces/settings/set_time_face.c b/movement/watch_faces/settings/set_time_face.c index 16011e3..fb0c806 100644 --- a/movement/watch_faces/settings/set_time_face.c +++ b/movement/watch_faces/settings/set_time_face.c @@ -185,6 +185,9 @@ bool set_time_face_loop(movement_event_t event, movement_settings_t *settings, v case 5: buf[8] = buf[9] = ' '; break; + case 7: + buf[9] = ' '; + break; } } From 149911e4addf203d90ed84f8a6884508637ef6d1 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Fri, 2 Aug 2024 01:23:21 -0400 Subject: [PATCH 02/11] Time now auto-updates with DST --- movement/movement.c | 16 +++++++++ movement/movement.h | 1 + movement/watch_faces/clock/clock_face.c | 24 +++++++++++--- .../watch_faces/clock/simple_clock_face.c | 24 +++++++++++--- movement/watch_faces/settings/set_time_face.c | 10 ++---- watch-library/shared/watch/watch_utility.c | 33 +++++++++++++++++++ watch-library/shared/watch/watch_utility.h | 13 ++++++++ 7 files changed, 105 insertions(+), 16 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 8b45535..5c804fe 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -34,6 +34,7 @@ #include "filesystem.h" #include "movement.h" #include "shell.h" +#include "watch_utility.h" #ifndef MOVEMENT_FIRMWARE #include "movement_config.h" @@ -467,6 +468,21 @@ uint8_t movement_claim_backup_register(void) { return movement_state.next_available_backup_register++; } +int16_t get_timezone_offset(uint8_t timezone_idx, watch_date_time date_time) { + if (!movement_state.settings.bit.dst_active) return movement_timezone_offsets[timezone_idx]; + uint8_t dst_result = is_dst(date_time); + switch (dst_result) + { + case DST_STARTED: + case DST_OCCURRING: + return movement_timezone_offsets[movement_dst_jump_table[timezone_idx]]; + case DST_ENDING: + case DST_ENDED: + default: + return movement_timezone_offsets[timezone_idx]; + } +} + void app_init(void) { #if defined(NO_FREQCORR) watch_rtc_freqcorr_write(0, 0); diff --git a/movement/movement.h b/movement/movement.h index d19ab3f..a89e377 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -314,5 +314,6 @@ void movement_play_alarm(void); void movement_play_alarm_beeps(uint8_t rounds, BuzzerNote alarm_note); uint8_t movement_claim_backup_register(void); +int16_t get_timezone_offset(uint8_t timezone_idx, watch_date_time date_time); #endif // MOVEMENT_H_ diff --git a/movement/watch_faces/clock/clock_face.c b/movement/watch_faces/clock/clock_face.c index eab5cd8..68019d8 100644 --- a/movement/watch_faces/clock/clock_face.c +++ b/movement/watch_faces/clock/clock_face.c @@ -280,12 +280,28 @@ void clock_face_resign(movement_settings_t *settings, void *context) { (void) context; } -bool clock_face_wants_background_task(movement_settings_t *settings, void *context) { - (void) settings; - clock_state_t *state = (clock_state_t *) context; - if (!state->time_signal_enabled) return false; +static void check_and_act_on_daylight_savings(bool dst_active, watch_date_time date_time) { + if (!dst_active) return; + uint8_t dst_result = is_dst(date_time); + switch (dst_result) + { + case DST_STARTED: + date_time.unit.hour = (date_time.unit.hour + 1) % 24; + break; + case DST_ENDING: + date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24; + break; + default: + return; + } + watch_rtc_set_date_time(date_time); +} +bool clock_face_wants_background_task(movement_settings_t *settings, void *context) { + clock_state_t *state = (clock_state_t *) context; watch_date_time date_time = watch_rtc_get_date_time(); + check_and_act_on_daylight_savings(settings->bit.dst_active, date_time); + if (!state->time_signal_enabled) return false; return date_time.unit.minute == 0; } diff --git a/movement/watch_faces/clock/simple_clock_face.c b/movement/watch_faces/clock/simple_clock_face.c index fbc2c4b..c0f8372 100644 --- a/movement/watch_faces/clock/simple_clock_face.c +++ b/movement/watch_faces/clock/simple_clock_face.c @@ -150,12 +150,28 @@ void simple_clock_face_resign(movement_settings_t *settings, void *context) { (void) context; } -bool simple_clock_face_wants_background_task(movement_settings_t *settings, void *context) { - (void) settings; - simple_clock_state_t *state = (simple_clock_state_t *)context; - if (!state->signal_enabled) return false; +static void check_and_act_on_daylight_savings(bool dst_active, watch_date_time date_time) { + if (!dst_active) return; + uint8_t dst_result = is_dst(date_time); + switch (dst_result) + { + case DST_STARTED: + date_time.unit.hour = (date_time.unit.hour + 1) % 24; + break; + case DST_ENDING: + date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24; + break; + default: + return; + } + watch_rtc_set_date_time(date_time); +} +bool simple_clock_face_wants_background_task(movement_settings_t *settings, void *context) { + simple_clock_state_t *state = (simple_clock_state_t *)context; watch_date_time date_time = watch_rtc_get_date_time(); + check_and_act_on_daylight_savings(settings->bit.dst_active, date_time); + if (!state->signal_enabled) return false; return date_time.unit.minute == 0; } diff --git a/movement/watch_faces/settings/set_time_face.c b/movement/watch_faces/settings/set_time_face.c index fb0c806..90edac2 100644 --- a/movement/watch_faces/settings/set_time_face.c +++ b/movement/watch_faces/settings/set_time_face.c @@ -67,13 +67,6 @@ static void _handle_alarm_button(movement_settings_t *settings, watch_date_time if (settings->bit.time_zone > 40) settings->bit.time_zone = 0; break; case 7: // daylight savings time - if (settings->bit.dst_active) { // deactivate DST - date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24; - settings->bit.time_zone = movement_dst_inverse_jump_table[settings->bit.time_zone]; - } else { // activate DST - date_time.unit.hour = (date_time.unit.hour + 1) % 24; - settings->bit.time_zone = movement_dst_jump_table[settings->bit.time_zone]; - } settings->bit.dst_active = !settings->bit.dst_active; break; } @@ -161,8 +154,9 @@ bool set_time_face_loop(movement_event_t event, movement_settings_t *settings, v watch_clear_colon(); sprintf(buf, "%s ", set_time_face_titles[current_page]); } else { + int16_t tz = get_timezone_offset(settings->bit.time_zone, date_time); watch_set_colon(); - sprintf(buf, "%s %3d%02d ", set_time_face_titles[current_page], (int8_t) (movement_timezone_offsets[settings->bit.time_zone] / 60), (int8_t) (movement_timezone_offsets[settings->bit.time_zone] % 60) * (movement_timezone_offsets[settings->bit.time_zone] < 0 ? -1 : 1)); + sprintf(buf, "%s %3d%02d ", set_time_face_titles[current_page], (int8_t) (tz / 60), (int8_t) (tz % 60) * (tz < 0 ? -1 : 1)); } } else { // daylight savings watch_clear_colon(); diff --git a/watch-library/shared/watch/watch_utility.c b/watch-library/shared/watch/watch_utility.c index 64b3bb7..1410e41 100644 --- a/watch-library/shared/watch/watch_utility.c +++ b/watch-library/shared/watch/watch_utility.c @@ -83,6 +83,39 @@ uint8_t is_leap(uint16_t y) return !(y%4) && ((y%100) || !(y%400)); } +uint8_t is_dst(watch_date_time date_time) { + uint8_t weekday_first_of_month; + watch_date_time dst_start_time; + watch_date_time dst_end_time; + uint32_t unix_dst_start_time; + uint32_t unix_dst_end_time; + uint32_t unix_curr_time; + + dst_start_time.unit.month = 3; + dst_start_time.unit.hour = 2; + dst_start_time.unit.minute = 0; + dst_start_time.unit.second = 0; + weekday_first_of_month = watch_utility_get_iso8601_weekday_number(date_time.unit.year, dst_start_time.unit.month, 1); + dst_start_time.unit.day = 15 - weekday_first_of_month; + unix_dst_start_time = watch_utility_date_time_to_unix_time(dst_start_time, 0); + + dst_end_time.unit.month = 11; + dst_end_time.unit.hour = 2; + dst_end_time.unit.minute = 0; + dst_end_time.unit.second = 0; + weekday_first_of_month = watch_utility_get_iso8601_weekday_number(date_time.unit.year, dst_end_time.unit.month, 1); + dst_end_time.unit.day = 15 - weekday_first_of_month; + unix_dst_end_time = watch_utility_date_time_to_unix_time(dst_end_time, 0); + + date_time.unit.second = 0; + unix_curr_time = watch_utility_date_time_to_unix_time(date_time, 0); + + if (unix_curr_time == unix_dst_start_time) return DST_STARTED; + if (unix_curr_time == unix_dst_end_time) return DST_ENDING; + if (unix_curr_time > unix_dst_end_time || unix_curr_time < unix_dst_start_time) return DST_ENDED; + return DST_OCCURRING; +} + uint16_t watch_utility_days_since_new_year(uint16_t year, uint8_t month, uint8_t day) { uint16_t DAYS_SO_FAR[] = { 0, // Jan diff --git a/watch-library/shared/watch/watch_utility.h b/watch-library/shared/watch/watch_utility.h index e2326d1..d3f3981 100644 --- a/watch-library/shared/watch/watch_utility.h +++ b/watch-library/shared/watch/watch_utility.h @@ -45,6 +45,13 @@ typedef struct { uint32_t days; // 0-4294967295 } watch_duration_t; +typedef enum { + DST_STARTED, + DST_OCCURRING, + DST_ENDING, + DST_ENDED +} dst_t; + /** @brief Returns a two-letter weekday for the given timestamp, suitable for display * in positions 0-1 of the watch face * @param date_time The watch_date_time whose weekday you want. @@ -78,6 +85,12 @@ uint16_t watch_utility_days_since_new_year(uint16_t year, uint8_t month, uint8_t */ uint8_t is_leap(uint16_t year); +/** @brief Returns off of dst_t based off if DST is occurring, srted, ended, or none of those. + * @param date_time The watch_date_time that you wish to convert. + * @return DST_OCCURRING, DST_HAPPENING, DST_ENDING, DST_ENDED + */ +uint8_t is_dst(watch_date_time date_time); + /** @brief Returns the UNIX time (seconds since 1970) for a given date/time in UTC. * @param date_time The watch_date_time that you wish to convert. * @param year The year of the date you wish to convert. From 4c546b14dc9ef8aa65dcee6560417665396c3bf0 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Fri, 2 Aug 2024 01:25:01 -0400 Subject: [PATCH 03/11] The timezone now auto-corrects with DST (but still displays the same offset in the settings screen to the user) --- movement/movement.c | 44 ------------------- movement/movement.h | 1 - movement/watch_faces/clock/beats_face.c | 4 +- .../clock/day_night_percentage_face.c | 5 ++- movement/watch_faces/clock/mars_time_face.c | 2 +- .../watch_faces/clock/world_clock2_face.c | 8 ++-- movement/watch_faces/clock/world_clock_face.c | 14 ++++-- .../watch_faces/complication/astronomy_face.c | 2 +- .../watch_faces/complication/countdown_face.c | 11 ++--- .../complication/moon_phase_face.c | 5 ++- .../watch_faces/complication/orrery_face.c | 2 +- .../complication/planetary_hours_face.c | 7 +-- .../complication/planetary_time_face.c | 8 ++-- .../watch_faces/complication/sailing_face.c | 15 ++++--- .../watch_faces/complication/solstice_face.c | 3 +- .../complication/sunrise_sunset_face.c | 5 ++- .../watch_faces/complication/timer_face.c | 11 ++--- .../watch_faces/complication/tomato_face.c | 11 ++--- movement/watch_faces/complication/totp_face.c | 5 ++- .../watch_faces/complication/totp_face_lfs.c | 3 +- .../accelerometer_data_acquisition_face.c | 2 +- .../settings/set_time_hackwatch_face.c | 5 ++- 22 files changed, 75 insertions(+), 98 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 5c804fe..52a9ac0 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -208,50 +208,6 @@ const uint8_t movement_dst_jump_table[] = { 0 // 40 AST + 1 = UTC }; -const uint8_t movement_dst_inverse_jump_table[] = { - 40, // 0 - 0, // 1 - 1, // 2 - 2, // 3 - 4, // 4 - 3, // 5 - 4, // 6 - 5, // 7 - 6, // 8 - 9, // 9 - 7, // 10 - 8, // 11 - 10, // 12 - 12, // 13 - 14, // 14 - 13, // 15 - 16, // 16 - 15, // 17 - 16, // 18 - 17, // 19 - 19, // 20 - 21, // 21 - 20, // 22 - 21, // 23 - 24, // 24 - 25, // 25 - 25, // 26 - 26, // 27 - 28, // 28 - 27, // 29 - 29, // 30 - 30, // 31 - 31, // 32 - 32, // 33 - 34, // 34 - 33, // 35 - 34, // 36 - 35, // 37 - 36, // 38 - 37, // 39 - 39 // 40 -}; - const char movement_valid_position_0_chars[] = " AaBbCcDdEeFGgHhIiJKLMNnOoPQrSTtUuWXYZ-='+\\/0123456789"; const char movement_valid_position_1_chars[] = " ABCDEFHlJLNORTtUX-='01378"; diff --git a/movement/movement.h b/movement/movement.h index a89e377..9aa1dbc 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -130,7 +130,6 @@ typedef struct { extern const int16_t movement_timezone_offsets[]; extern const uint8_t movement_dst_jump_table[]; -extern const uint8_t movement_dst_inverse_jump_table[]; extern const char movement_valid_position_0_chars[]; extern const char movement_valid_position_1_chars[]; diff --git a/movement/watch_faces/clock/beats_face.c b/movement/watch_faces/clock/beats_face.c index 85bcbe0..6954396 100644 --- a/movement/watch_faces/clock/beats_face.c +++ b/movement/watch_faces/clock/beats_face.c @@ -61,7 +61,7 @@ bool beats_face_loop(movement_event_t event, movement_settings_t *settings, void case EVENT_ACTIVATE: case EVENT_TICK: date_time = watch_rtc_get_date_time(); - centibeats = clock2beats(date_time.unit.hour, date_time.unit.minute, date_time.unit.second, event.subsecond, movement_timezone_offsets[settings->bit.time_zone]); + centibeats = clock2beats(date_time.unit.hour, date_time.unit.minute, date_time.unit.second, event.subsecond, get_timezone_offset(settings->bit.time_zone, date_time)); if (centibeats == state->last_centibeat_displayed) { // we missed this update, try again next subsecond state->next_subsecond_update = (event.subsecond + 1) % BEAT_REFRESH_FREQUENCY; @@ -76,7 +76,7 @@ bool beats_face_loop(movement_event_t event, movement_settings_t *settings, void case EVENT_LOW_ENERGY_UPDATE: if (!watch_tick_animation_is_running()) watch_start_tick_animation(432); date_time = watch_rtc_get_date_time(); - centibeats = clock2beats(date_time.unit.hour, date_time.unit.minute, date_time.unit.second, event.subsecond, movement_timezone_offsets[settings->bit.time_zone]); + centibeats = clock2beats(date_time.unit.hour, date_time.unit.minute, date_time.unit.second, event.subsecond, get_timezone_offset(settings->bit.time_zone, date_time)); sprintf(buf, "bt %4lu ", centibeats / 100); watch_display_string(buf, 0); diff --git a/movement/watch_faces/clock/day_night_percentage_face.c b/movement/watch_faces/clock/day_night_percentage_face.c index 86f07f9..4041c05 100644 --- a/movement/watch_faces/clock/day_night_percentage_face.c +++ b/movement/watch_faces/clock/day_night_percentage_face.c @@ -62,7 +62,8 @@ void day_night_percentage_face_setup(movement_settings_t *settings, uint8_t watc if (*context_ptr == NULL) { *context_ptr = malloc(sizeof(day_night_percentage_state_t)); day_night_percentage_state_t *state = (day_night_percentage_state_t *)*context_ptr; - watch_date_time utc_now = watch_utility_date_time_convert_zone(watch_rtc_get_date_time(), movement_timezone_offsets[settings->bit.time_zone] * 60, 0); + watch_date_time date_time = watch_rtc_get_date_time(); + watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, get_timezone_offset(settings->bit.time_zone, date_time) * 60, 0); recalculate(utc_now, state); } } @@ -77,7 +78,7 @@ bool day_night_percentage_face_loop(movement_event_t event, movement_settings_t char buf[12]; watch_date_time date_time = watch_rtc_get_date_time(); - watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60, 0); + watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, get_timezone_offset(settings->bit.time_zone, date_time) * 60, 0); switch (event.event_type) { case EVENT_ACTIVATE: diff --git a/movement/watch_faces/clock/mars_time_face.c b/movement/watch_faces/clock/mars_time_face.c index 30f6a34..304c615 100644 --- a/movement/watch_faces/clock/mars_time_face.c +++ b/movement/watch_faces/clock/mars_time_face.c @@ -70,7 +70,7 @@ static void _h_to_hms(mars_clock_hms_t *date_time, double h) { static void _update(movement_settings_t *settings, mars_time_state_t *state) { char buf[11]; watch_date_time date_time = watch_rtc_get_date_time(); - uint32_t now = watch_utility_date_time_to_unix_time(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60); + uint32_t now = watch_utility_date_time_to_unix_time(date_time, get_timezone_offset(settings->bit.time_zone, date_time) * 60); // TODO: I'm skipping over some steps here. // https://www.giss.nasa.gov/tools/mars24/help/algorithm.html double jdut = 2440587.5 + ((double)now / 86400.0); diff --git a/movement/watch_faces/clock/world_clock2_face.c b/movement/watch_faces/clock/world_clock2_face.c index 2e1e969..6ff806b 100644 --- a/movement/watch_faces/clock/world_clock2_face.c +++ b/movement/watch_faces/clock/world_clock2_face.c @@ -165,6 +165,7 @@ static bool mode_display(movement_event_t event, movement_settings_t *settings, uint32_t timestamp; uint32_t previous_date_time; watch_date_time date_time; + int16_t tz; switch (event.event_type) { case EVENT_ACTIVATE: @@ -183,8 +184,9 @@ static bool mode_display(movement_event_t event, movement_settings_t *settings, /* Determine current time at time zone and store date/time */ date_time = watch_rtc_get_date_time(); - timestamp = watch_utility_date_time_to_unix_time(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60); - date_time = watch_utility_date_time_from_unix_time(timestamp, movement_timezone_offsets[state->current_zone] * 60); + tz = get_timezone_offset(settings->bit.time_zone, date_time); + timestamp = watch_utility_date_time_to_unix_time(date_time, tz * 60); + date_time = watch_utility_date_time_from_unix_time(timestamp, tz * 60); previous_date_time = state->previous_date_time; state->previous_date_time = date_time.reg; @@ -284,7 +286,7 @@ static bool mode_settings(movement_event_t event, movement_settings_t *settings, watch_clear_indicator(WATCH_INDICATOR_PM); refresh_face = false; } - result = div(movement_timezone_offsets[state->current_zone], 60); + result = div(get_timezone_offset(state->current_zone, watch_rtc_get_date_time()), 60); hours = result.quot; minutes = result.rem; diff --git a/movement/watch_faces/clock/world_clock_face.c b/movement/watch_faces/clock/world_clock_face.c index b12d9cd..c34db92 100644 --- a/movement/watch_faces/clock/world_clock_face.c +++ b/movement/watch_faces/clock/world_clock_face.c @@ -54,6 +54,7 @@ void world_clock_face_activate(movement_settings_t *settings, void *context) { static bool world_clock_face_do_display_mode(movement_event_t event, movement_settings_t *settings, world_clock_state_t *state) { char buf[11]; uint8_t pos; + int16_t tz; uint32_t timestamp; uint32_t previous_date_time; @@ -67,8 +68,9 @@ static bool world_clock_face_do_display_mode(movement_event_t event, movement_se case EVENT_TICK: case EVENT_LOW_ENERGY_UPDATE: date_time = watch_rtc_get_date_time(); - timestamp = watch_utility_date_time_to_unix_time(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60); - date_time = watch_utility_date_time_from_unix_time(timestamp, movement_timezone_offsets[state->settings.bit.timezone_index] * 60); + tz = get_timezone_offset(settings->bit.time_zone, date_time); + timestamp = watch_utility_date_time_to_unix_time(date_time, tz * 60); + date_time = watch_utility_date_time_from_unix_time(timestamp, tz * 60); previous_date_time = state->previous_date_time; state->previous_date_time = date_time.reg; @@ -125,6 +127,8 @@ static bool world_clock_face_do_display_mode(movement_event_t event, movement_se } static bool _world_clock_face_do_settings_mode(movement_event_t event, movement_settings_t *settings, world_clock_state_t *state) { + watch_date_time date_time; + int16_t tz; switch (event.event_type) { case EVENT_MODE_BUTTON_UP: if (state->backup_register) watch_store_backup_data(state->settings.reg, state->backup_register); @@ -168,11 +172,13 @@ static bool _world_clock_face_do_settings_mode(movement_event_t event, movement_ } char buf[13]; + date_time = watch_rtc_get_date_time(); + tz = get_timezone_offset(settings->bit.time_zone, date_time); sprintf(buf, "%c%c %3d%02d ", movement_valid_position_0_chars[state->settings.bit.char_0], movement_valid_position_1_chars[state->settings.bit.char_1], - (int8_t) (movement_timezone_offsets[state->settings.bit.timezone_index] / 60), - (int8_t) (movement_timezone_offsets[state->settings.bit.timezone_index] % 60) * (movement_timezone_offsets[state->settings.bit.timezone_index] < 0 ? -1 : 1)); + (int8_t) (tz / 60), + (int8_t) (tz % 60) * (tz < 0 ? -1 : 1)); watch_set_colon(); watch_clear_indicator(WATCH_INDICATOR_PM); diff --git a/movement/watch_faces/complication/astronomy_face.c b/movement/watch_faces/complication/astronomy_face.c index 204a0a3..8db8760 100644 --- a/movement/watch_faces/complication/astronomy_face.c +++ b/movement/watch_faces/complication/astronomy_face.c @@ -80,7 +80,7 @@ static void _astronomy_face_recalculate(movement_settings_t *settings, astronomy #endif watch_date_time date_time = watch_rtc_get_date_time(); - uint32_t timestamp = watch_utility_date_time_to_unix_time(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60); + uint32_t timestamp = watch_utility_date_time_to_unix_time(date_time, get_timezone_offset(settings->bit.time_zone, date_time) * 60); date_time = watch_utility_date_time_from_unix_time(timestamp, 0); double jd = astro_convert_date_to_julian_date(date_time.unit.year + WATCH_RTC_REFERENCE_YEAR, date_time.unit.month, date_time.unit.day, date_time.unit.hour, date_time.unit.minute, date_time.unit.second); diff --git a/movement/watch_faces/complication/countdown_face.c b/movement/watch_faces/complication/countdown_face.c index be04040..04dc592 100644 --- a/movement/watch_faces/complication/countdown_face.c +++ b/movement/watch_faces/complication/countdown_face.c @@ -44,8 +44,8 @@ static void abort_quick_ticks(countdown_state_t *state) { } } -static inline int32_t get_tz_offset(movement_settings_t *settings) { - return movement_timezone_offsets[settings->bit.time_zone] * 60; +static inline int32_t get_tz_offset(movement_settings_t *settings, watch_date_time date_time) { + return get_timezone_offset(settings->bit.time_zone, date_time) * 60; } static inline void store_countdown(countdown_state_t *state) { @@ -70,11 +70,12 @@ static inline void button_beep(movement_settings_t *settings) { static void start(countdown_state_t *state, movement_settings_t *settings) { watch_date_time now = watch_rtc_get_date_time(); + int16_t tz = get_tz_offset(settings, now); state->mode = cd_running; - state->now_ts = watch_utility_date_time_to_unix_time(now, get_tz_offset(settings)); + state->now_ts = watch_utility_date_time_to_unix_time(now, tz); state->target_ts = watch_utility_offset_timestamp(state->now_ts, state->hours, state->minutes, state->seconds); - watch_date_time target_dt = watch_utility_date_time_from_unix_time(state->target_ts, get_tz_offset(settings)); + watch_date_time target_dt = watch_utility_date_time_from_unix_time(state->target_ts, tz); movement_schedule_background_task(target_dt); watch_set_indicator(WATCH_INDICATOR_BELL); } @@ -176,7 +177,7 @@ void countdown_face_activate(movement_settings_t *settings, void *context) { countdown_state_t *state = (countdown_state_t *)context; if(state->mode == cd_running) { watch_date_time now = watch_rtc_get_date_time(); - state->now_ts = watch_utility_date_time_to_unix_time(now, get_tz_offset(settings)); + state->now_ts = watch_utility_date_time_to_unix_time(now, get_tz_offset(settings, now)); watch_set_indicator(WATCH_INDICATOR_BELL); } watch_set_colon(); diff --git a/movement/watch_faces/complication/moon_phase_face.c b/movement/watch_faces/complication/moon_phase_face.c index f74de64..47ed6e6 100644 --- a/movement/watch_faces/complication/moon_phase_face.c +++ b/movement/watch_faces/complication/moon_phase_face.c @@ -59,8 +59,9 @@ static void _update(movement_settings_t *settings, moon_phase_state_t *state, ui (void)state; char buf[11]; watch_date_time date_time = watch_rtc_get_date_time(); - uint32_t now = watch_utility_date_time_to_unix_time(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60) + offset; - date_time = watch_utility_date_time_from_unix_time(now, movement_timezone_offsets[settings->bit.time_zone] * 60); + int16_t tz = get_timezone_offset(settings->bit.time_zone, date_time); + uint32_t now = watch_utility_date_time_to_unix_time(date_time, tz * 60) + offset; + date_time = watch_utility_date_time_from_unix_time(now, tz * 60); double currentfrac = fmod(now - FIRST_MOON, LUNAR_SECONDS) / LUNAR_SECONDS; double currentday = currentfrac * LUNAR_DAYS; uint8_t phase_index = 0; diff --git a/movement/watch_faces/complication/orrery_face.c b/movement/watch_faces/complication/orrery_face.c index 42fdf81..0570dd4 100644 --- a/movement/watch_faces/complication/orrery_face.c +++ b/movement/watch_faces/complication/orrery_face.c @@ -48,7 +48,7 @@ static const char orrery_celestial_body_names[NUM_AVAILABLE_BODIES][3] = { static void _orrery_face_recalculate(movement_settings_t *settings, orrery_state_t *state) { watch_date_time date_time = watch_rtc_get_date_time(); - uint32_t timestamp = watch_utility_date_time_to_unix_time(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60); + uint32_t timestamp = watch_utility_date_time_to_unix_time(date_time, get_timezone_offset(settings->bit.time_zone, date_time) * 60); date_time = watch_utility_date_time_from_unix_time(timestamp, 0); double jd = astro_convert_date_to_julian_date(date_time.unit.year + WATCH_RTC_REFERENCE_YEAR, date_time.unit.month, date_time.unit.day, date_time.unit.hour, date_time.unit.minute, date_time.unit.second); double et = astro_convert_jd_to_julian_millenia_since_j2000(jd); diff --git a/movement/watch_faces/complication/planetary_hours_face.c b/movement/watch_faces/complication/planetary_hours_face.c index acded91..d9e32c5 100644 --- a/movement/watch_faces/complication/planetary_hours_face.c +++ b/movement/watch_faces/complication/planetary_hours_face.c @@ -134,7 +134,8 @@ static void _planetary_solar_phases(movement_settings_t *settings, planetary_hou state->no_location = false; watch_date_time date_time = watch_rtc_get_date_time(); // the current local date / time - watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60, 0); // the current date / time in UTC + int16_t tz = get_timezone_offset(settings->bit.time_zone, date_time); + watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, tz * 60, 0); // the current date / time in UTC watch_date_time scratch_time; // scratchpad, contains different values at different times watch_date_time midnight; scratch_time.reg = midnight.reg = utc_now.reg; @@ -147,7 +148,7 @@ static void _planetary_solar_phases(movement_settings_t *settings, planetary_hou double lon = (double)lon_centi / 100.0; // save UTC offset - state->utc_offset = ((double)movement_timezone_offsets[settings->bit.time_zone]) / 60.0; + state->utc_offset = ((double)tz) / 60.0; // calculate sunrise and sunset of current day in decimal hours after midnight sun_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &sunrise, &sunset); @@ -237,7 +238,7 @@ static void _planetary_hours(movement_settings_t *settings, planetary_hours_stat // get current time watch_date_time date_time = watch_rtc_get_date_time(); // the current local date / time - watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60, 0); // the current date / time in UTC + watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, get_timezone_offset(settings->bit.time_zone, date_time) * 60, 0); // the current date / time in UTC current_hour_epoch = watch_utility_date_time_to_unix_time(utc_now, 0); // set the current planetary hour as default screen diff --git a/movement/watch_faces/complication/planetary_time_face.c b/movement/watch_faces/complication/planetary_time_face.c index 56a18cf..836ada6 100644 --- a/movement/watch_faces/complication/planetary_time_face.c +++ b/movement/watch_faces/complication/planetary_time_face.c @@ -129,7 +129,8 @@ static void _planetary_solar_phase(movement_settings_t *settings, planetary_time state->no_location = false; watch_date_time date_time = watch_rtc_get_date_time(); // the current local date / time - watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60, 0); // the current date / time in UTC + int16_t tz = get_timezone_offset(settings->bit.time_zone, date_time); + watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, tz * 60, 0); // the current date / time in UTC watch_date_time scratch_time; // scratchpad, contains different values at different times watch_date_time midnight; scratch_time.reg = midnight.reg = utc_now.reg; @@ -142,7 +143,7 @@ static void _planetary_solar_phase(movement_settings_t *settings, planetary_time double lon = (double)lon_centi / 100.0; // save UTC offset - state->utc_offset = ((double)movement_timezone_offsets[settings->bit.time_zone]) / 60.0; + state->utc_offset = ((double)tz) / 60.0; // get UNIX epoch time now_epoch = watch_utility_date_time_to_unix_time(utc_now, 0); @@ -206,11 +207,12 @@ static void _planetary_time(movement_event_t event, movement_settings_t *setting double night_hour_count = 0.0; uint8_t weekday, planet, planetary_hour; double hour_duration, current_hour, current_minute, current_second; + watch_date_time date_time = watch_rtc_get_date_time(); watch_set_colon(); // get current time and convert to UTC - state->scratch = watch_utility_date_time_convert_zone(watch_rtc_get_date_time(), movement_timezone_offsets[settings->bit.time_zone] * 60, 0); + state->scratch = watch_utility_date_time_convert_zone(date_time, get_timezone_offset(settings->bit.time_zone, date_time) * 60, 0); // when current phase ends calculate the next phase if ( watch_utility_date_time_to_unix_time(state->scratch, 0) >= state->phase_end ) { diff --git a/movement/watch_faces/complication/sailing_face.c b/movement/watch_faces/complication/sailing_face.c index a6c13fe..16d60c9 100644 --- a/movement/watch_faces/complication/sailing_face.c +++ b/movement/watch_faces/complication/sailing_face.c @@ -33,8 +33,8 @@ #define sl_SELECTIONS 6 #define DEFAULT_MINUTES { 5,4,1,0,0,0 } -static inline int32_t get_tz_offset(movement_settings_t *settings) { - return movement_timezone_offsets[settings->bit.time_zone] * 60; +static inline int32_t get_tz_offset(movement_settings_t *settings, watch_date_time date_time) { + return get_timezone_offset(settings->bit.time_zone, date_time) * 60; } static int lap = 0; @@ -165,7 +165,8 @@ static void ring(sailing_state_t *state, movement_settings_t *settings) { return; } state->nextbeep_ts = state->target_ts - beepseconds[beepflag+1]; - watch_date_time target_dt = watch_utility_date_time_from_unix_time(state->nextbeep_ts, get_tz_offset(settings)); + watch_date_time now = watch_rtc_get_date_time(); + watch_date_time target_dt = watch_utility_date_time_from_unix_time(state->nextbeep_ts, get_tz_offset(settings, now)); movement_schedule_background_task_for_face(state->watch_face_index, target_dt); //background task is set, now we have time to play the tune. If this is cancelled accidentally, the next alarm will still ring. Sound is implemented non-blocking, so that neither buttons nor display output are compromised. for (int i = 0; i < 5; i++) { @@ -194,7 +195,7 @@ static void start(sailing_state_t *state, movement_settings_t *settings) {//gets } if (state->index > 5 || state->minutes[state->index] == 0) { watch_date_time now = watch_rtc_get_date_time(); - state->now_ts = watch_utility_date_time_to_unix_time(now, get_tz_offset(settings)); + state->now_ts = watch_utility_date_time_to_unix_time(now, get_tz_offset(settings, now)); state->target_ts = state->now_ts; if (alarmflag != 0){ watch_buzzer_play_sequence(long_beep, NULL); @@ -205,7 +206,7 @@ static void start(sailing_state_t *state, movement_settings_t *settings) {//gets movement_request_tick_frequency(1); //synchronises tick with the moment the button was pressed. Solves 1s offset between sound and display, solves up to +-0.5s offset between button action and display. state->mode = sl_running; watch_date_time now = watch_rtc_get_date_time(); - state->now_ts = watch_utility_date_time_to_unix_time(now, get_tz_offset(settings)); + state->now_ts = watch_utility_date_time_to_unix_time(now, get_tz_offset(settings, now)); state->target_ts = watch_utility_offset_timestamp(state->now_ts, 0, state->minutes[state->index], 0); ring(state, settings); } @@ -253,11 +254,11 @@ void sailing_face_activate(movement_settings_t *settings, void *context) { sailing_state_t *state = (sailing_state_t *)context; if(state->mode == sl_running) { watch_date_time now = watch_rtc_get_date_time(); - state->now_ts = watch_utility_date_time_to_unix_time(now, get_tz_offset(settings)); + state->now_ts = watch_utility_date_time_to_unix_time(now, get_tz_offset(settings, now)); } if(state->mode == sl_counting) { watch_date_time now = watch_rtc_get_date_time(); - state->now_ts = watch_utility_date_time_to_unix_time(now, get_tz_offset(settings)); + state->now_ts = watch_utility_date_time_to_unix_time(now, get_tz_offset(settings, now)); watch_set_indicator(WATCH_INDICATOR_LAP); } switch (alarmflag) { diff --git a/movement/watch_faces/complication/solstice_face.c b/movement/watch_faces/complication/solstice_face.c index e74f878..76d0d26 100644 --- a/movement/watch_faces/complication/solstice_face.c +++ b/movement/watch_faces/complication/solstice_face.c @@ -123,9 +123,10 @@ static watch_date_time jde_to_date_time(double JDE) { } static void calculate_datetimes(solstice_state_t *state, movement_settings_t *settings) { + watch_date_time date_time = watch_rtc_get_date_time(); for (int i = 0; i < 4; i++) { // TODO: handle DST changes - state->datetimes[i] = jde_to_date_time(calculate_solstice_equinox(2020 + state->year, i) + (movement_timezone_offsets[settings->bit.time_zone] / (60.0*24.0))); + state->datetimes[i] = jde_to_date_time(calculate_solstice_equinox(2020 + state->year, i) + (get_timezone_offset(settings->bit.time_zone, date_time) / (60.0*24.0))); } } diff --git a/movement/watch_faces/complication/sunrise_sunset_face.c b/movement/watch_faces/complication/sunrise_sunset_face.c index 7330c42..a6ec764 100644 --- a/movement/watch_faces/complication/sunrise_sunset_face.c +++ b/movement/watch_faces/complication/sunrise_sunset_face.c @@ -54,7 +54,8 @@ static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_s } watch_date_time date_time = watch_rtc_get_date_time(); // the current local date / time - watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60, 0); // the current date / time in UTC + int16_t tz = get_timezone_offset(settings->bit.time_zone, date_time); + watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, tz * 60, 0); // the current date / time in UTC watch_date_time scratch_time; // scratchpad, contains different values at different times scratch_time.reg = utc_now.reg; @@ -69,7 +70,7 @@ static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_s // sunriset returns the rise/set times as signed decimal hours in UTC. // this can mean hours below 0 or above 31, which won't fit into a watch_date_time struct. // to deal with this, we set aside the offset in hours, and add it back before converting it to a watch_date_time. - double hours_from_utc = ((double)movement_timezone_offsets[settings->bit.time_zone]) / 60.0; + double hours_from_utc = ((double)tz) / 60.0; // we loop twice because if it's after sunset today, we need to recalculate to display values for tomorrow. for(int i = 0; i < 2; i++) { diff --git a/movement/watch_faces/complication/timer_face.c b/movement/watch_faces/complication/timer_face.c index 29392d6..5ee2967 100644 --- a/movement/watch_faces/complication/timer_face.c +++ b/movement/watch_faces/complication/timer_face.c @@ -36,8 +36,8 @@ static const int8_t _sound_seq_start[] = {BUZZER_NOTE_C8, 2, 0}; static uint8_t _beeps_to_play; // temporary counter for ring signals playing -static inline int32_t _get_tz_offset(movement_settings_t *settings) { - return movement_timezone_offsets[settings->bit.time_zone] * 60; +static inline int32_t _get_tz_offset(movement_settings_t *settings, watch_date_time date_time) { + return get_timezone_offset(settings->bit.time_zone, date_time) * 60; } static void _signal_callback() { @@ -50,7 +50,8 @@ static void _signal_callback() { static void _start(timer_state_t *state, movement_settings_t *settings, bool with_beep) { if (state->timers[state->current_timer].value == 0) return; watch_date_time now = watch_rtc_get_date_time(); - state->now_ts = watch_utility_date_time_to_unix_time(now, _get_tz_offset(settings)); + int32_t tz = _get_tz_offset(settings, now); + state->now_ts = watch_utility_date_time_to_unix_time(now, tz); if (state->mode == pausing) state->target_ts = state->now_ts + state->paused_left; else @@ -58,7 +59,7 @@ static void _start(timer_state_t *state, movement_settings_t *settings, bool wit state->timers[state->current_timer].unit.hours, state->timers[state->current_timer].unit.minutes, state->timers[state->current_timer].unit.seconds); - watch_date_time target_dt = watch_utility_date_time_from_unix_time(state->target_ts, _get_tz_offset(settings)); + watch_date_time target_dt = watch_utility_date_time_from_unix_time(state->target_ts, tz); state->mode = running; movement_schedule_background_task_for_face(state->watch_face_index, target_dt); watch_set_indicator(WATCH_INDICATOR_BELL); @@ -210,7 +211,7 @@ void timer_face_activate(movement_settings_t *settings, void *context) { watch_set_colon(); if(state->mode == running) { watch_date_time now = watch_rtc_get_date_time(); - state->now_ts = watch_utility_date_time_to_unix_time(now, _get_tz_offset(settings)); + state->now_ts = watch_utility_date_time_to_unix_time(now, _get_tz_offset(settings, now)); watch_set_indicator(WATCH_INDICATOR_BELL); } else { state->pausing_seconds = 1; diff --git a/movement/watch_faces/complication/tomato_face.c b/movement/watch_faces/complication/tomato_face.c index 3d46ba9..15b67c6 100644 --- a/movement/watch_faces/complication/tomato_face.c +++ b/movement/watch_faces/complication/tomato_face.c @@ -30,8 +30,8 @@ static uint8_t focus_min = 25; static uint8_t break_min = 5; -static inline int32_t get_tz_offset(movement_settings_t *settings) { - return movement_timezone_offsets[settings->bit.time_zone] * 60; +static inline int32_t get_tz_offset(movement_settings_t *settings, watch_date_time date_time) { + return get_timezone_offset(settings->bit.time_zone, date_time) * 60; } static uint8_t get_length(tomato_state_t *state) { @@ -47,12 +47,13 @@ static uint8_t get_length(tomato_state_t *state) { static void tomato_start(tomato_state_t *state, movement_settings_t *settings) { watch_date_time now = watch_rtc_get_date_time(); + int32_t tz = get_tz_offset(settings, now); int8_t length = (int8_t) get_length(state); state->mode = tomato_run; - state->now_ts = watch_utility_date_time_to_unix_time(now, get_tz_offset(settings)); + state->now_ts = watch_utility_date_time_to_unix_time(now, tz); state->target_ts = watch_utility_offset_timestamp(state->now_ts, 0, length, 0); - watch_date_time target_dt = watch_utility_date_time_from_unix_time(state->target_ts, get_tz_offset(settings)); + watch_date_time target_dt = watch_utility_date_time_from_unix_time(state->target_ts, tz); movement_schedule_background_task(target_dt); watch_set_indicator(WATCH_INDICATOR_BELL); } @@ -126,7 +127,7 @@ void tomato_face_activate(movement_settings_t *settings, void *context) { tomato_state_t *state = (tomato_state_t *)context; if (state->mode == tomato_run) { watch_date_time now = watch_rtc_get_date_time(); - state->now_ts = watch_utility_date_time_to_unix_time(now, get_tz_offset(settings)); + state->now_ts = watch_utility_date_time_to_unix_time(now, get_tz_offset(settings, now)); watch_set_indicator(WATCH_INDICATOR_BELL); } watch_set_colon(); diff --git a/movement/watch_faces/complication/totp_face.c b/movement/watch_faces/complication/totp_face.c index a593e9c..10a5bfc 100644 --- a/movement/watch_faces/complication/totp_face.c +++ b/movement/watch_faces/complication/totp_face.c @@ -157,8 +157,9 @@ static void totp_generate_and_display(totp_state_t *totp_state) { totp_display(totp_state); } -static inline uint32_t totp_compute_base_timestamp(movement_settings_t *settings) { - return watch_utility_date_time_to_unix_time(watch_rtc_get_date_time(), movement_timezone_offsets[settings->bit.time_zone] * 60); +static uint32_t totp_compute_base_timestamp(movement_settings_t *settings) { + watch_date_time date_time = watch_rtc_get_date_time(); + return watch_utility_date_time_to_unix_time(date_time, get_timezone_offset(settings->bit.time_zone, date_time) * 60); } void totp_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) { diff --git a/movement/watch_faces/complication/totp_face_lfs.c b/movement/watch_faces/complication/totp_face_lfs.c index 820ad52..f560627 100644 --- a/movement/watch_faces/complication/totp_face_lfs.c +++ b/movement/watch_faces/complication/totp_face_lfs.c @@ -210,7 +210,8 @@ void totp_face_lfs_activate(movement_settings_t *settings, void *context) { } #endif - totp_state->timestamp = watch_utility_date_time_to_unix_time(watch_rtc_get_date_time(), movement_timezone_offsets[settings->bit.time_zone] * 60); + watch_date_time date_time = watch_rtc_get_date_time(); + totp_state->timestamp = watch_utility_date_time_to_unix_time(date_time, get_timezone_offset(settings->bit.time_zone, date_time) * 60); totp_face_set_record(totp_state, 0); } diff --git a/movement/watch_faces/sensor/accelerometer_data_acquisition_face.c b/movement/watch_faces/sensor/accelerometer_data_acquisition_face.c index 6d174d5..9cadf67 100644 --- a/movement/watch_faces/sensor/accelerometer_data_acquisition_face.c +++ b/movement/watch_faces/sensor/accelerometer_data_acquisition_face.c @@ -442,7 +442,7 @@ static void start_reading(accelerometer_data_acquisition_state_t *state, movemen accelerometer_data_acquisition_record_t record; watch_date_time date_time = watch_rtc_get_date_time(); - state->starting_timestamp = watch_utility_date_time_to_unix_time(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60); + state->starting_timestamp = watch_utility_date_time_to_unix_time(date_time, get_timezone_offset(settings->bit.time_zone, date_time) * 60); record.header.info.record_type = ACCELEROMETER_DATA_ACQUISITION_HEADER; record.header.info.range = ACCELEROMETER_RANGE; record.header.info.temperature = lis2dw_get_temperature(); diff --git a/movement/watch_faces/settings/set_time_hackwatch_face.c b/movement/watch_faces/settings/set_time_hackwatch_face.c index fbe8cbb..bdd1b0a 100644 --- a/movement/watch_faces/settings/set_time_hackwatch_face.c +++ b/movement/watch_faces/settings/set_time_hackwatch_face.c @@ -232,12 +232,13 @@ bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *s watch_clear_colon(); sprintf(buf, "%s ", set_time_hackwatch_face_titles[current_page]); } else { + int16_t tz = get_timezone_offset(settings->bit.time_zone, date_time_settings); watch_set_colon(); sprintf(buf, "%s %3d%02d ", set_time_hackwatch_face_titles[current_page], - (int8_t)(movement_timezone_offsets[settings->bit.time_zone] / 60), - (int8_t)(movement_timezone_offsets[settings->bit.time_zone] % 60) * (movement_timezone_offsets[settings->bit.time_zone] < 0 ? -1 : 1)); + (int8_t)(tz / 60), + (int8_t)(tz % 60) * (tz < 0 ? -1 : 1)); } } From bae8c6582559e2617ceae22ed34f7d0be8e10a9f Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Fri, 2 Aug 2024 07:37:30 -0400 Subject: [PATCH 04/11] Made the faces I care about not need to continuously re-find the timezone --- movement/watch_faces/clock/world_clock2_face.c | 9 ++++----- movement/watch_faces/clock/world_clock2_face.h | 1 + movement/watch_faces/clock/world_clock_face.c | 15 +++++---------- movement/watch_faces/clock/world_clock_face.h | 1 + .../watch_faces/complication/moon_phase_face.c | 1 + .../complication/sunrise_sunset_face.c | 6 +++--- .../complication/sunrise_sunset_face.h | 1 + 7 files changed, 16 insertions(+), 18 deletions(-) diff --git a/movement/watch_faces/clock/world_clock2_face.c b/movement/watch_faces/clock/world_clock2_face.c index 6ff806b..cf37a40 100644 --- a/movement/watch_faces/clock/world_clock2_face.c +++ b/movement/watch_faces/clock/world_clock2_face.c @@ -154,6 +154,7 @@ void world_clock2_face_activate(movement_settings_t *settings, void *context) movement_request_tick_frequency(4); break; } + state->tz = get_timezone_offset(settings->bit.time_zone, watch_rtc_get_date_time()); refresh_face = true; } @@ -165,7 +166,6 @@ static bool mode_display(movement_event_t event, movement_settings_t *settings, uint32_t timestamp; uint32_t previous_date_time; watch_date_time date_time; - int16_t tz; switch (event.event_type) { case EVENT_ACTIVATE: @@ -184,9 +184,8 @@ static bool mode_display(movement_event_t event, movement_settings_t *settings, /* Determine current time at time zone and store date/time */ date_time = watch_rtc_get_date_time(); - tz = get_timezone_offset(settings->bit.time_zone, date_time); - timestamp = watch_utility_date_time_to_unix_time(date_time, tz * 60); - date_time = watch_utility_date_time_from_unix_time(timestamp, tz * 60); + timestamp = watch_utility_date_time_to_unix_time(date_time, state->tz * 60); + date_time = watch_utility_date_time_from_unix_time(timestamp, state->tz * 60); previous_date_time = state->previous_date_time; state->previous_date_time = date_time.reg; @@ -286,7 +285,7 @@ static bool mode_settings(movement_event_t event, movement_settings_t *settings, watch_clear_indicator(WATCH_INDICATOR_PM); refresh_face = false; } - result = div(get_timezone_offset(state->current_zone, watch_rtc_get_date_time()), 60); + result = div(state->tz, 60); hours = result.quot; minutes = result.rem; diff --git a/movement/watch_faces/clock/world_clock2_face.h b/movement/watch_faces/clock/world_clock2_face.h index 0baac21..efc107e 100644 --- a/movement/watch_faces/clock/world_clock2_face.h +++ b/movement/watch_faces/clock/world_clock2_face.h @@ -104,6 +104,7 @@ typedef struct { world_clock2_mode_t current_mode; uint8_t current_zone; uint32_t previous_date_time; + int16_t tz; } world_clock2_state_t; void world_clock2_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void **context_ptr); diff --git a/movement/watch_faces/clock/world_clock_face.c b/movement/watch_faces/clock/world_clock_face.c index c34db92..e7f393e 100644 --- a/movement/watch_faces/clock/world_clock_face.c +++ b/movement/watch_faces/clock/world_clock_face.c @@ -54,13 +54,13 @@ void world_clock_face_activate(movement_settings_t *settings, void *context) { static bool world_clock_face_do_display_mode(movement_event_t event, movement_settings_t *settings, world_clock_state_t *state) { char buf[11]; uint8_t pos; - int16_t tz; uint32_t timestamp; uint32_t previous_date_time; watch_date_time date_time; switch (event.event_type) { case EVENT_ACTIVATE: + state->tz = get_timezone_offset(settings->bit.time_zone, watch_rtc_get_date_time()); if (settings->bit.clock_mode_24h) watch_set_indicator(WATCH_INDICATOR_24H); watch_set_colon(); state->previous_date_time = 0xFFFFFFFF; @@ -68,9 +68,8 @@ static bool world_clock_face_do_display_mode(movement_event_t event, movement_se case EVENT_TICK: case EVENT_LOW_ENERGY_UPDATE: date_time = watch_rtc_get_date_time(); - tz = get_timezone_offset(settings->bit.time_zone, date_time); - timestamp = watch_utility_date_time_to_unix_time(date_time, tz * 60); - date_time = watch_utility_date_time_from_unix_time(timestamp, tz * 60); + timestamp = watch_utility_date_time_to_unix_time(date_time, state->tz * 60); + date_time = watch_utility_date_time_from_unix_time(timestamp, state->tz * 60); previous_date_time = state->previous_date_time; state->previous_date_time = date_time.reg; @@ -127,8 +126,6 @@ static bool world_clock_face_do_display_mode(movement_event_t event, movement_se } static bool _world_clock_face_do_settings_mode(movement_event_t event, movement_settings_t *settings, world_clock_state_t *state) { - watch_date_time date_time; - int16_t tz; switch (event.event_type) { case EVENT_MODE_BUTTON_UP: if (state->backup_register) watch_store_backup_data(state->settings.reg, state->backup_register); @@ -172,13 +169,11 @@ static bool _world_clock_face_do_settings_mode(movement_event_t event, movement_ } char buf[13]; - date_time = watch_rtc_get_date_time(); - tz = get_timezone_offset(settings->bit.time_zone, date_time); sprintf(buf, "%c%c %3d%02d ", movement_valid_position_0_chars[state->settings.bit.char_0], movement_valid_position_1_chars[state->settings.bit.char_1], - (int8_t) (tz / 60), - (int8_t) (tz % 60) * (tz < 0 ? -1 : 1)); + (int8_t) (state->tz / 60), + (int8_t) (state->tz % 60) * (state->tz < 0 ? -1 : 1)); watch_set_colon(); watch_clear_indicator(WATCH_INDICATOR_PM); diff --git a/movement/watch_faces/clock/world_clock_face.h b/movement/watch_faces/clock/world_clock_face.h index 92e91a6..e76d85e 100644 --- a/movement/watch_faces/clock/world_clock_face.h +++ b/movement/watch_faces/clock/world_clock_face.h @@ -62,6 +62,7 @@ typedef struct { uint8_t backup_register; uint8_t current_screen; uint32_t previous_date_time; + int16_t tz; } world_clock_state_t; void world_clock_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); diff --git a/movement/watch_faces/complication/moon_phase_face.c b/movement/watch_faces/complication/moon_phase_face.c index 47ed6e6..c571843 100644 --- a/movement/watch_faces/complication/moon_phase_face.c +++ b/movement/watch_faces/complication/moon_phase_face.c @@ -139,6 +139,7 @@ bool moon_phase_face_loop(movement_event_t event, movement_settings_t *settings, switch (event.event_type) { case EVENT_ACTIVATE: + _update(settings, state, state->offset); break; case EVENT_TICK: diff --git a/movement/watch_faces/complication/sunrise_sunset_face.c b/movement/watch_faces/complication/sunrise_sunset_face.c index a6ec764..ad03d88 100644 --- a/movement/watch_faces/complication/sunrise_sunset_face.c +++ b/movement/watch_faces/complication/sunrise_sunset_face.c @@ -54,8 +54,7 @@ static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_s } watch_date_time date_time = watch_rtc_get_date_time(); // the current local date / time - int16_t tz = get_timezone_offset(settings->bit.time_zone, date_time); - watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, tz * 60, 0); // the current date / time in UTC + watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, state->tz * 60, 0); // the current date / time in UTC watch_date_time scratch_time; // scratchpad, contains different values at different times scratch_time.reg = utc_now.reg; @@ -70,7 +69,7 @@ static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_s // sunriset returns the rise/set times as signed decimal hours in UTC. // this can mean hours below 0 or above 31, which won't fit into a watch_date_time struct. // to deal with this, we set aside the offset in hours, and add it back before converting it to a watch_date_time. - double hours_from_utc = ((double)tz) / 60.0; + double hours_from_utc = ((double)state->tz) / 60.0; // we loop twice because if it's after sunset today, we need to recalculate to display values for tomorrow. for(int i = 0; i < 2; i++) { @@ -317,6 +316,7 @@ void sunrise_sunset_face_activate(movement_settings_t *settings, void *context) movement_location_t movement_location = (movement_location_t) watch_get_backup_data(1); state->working_latitude = _sunrise_sunset_face_struct_from_latlon(movement_location.bit.latitude); state->working_longitude = _sunrise_sunset_face_struct_from_latlon(movement_location.bit.longitude); + state->tz = get_timezone_offset(settings->bit.time_zone, watch_rtc_get_date_time()); } bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { diff --git a/movement/watch_faces/complication/sunrise_sunset_face.h b/movement/watch_faces/complication/sunrise_sunset_face.h index 16e65b7..71b8462 100644 --- a/movement/watch_faces/complication/sunrise_sunset_face.h +++ b/movement/watch_faces/complication/sunrise_sunset_face.h @@ -52,6 +52,7 @@ typedef struct { uint8_t rise_index; uint8_t active_digit; bool location_changed; + int16_t tz; watch_date_time rise_set_expires; sunrise_sunset_lat_lon_settings_t working_latitude; sunrise_sunset_lat_lon_settings_t working_longitude; From fa2907e098ceccc249e864aad864140208bb4215 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Fri, 2 Aug 2024 17:57:29 -0400 Subject: [PATCH 05/11] Some more cleanup --- movement/movement.c | 111 +++++++++--------- movement/movement.h | 2 +- movement/movement_config.h | 7 ++ movement/watch_faces/settings/set_time_face.c | 9 +- watch-library/shared/watch/watch_utility.h | 9 +- 5 files changed, 76 insertions(+), 62 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 52a9ac0..4afe273 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -96,6 +96,11 @@ #define MOVEMENT_DEFAULT_LED_DURATION 1 #endif +// Default to having DST get set +#ifndef MOVEMENT_DEFAULT_DST_ACTIVE +#define MOVEMENT_DEFAULT_DST_ACTIVE true +#endif + #if __EMSCRIPTEN__ #include #endif @@ -107,7 +112,8 @@ const int32_t movement_le_inactivity_deadlines[8] = {INT_MAX, 600, 3600, 7200, 2 const int16_t movement_timeout_inactivity_deadlines[4] = {60, 120, 300, 1800}; movement_event_t event; -const int16_t movement_timezone_offsets[] = { +#define NUM_TIME_ZONES 41 +const int16_t movement_timezone_offsets[NUM_TIME_ZONES] = { 0, // 0 : 0:00:00 (UTC) 60, // 1 : 1:00:00 (Central European Time) 120, // 2 : 2:00:00 (South African Standard Time) @@ -164,47 +170,47 @@ const int16_t movement_timezone_offsets[] = { * having to separately change the hour and timezone info * in the time set face. */ -const uint8_t movement_dst_jump_table[] = { - 1, // 0 UTC + 1 = CET - 2, // 1 CET + 1 = SAST - 3, // 2 SAST + 1 = AST - 5, // 3 AST + 1 = GST - 6, // 4 IST + 1 = AT - 7, // 5 GST + 1 = PST - 8, // 6 AT + 1 = IST - 10, // 7 PST + 1 = KT - 11, // 8 IST + 1 = MT - 9, // 9 Nepal has no equivalent DST timezone, but they don't observe DST anyway - 12, // 10 KT + 1 = TST - 11, // 11 Myanmar has no equivalent DST timezone, but they don't observe DST anyway - 13, // 12 TST + 1 = CST - 15, // 13 CST + 1 = JST - 14, // 14 ACWST has no equivalent DST timezone, but they don't observe DST anyway - 17, // 15 JST + 1 = AEST - 18, // 16 ACST + 1 = LHST - 19, // 17 AEST + 1 = SIT - 18, // 18 LHST has no equivalent DST timezone, but they don't observe DST anyway - 20, // 19 SIT + 1 = NZST - 22, // 20 NZST + 1 = TT - 23, // 21 CST + 1 = CDT - 24, // 22 TT + 1 = LIT - 23, // 23 CDT is already a daylight timezone - 24, // 24 LIT has no equivalent DST timezone, but they don't observe DST anyway - 26, // 25 BIT + 1 = NT - 27, // 26 NT + 1 = HAST - 29, // 27 HAST + 1 = AST - 28, // 28 MIT has no equivalent DST timezone, but they don't observe DST anyway - 30, // 29 AST + 1 = PST - 31, // 30 PST + 1 = MST - 32, // 31 MST + 1 = CST - 33, // 32 CST + 1 = EST - 35, // 33 EST + 1 = AST - 36, // 34 VST + 1 = NST - 37, // 35 AST + 1 = BT - 38, // 36 NST + 1 = NDT - 39, // 37 BT + 1 = 39 - 38, // 38 NDT is already a daylight timezone - 40, // 39 FNT + 1 = AST +const int16_t movement_timezone_dst_offsets[NUM_TIME_ZONES] = { + 60, // 0 UTC + 1 = CET + 120, // 1 CET + 1 = SAST + 189, // 2 SAST + 1 = AST + 240, // 3 AST + 1 = GST + 270, // 4 IST + 1 = AT + 300, // 5 GST + 1 = PST + 330, // 6 AT + 1 = IST + 360, // 7 PST + 1 = KT + 390, // 8 IST + 1 = MT + 345, // 9 Nepal has no equivalent DST timezone, but they don't observe DST anyway + 420, // 10 KT + 1 = TST + 390, // 11 Myanmar has no equivalent DST timezone, but they don't observe DST anyway + 480, // 12 TST + 1 = CST + 540, // 13 CST + 1 = JST + 525, // 14 ACWST has no equivalent DST timezone, but they don't observe DST anyway + 600, // 15 JST + 1 = AEST + 630, // 16 ACST + 1 = LHST + 660, // 17 AEST + 1 = SIT + 630, // 18 LHST has no equivalent DST timezone, but they don't observe DST anyway + 720, // 19 SIT + 1 = NZST + 780, // 20 NZST + 1 = TT + 825, // 21 CST + 1 = CDT + 840, // 22 TT + 1 = LIT + 825, // 23 CDT is already a daylight timezone + 840, // 24 LIT has no equivalent DST timezone, but they don't observe DST anyway + -660, // 25 BIT + 1 = NT + -600, // 26 NT + 1 = HAST + -540, // 27 HAST + 1 = AST + -570, // 28 MIT has no equivalent DST timezone, but they don't observe DST anyway + -480, // 29 AST + 1 = PST + -420, // 30 PST + 1 = MST + -360, // 31 MST + 1 = CST + -300, // 32 CST + 1 = EST + -240, // 33 EST + 1 = AST + -210, // 34 VST + 1 = NST + -180, // 35 AST + 1 = BT + -150, // 36 NST + 1 = NDT + -120, // 37 BT + 1 = 39 + -150, // 38 NDT is already a daylight timezone + -60, // 39 FNT + 1 = AST 0 // 40 AST + 1 = UTC }; @@ -426,20 +432,13 @@ uint8_t movement_claim_backup_register(void) { int16_t get_timezone_offset(uint8_t timezone_idx, watch_date_time date_time) { if (!movement_state.settings.bit.dst_active) return movement_timezone_offsets[timezone_idx]; - uint8_t dst_result = is_dst(date_time); - switch (dst_result) - { - case DST_STARTED: - case DST_OCCURRING: - return movement_timezone_offsets[movement_dst_jump_table[timezone_idx]]; - case DST_ENDING: - case DST_ENDED: - default: - return movement_timezone_offsets[timezone_idx]; - } + if (dst_occurring(date_time)) + return movement_timezone_dst_offsets[timezone_idx]; + return movement_timezone_offsets[timezone_idx]; } void app_init(void) { + const int16_t* timezone_offsets; #if defined(NO_FREQCORR) watch_rtc_freqcorr_write(0, 0); #elif defined(WATCH_IS_BLUE_BOARD) @@ -457,6 +456,7 @@ 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.settings.bit.dst_active = MOVEMENT_DEFAULT_DST_ACTIVE; movement_state.light_ticks = -1; movement_state.alarm_ticks = -1; movement_state.next_available_backup_register = 4; @@ -468,8 +468,9 @@ void app_init(void) { int32_t time_zone_offset = EM_ASM_INT({ return -new Date().getTimezoneOffset(); }); - for (int i = 0, count = sizeof(movement_timezone_offsets) / sizeof(movement_timezone_offsets[0]); i < count; i++) { - if (movement_timezone_offsets[i] == time_zone_offset) { + timezone_offsets = dst_occurring(watch_rtc_get_date_time()) ? movement_timezone_dst_offsets : movement_timezone_offsets; + for (int i = 0; i < NUM_TIME_ZONES; i++) { + if (timezone_offsets[i] == time_zone_offset) { movement_state.settings.bit.time_zone = i; break; } diff --git a/movement/movement.h b/movement/movement.h index 9aa1dbc..d0595fb 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -129,7 +129,7 @@ typedef struct { } movement_event_t; extern const int16_t movement_timezone_offsets[]; -extern const uint8_t movement_dst_jump_table[]; +extern const int16_t movement_timezone_dst_offsets[]; extern const char movement_valid_position_0_chars[]; extern const char movement_valid_position_1_chars[]; diff --git a/movement/movement_config.h b/movement/movement_config.h index 10a30af..46e1d2e 100644 --- a/movement/movement_config.h +++ b/movement/movement_config.h @@ -95,4 +95,11 @@ const watch_face_t watch_faces[] = { */ #define MOVEMENT_DEFAULT_LED_DURATION 1 +/* Set if using DST + * Valid values are: + * false: Don't allow the watch to use DST + * true: Allow the watch to use DST + */ +#define MOVEMENT_DEFAULT_DST_ACTIVE true + #endif // MOVEMENT_CONFIG_H_ diff --git a/movement/watch_faces/settings/set_time_face.c b/movement/watch_faces/settings/set_time_face.c index 90edac2..b16cb6d 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 (8) const char set_time_face_titles[SET_TIME_FACE_NUM_SETTINGS][3] = {"HR", "M1", "SE", "YR", "MO", "DA", "ZO", "DS"}; @@ -150,18 +151,18 @@ bool set_time_face_loop(movement_event_t event, movement_settings_t *settings, v watch_clear_indicator(WATCH_INDICATOR_PM); sprintf(buf, "%s %2d%02d%02d", set_time_face_titles[current_page], date_time.unit.year + 20, date_time.unit.month, date_time.unit.day); } else if (current_page < 7) { // zone + char dst_char = (settings->bit.dst_active && dst_occurring(watch_rtc_get_date_time())) ? 'd' : ' '; if (event.subsecond % 2) { watch_clear_colon(); - sprintf(buf, "%s ", set_time_face_titles[current_page]); + sprintf(buf, "%s %c", set_time_face_titles[current_page], dst_char); } else { int16_t tz = get_timezone_offset(settings->bit.time_zone, date_time); watch_set_colon(); - sprintf(buf, "%s %3d%02d ", set_time_face_titles[current_page], (int8_t) (tz / 60), (int8_t) (tz % 60) * (tz < 0 ? -1 : 1)); + sprintf(buf, "%s %3d%02d %c", set_time_face_titles[current_page], (int8_t) (tz / 60), (int8_t) (tz % 60) * (tz < 0 ? -1 : 1), dst_char); } } else { // daylight savings watch_clear_colon(); - if (settings->bit.dst_active) sprintf(buf, "%s dsT y", set_time_face_titles[current_page]); - else sprintf(buf, "%s dsT n", set_time_face_titles[current_page]); + sprintf(buf, "%s dsT %c", set_time_face_titles[current_page], settings->bit.dst_active ? 'y' : 'n'); } // blink up the parameter we're setting diff --git a/watch-library/shared/watch/watch_utility.h b/watch-library/shared/watch/watch_utility.h index d3f3981..bdc2a88 100644 --- a/watch-library/shared/watch/watch_utility.h +++ b/watch-library/shared/watch/watch_utility.h @@ -46,7 +46,7 @@ typedef struct { } watch_duration_t; typedef enum { - DST_STARTED, + DST_STARTING, DST_OCCURRING, DST_ENDING, DST_ENDED @@ -89,7 +89,12 @@ uint8_t is_leap(uint16_t year); * @param date_time The watch_date_time that you wish to convert. * @return DST_OCCURRING, DST_HAPPENING, DST_ENDING, DST_ENDED */ -uint8_t is_dst(watch_date_time date_time); +uint8_t get_dst_status(watch_date_time date_time); + +/** @brief Returns true if it's DST and false otherwise. + * @param date_time The watch_date_time that you wish to convert. + */ +bool dst_occurring(watch_date_time date_time); /** @brief Returns the UNIX time (seconds since 1970) for a given date/time in UTC. * @param date_time The watch_date_time that you wish to convert. From 74421c7e65f9a735bcc394eed027b59baef1cb97 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 3 Aug 2024 08:46:34 -0400 Subject: [PATCH 06/11] Day roll back repeat fix --- movement/watch_faces/clock/clock_face.c | 32 +++++++++-------- .../watch_faces/clock/simple_clock_face.c | 34 +++++++++++-------- movement/watch_faces/settings/set_time_face.c | 1 + .../settings/set_time_hackwatch_face.c | 9 +++-- watch-library/shared/watch/watch_utility.c | 21 +++++++----- 5 files changed, 58 insertions(+), 39 deletions(-) diff --git a/movement/watch_faces/clock/clock_face.c b/movement/watch_faces/clock/clock_face.c index 68019d8..f9ec58a 100644 --- a/movement/watch_faces/clock/clock_face.c +++ b/movement/watch_faces/clock/clock_face.c @@ -280,27 +280,31 @@ void clock_face_resign(movement_settings_t *settings, void *context) { (void) context; } -static void check_and_act_on_daylight_savings(bool dst_active, watch_date_time date_time) { - if (!dst_active) return; - uint8_t dst_result = is_dst(date_time); - switch (dst_result) - { - case DST_STARTED: - date_time.unit.hour = (date_time.unit.hour + 1) % 24; - break; - case DST_ENDING: - date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24; - break; - default: +static void check_and_act_on_daylight_savings(movement_settings_t *settings, watch_date_time date_time) { + if (!settings ->bit.dst_active) return; + uint8_t dst_result = get_dst_status(date_time); + + if (settings ->bit.dst_skip_rolling_back && dst_result == DST_ENDED) { + settings ->bit.dst_skip_rolling_back = false; return; } - watch_rtc_set_date_time(date_time); + else if (dst_result == DST_ENDING && !settings ->bit.dst_skip_rolling_back) { + settings ->bit.dst_skip_rolling_back = true; + date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24; + watch_rtc_set_date_time(date_time); + return; + } + else if (dst_result == DST_STARTING) { + date_time.unit.hour = (date_time.unit.hour + 1) % 24; + watch_rtc_set_date_time(date_time); + return; + } } bool clock_face_wants_background_task(movement_settings_t *settings, void *context) { clock_state_t *state = (clock_state_t *) context; watch_date_time date_time = watch_rtc_get_date_time(); - check_and_act_on_daylight_savings(settings->bit.dst_active, date_time); + check_and_act_on_daylight_savings(settings, date_time); if (!state->time_signal_enabled) return false; return date_time.unit.minute == 0; diff --git a/movement/watch_faces/clock/simple_clock_face.c b/movement/watch_faces/clock/simple_clock_face.c index c0f8372..a7e08a9 100644 --- a/movement/watch_faces/clock/simple_clock_face.c +++ b/movement/watch_faces/clock/simple_clock_face.c @@ -150,27 +150,31 @@ void simple_clock_face_resign(movement_settings_t *settings, void *context) { (void) context; } -static void check_and_act_on_daylight_savings(bool dst_active, watch_date_time date_time) { - if (!dst_active) return; - uint8_t dst_result = is_dst(date_time); - switch (dst_result) - { - case DST_STARTED: - date_time.unit.hour = (date_time.unit.hour + 1) % 24; - break; - case DST_ENDING: - date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24; - break; - default: +static void check_and_act_on_daylight_savings(movement_settings_t *settings, watch_date_time date_time) { + if (!settings ->bit.dst_active) return; + uint8_t dst_result = get_dst_status(date_time); + + if (settings ->bit.dst_skip_rolling_back && (dst_result == DST_ENDED)) { + settings ->bit.dst_skip_rolling_back = false; return; } - watch_rtc_set_date_time(date_time); + else if (dst_result == DST_ENDING && !settings ->bit.dst_skip_rolling_back) { + settings ->bit.dst_skip_rolling_back = true; + date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24; + watch_rtc_set_date_time(date_time); + return; + } + else if (dst_result == DST_STARTING) { + date_time.unit.hour = (date_time.unit.hour + 1) % 24; + watch_rtc_set_date_time(date_time); + return; + } } bool simple_clock_face_wants_background_task(movement_settings_t *settings, void *context) { simple_clock_state_t *state = (simple_clock_state_t *)context; - watch_date_time date_time = watch_rtc_get_date_time(); - check_and_act_on_daylight_savings(settings->bit.dst_active, date_time); + date_time = watch_rtc_get_date_time(); + check_and_act_on_daylight_savings(settings, date_time); if (!state->signal_enabled) return false; return date_time.unit.minute == 0; diff --git a/movement/watch_faces/settings/set_time_face.c b/movement/watch_faces/settings/set_time_face.c index b16cb6d..3f7d0c7 100644 --- a/movement/watch_faces/settings/set_time_face.c +++ b/movement/watch_faces/settings/set_time_face.c @@ -72,6 +72,7 @@ static void _handle_alarm_button(movement_settings_t *settings, watch_date_time break; } watch_rtc_set_date_time(date_time); + settings->bit.dst_skip_rolling_back = false; } static void _abort_quick_ticks() { diff --git a/movement/watch_faces/settings/set_time_hackwatch_face.c b/movement/watch_faces/settings/set_time_hackwatch_face.c index bdd1b0a..be293ab 100644 --- a/movement/watch_faces/settings/set_time_hackwatch_face.c +++ b/movement/watch_faces/settings/set_time_hackwatch_face.c @@ -94,6 +94,7 @@ bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *s } date_time_settings.unit.second = 0; watch_rtc_set_date_time(date_time_settings); + settings->bit.dst_skip_rolling_back = false; } break; case EVENT_ALARM_BUTTON_DOWN: @@ -134,8 +135,10 @@ bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *s } break; } - if (current_page != 2) // Do not set time when we are at seconds, it was already set previously + 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); + settings->bit.dst_skip_rolling_back = false; + } break; case EVENT_ALARM_LONG_UP://Setting seconds on long release @@ -178,8 +181,10 @@ 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 (current_page != 2) // Do not set time when we are at seconds, it was already set previously + 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); + settings->bit.dst_skip_rolling_back = false; + } //TODO: Do not update whole RTC, just what we are changing break; case EVENT_TIMEOUT: diff --git a/watch-library/shared/watch/watch_utility.c b/watch-library/shared/watch/watch_utility.c index 1410e41..5938b60 100644 --- a/watch-library/shared/watch/watch_utility.c +++ b/watch-library/shared/watch/watch_utility.c @@ -83,38 +83,43 @@ uint8_t is_leap(uint16_t y) return !(y%4) && ((y%100) || !(y%400)); } -uint8_t is_dst(watch_date_time date_time) { - uint8_t weekday_first_of_month; +uint8_t get_dst_status(watch_date_time date_time) { watch_date_time dst_start_time; watch_date_time dst_end_time; uint32_t unix_dst_start_time; uint32_t unix_dst_end_time; uint32_t unix_curr_time; + dst_start_time.unit.year = date_time.unit.year; dst_start_time.unit.month = 3; dst_start_time.unit.hour = 2; dst_start_time.unit.minute = 0; dst_start_time.unit.second = 0; - weekday_first_of_month = watch_utility_get_iso8601_weekday_number(date_time.unit.year, dst_start_time.unit.month, 1); - dst_start_time.unit.day = 15 - weekday_first_of_month; + dst_start_time.unit.day = 15 - watch_utility_get_iso8601_weekday_number(dst_start_time.unit.year + WATCH_RTC_REFERENCE_YEAR, dst_start_time.unit.month, 1); unix_dst_start_time = watch_utility_date_time_to_unix_time(dst_start_time, 0); + dst_end_time.unit.year = date_time.unit.year; dst_end_time.unit.month = 11; dst_end_time.unit.hour = 2; dst_end_time.unit.minute = 0; dst_end_time.unit.second = 0; - weekday_first_of_month = watch_utility_get_iso8601_weekday_number(date_time.unit.year, dst_end_time.unit.month, 1); - dst_end_time.unit.day = 15 - weekday_first_of_month; + dst_end_time.unit.day = 15 - watch_utility_get_iso8601_weekday_number(dst_end_time.unit.year + WATCH_RTC_REFERENCE_YEAR, dst_end_time.unit.month, 1); unix_dst_end_time = watch_utility_date_time_to_unix_time(dst_end_time, 0); + if (date_time.unit.second > 45) // In emu, it's been seen that we may trigger at 59sec rather than exactly 0 each time + date_time.unit.minute = (date_time.unit.minute + 1) % 60; date_time.unit.second = 0; unix_curr_time = watch_utility_date_time_to_unix_time(date_time, 0); - if (unix_curr_time == unix_dst_start_time) return DST_STARTED; + if (unix_curr_time == unix_dst_start_time) return DST_STARTING; if (unix_curr_time == unix_dst_end_time) return DST_ENDING; if (unix_curr_time > unix_dst_end_time || unix_curr_time < unix_dst_start_time) return DST_ENDED; return DST_OCCURRING; -} +} + +bool dst_occurring(watch_date_time date_time) { + return get_dst_status(date_time) <= DST_OCCURRING; +} uint16_t watch_utility_days_since_new_year(uint16_t year, uint8_t month, uint8_t day) { uint16_t DAYS_SO_FAR[] = { From e50390b673fda13a31463509a0d26165f1a4d1ea Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 3 Aug 2024 09:33:49 -0400 Subject: [PATCH 07/11] DST roll is now a global variable in watch_rtc --- movement/movement.c | 20 +++++++++++++ movement/movement.h | 1 + movement/watch_faces/clock/clock_face.c | 29 +++++------------- .../clock/minute_repeater_decimal_face.c | 4 +-- .../clock/repetition_minute_face.c | 4 +-- .../clock/simple_clock_bin_led_face.c | 4 +-- .../watch_faces/clock/simple_clock_face.c | 30 +++++-------------- movement/watch_faces/settings/set_time_face.c | 1 - .../settings/set_time_hackwatch_face.c | 3 -- watch-library/hardware/watch/watch_rtc.c | 14 +++++++++ watch-library/shared/watch/watch_rtc.h | 6 ++++ watch-library/simulator/watch/watch_rtc.c | 14 +++++++++ 12 files changed, 75 insertions(+), 55 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 4afe273..eabc29c 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -430,6 +430,26 @@ uint8_t movement_claim_backup_register(void) { return movement_state.next_available_backup_register++; } +uint8_t check_and_act_on_daylight_savings(watch_date_time date_time) { + if (movement_state.settings.bit.dst_active) return date_time.unit.hour; + uint8_t dst_result = get_dst_status(date_time); + bool dst_skip_rolling_back = get_dst_skip_rolling_back(); + + if (dst_skip_rolling_back && (dst_result == DST_ENDED)) { + clear_dst_skip_rolling_back(); + } + else if (dst_result == DST_ENDING && !dst_skip_rolling_back) { + set_dst_skip_rolling_back(); + date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24; + watch_rtc_set_date_time(date_time); + } + else if (dst_result == DST_STARTING) { + date_time.unit.hour = (date_time.unit.hour + 1) % 24; + watch_rtc_set_date_time(date_time); + } + return date_time.unit.hour; +} + int16_t get_timezone_offset(uint8_t timezone_idx, watch_date_time date_time) { if (!movement_state.settings.bit.dst_active) return movement_timezone_offsets[timezone_idx]; if (dst_occurring(date_time)) diff --git a/movement/movement.h b/movement/movement.h index d0595fb..6dd38ba 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -313,6 +313,7 @@ void movement_play_alarm(void); void movement_play_alarm_beeps(uint8_t rounds, BuzzerNote alarm_note); uint8_t movement_claim_backup_register(void); +uint8_t check_and_act_on_daylight_savings(watch_date_time date_time); // Returns the currently set hour int16_t get_timezone_offset(uint8_t timezone_idx, watch_date_time date_time); #endif // MOVEMENT_H_ diff --git a/movement/watch_faces/clock/clock_face.c b/movement/watch_faces/clock/clock_face.c index f9ec58a..af601ce 100644 --- a/movement/watch_faces/clock/clock_face.c +++ b/movement/watch_faces/clock/clock_face.c @@ -280,31 +280,16 @@ void clock_face_resign(movement_settings_t *settings, void *context) { (void) context; } -static void check_and_act_on_daylight_savings(movement_settings_t *settings, watch_date_time date_time) { - if (!settings ->bit.dst_active) return; - uint8_t dst_result = get_dst_status(date_time); - - if (settings ->bit.dst_skip_rolling_back && dst_result == DST_ENDED) { - settings ->bit.dst_skip_rolling_back = false; - return; - } - else if (dst_result == DST_ENDING && !settings ->bit.dst_skip_rolling_back) { - settings ->bit.dst_skip_rolling_back = true; - date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24; - watch_rtc_set_date_time(date_time); - return; - } - else if (dst_result == DST_STARTING) { - date_time.unit.hour = (date_time.unit.hour + 1) % 24; - watch_rtc_set_date_time(date_time); - return; - } -} - bool clock_face_wants_background_task(movement_settings_t *settings, void *context) { + (void) settings; clock_state_t *state = (clock_state_t *) context; watch_date_time date_time = watch_rtc_get_date_time(); - check_and_act_on_daylight_savings(settings, date_time); + uint8_t hour_dst = check_and_act_on_daylight_savings(date_time); + if(hour_dst != date_time.unit.hour) { + char buf[3 + 1]; + sprintf(buf, "%2d", hour_dst); + watch_display_string(buf, 4); + } if (!state->time_signal_enabled) return false; return date_time.unit.minute == 0; diff --git a/movement/watch_faces/clock/minute_repeater_decimal_face.c b/movement/watch_faces/clock/minute_repeater_decimal_face.c index 2cedc30..ab0e6de 100644 --- a/movement/watch_faces/clock/minute_repeater_decimal_face.c +++ b/movement/watch_faces/clock/minute_repeater_decimal_face.c @@ -230,9 +230,9 @@ void minute_repeater_decimal_face_resign(movement_settings_t *settings, void *co bool minute_repeater_decimal_face_wants_background_task(movement_settings_t *settings, void *context) { (void) settings; minute_repeater_decimal_state_t *state = (minute_repeater_decimal_state_t *)context; - if (!state->signal_enabled) return false; - watch_date_time date_time = watch_rtc_get_date_time(); + check_and_act_on_daylight_savings(date_time); + if (!state->signal_enabled) return false; return date_time.unit.minute == 0; } diff --git a/movement/watch_faces/clock/repetition_minute_face.c b/movement/watch_faces/clock/repetition_minute_face.c index e9e5e31..1afc4ce 100644 --- a/movement/watch_faces/clock/repetition_minute_face.c +++ b/movement/watch_faces/clock/repetition_minute_face.c @@ -213,9 +213,9 @@ void repetition_minute_face_resign(movement_settings_t *settings, void *context) bool repetition_minute_face_wants_background_task(movement_settings_t *settings, void *context) { (void) settings; repetition_minute_state_t *state = (repetition_minute_state_t *)context; - if (!state->signal_enabled) return false; - watch_date_time date_time = watch_rtc_get_date_time(); + check_and_act_on_daylight_savings(date_time); + if (!state->signal_enabled) return false; return date_time.unit.minute == 0; } diff --git a/movement/watch_faces/clock/simple_clock_bin_led_face.c b/movement/watch_faces/clock/simple_clock_bin_led_face.c index cf39c18..1762cfa 100644 --- a/movement/watch_faces/clock/simple_clock_bin_led_face.c +++ b/movement/watch_faces/clock/simple_clock_bin_led_face.c @@ -214,9 +214,9 @@ void simple_clock_bin_led_face_resign(movement_settings_t *settings, void *conte bool simple_clock_bin_led_face_wants_background_task(movement_settings_t *settings, void *context) { (void) settings; simple_clock_bin_led_state_t *state = (simple_clock_bin_led_state_t *)context; - if (!state->signal_enabled) return false; - watch_date_time date_time = watch_rtc_get_date_time(); + check_and_act_on_daylight_savings(date_time); + if (!state->signal_enabled) return false; return date_time.unit.minute == 0; } diff --git a/movement/watch_faces/clock/simple_clock_face.c b/movement/watch_faces/clock/simple_clock_face.c index a7e08a9..3866e2c 100644 --- a/movement/watch_faces/clock/simple_clock_face.c +++ b/movement/watch_faces/clock/simple_clock_face.c @@ -150,31 +150,15 @@ void simple_clock_face_resign(movement_settings_t *settings, void *context) { (void) context; } -static void check_and_act_on_daylight_savings(movement_settings_t *settings, watch_date_time date_time) { - if (!settings ->bit.dst_active) return; - uint8_t dst_result = get_dst_status(date_time); - - if (settings ->bit.dst_skip_rolling_back && (dst_result == DST_ENDED)) { - settings ->bit.dst_skip_rolling_back = false; - return; - } - else if (dst_result == DST_ENDING && !settings ->bit.dst_skip_rolling_back) { - settings ->bit.dst_skip_rolling_back = true; - date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24; - watch_rtc_set_date_time(date_time); - return; - } - else if (dst_result == DST_STARTING) { - date_time.unit.hour = (date_time.unit.hour + 1) % 24; - watch_rtc_set_date_time(date_time); - return; - } -} - bool simple_clock_face_wants_background_task(movement_settings_t *settings, void *context) { simple_clock_state_t *state = (simple_clock_state_t *)context; - date_time = watch_rtc_get_date_time(); - check_and_act_on_daylight_savings(settings, date_time); + watch_date_time date_time = watch_rtc_get_date_time(); + uint8_t hour_dst = check_and_act_on_daylight_savings(date_time); + if(hour_dst != date_time.unit.hour) { + char buf[3 + 1]; + sprintf(buf, "%2d", hour_dst); + watch_display_string(buf, 4); + } if (!state->signal_enabled) return false; return date_time.unit.minute == 0; diff --git a/movement/watch_faces/settings/set_time_face.c b/movement/watch_faces/settings/set_time_face.c index 3f7d0c7..b16cb6d 100644 --- a/movement/watch_faces/settings/set_time_face.c +++ b/movement/watch_faces/settings/set_time_face.c @@ -72,7 +72,6 @@ static void _handle_alarm_button(movement_settings_t *settings, watch_date_time break; } watch_rtc_set_date_time(date_time); - settings->bit.dst_skip_rolling_back = false; } static void _abort_quick_ticks() { diff --git a/movement/watch_faces/settings/set_time_hackwatch_face.c b/movement/watch_faces/settings/set_time_hackwatch_face.c index be293ab..44ae04e 100644 --- a/movement/watch_faces/settings/set_time_hackwatch_face.c +++ b/movement/watch_faces/settings/set_time_hackwatch_face.c @@ -94,7 +94,6 @@ bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *s } date_time_settings.unit.second = 0; watch_rtc_set_date_time(date_time_settings); - settings->bit.dst_skip_rolling_back = false; } break; case EVENT_ALARM_BUTTON_DOWN: @@ -137,7 +136,6 @@ bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *s } 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); - settings->bit.dst_skip_rolling_back = false; } break; @@ -183,7 +181,6 @@ bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *s } 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); - settings->bit.dst_skip_rolling_back = false; } //TODO: Do not update whole RTC, just what we are changing break; diff --git a/watch-library/hardware/watch/watch_rtc.c b/watch-library/hardware/watch/watch_rtc.c index 93cb9f1..67ecb53 100644 --- a/watch-library/hardware/watch/watch_rtc.c +++ b/watch-library/hardware/watch/watch_rtc.c @@ -30,6 +30,19 @@ ext_irq_cb_t btn_alarm_callback; ext_irq_cb_t a2_callback; ext_irq_cb_t a4_callback; +static bool dst_skip_rolling_back; +bool get_dst_skip_rolling_back(void) { + return dst_skip_rolling_back; +} + +void set_dst_skip_rolling_back(void) { + dst_skip_rolling_back = true; +} + +void clear_dst_skip_rolling_back(void) { + dst_skip_rolling_back = false; +} + bool _watch_rtc_is_enabled(void) { return RTC->MODE2.CTRLA.bit.ENABLE; } @@ -60,6 +73,7 @@ void watch_rtc_set_date_time(watch_date_time date_time) { _sync_rtc(); // Double sync as without it at high Hz faces setting time is unrealiable (specifically, set_time_hackwatch) RTC->MODE2.CLOCK.reg = date_time.reg; _sync_rtc(); + clear_dst_skip_rolling_back(); } watch_date_time watch_rtc_get_date_time(void) { diff --git a/watch-library/shared/watch/watch_rtc.h b/watch-library/shared/watch/watch_rtc.h index 3e63bb5..a9134eb 100644 --- a/watch-library/shared/watch/watch_rtc.h +++ b/watch-library/shared/watch/watch_rtc.h @@ -157,5 +157,11 @@ void watch_rtc_enable(bool en); */ void watch_rtc_freqcorr_write(int16_t value, int16_t sign); +/** @brief Returns if we're currently at a point where the we rolled back for DST and need to ignore the next DST segment + */ +bool get_dst_skip_rolling_back(void); +void set_dst_skip_rolling_back(void); +void clear_dst_skip_rolling_back(void); + /// @} #endif diff --git a/watch-library/simulator/watch/watch_rtc.c b/watch-library/simulator/watch/watch_rtc.c index 2bb6074..9fe9e29 100644 --- a/watch-library/simulator/watch/watch_rtc.c +++ b/watch-library/simulator/watch/watch_rtc.c @@ -39,6 +39,19 @@ ext_irq_cb_t btn_alarm_callback; ext_irq_cb_t a2_callback; ext_irq_cb_t a4_callback; +static bool dst_skip_rolling_back; +bool get_dst_skip_rolling_back(void) { + return dst_skip_rolling_back; +} + +void set_dst_skip_rolling_back(void) { + dst_skip_rolling_back = true; +} + +void clear_dst_skip_rolling_back(void) { + dst_skip_rolling_back = false; +} + bool _watch_rtc_is_enabled(void) { return true; } @@ -57,6 +70,7 @@ void watch_rtc_set_date_time(watch_date_time date_time) { const date = new Date(year, month - 1, day, hour, minute, second); return date - Date.now(); }, date_time.reg); + clear_dst_skip_rolling_back(); } watch_date_time watch_rtc_get_date_time(void) { From aebea960c01772bcb54210b30109eb1b11b4e34d Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sat, 3 Aug 2024 10:08:24 -0400 Subject: [PATCH 08/11] Cleanup to the default branch --- movement/movement.c | 2 +- movement/watch_faces/clock/simple_clock_face.c | 1 + movement/watch_faces/settings/set_time_face.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index eabc29c..256aa8a 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -458,7 +458,6 @@ int16_t get_timezone_offset(uint8_t timezone_idx, watch_date_time date_time) { } void app_init(void) { - const int16_t* timezone_offsets; #if defined(NO_FREQCORR) watch_rtc_freqcorr_write(0, 0); #elif defined(WATCH_IS_BLUE_BOARD) @@ -485,6 +484,7 @@ void app_init(void) { filesystem_init(); #if __EMSCRIPTEN__ + const int16_t* timezone_offsets; int32_t time_zone_offset = EM_ASM_INT({ return -new Date().getTimezoneOffset(); }); diff --git a/movement/watch_faces/clock/simple_clock_face.c b/movement/watch_faces/clock/simple_clock_face.c index 3866e2c..20dfb54 100644 --- a/movement/watch_faces/clock/simple_clock_face.c +++ b/movement/watch_faces/clock/simple_clock_face.c @@ -151,6 +151,7 @@ void simple_clock_face_resign(movement_settings_t *settings, void *context) { } bool simple_clock_face_wants_background_task(movement_settings_t *settings, void *context) { + (void) settings; simple_clock_state_t *state = (simple_clock_state_t *)context; watch_date_time date_time = watch_rtc_get_date_time(); uint8_t hour_dst = check_and_act_on_daylight_savings(date_time); diff --git a/movement/watch_faces/settings/set_time_face.c b/movement/watch_faces/settings/set_time_face.c index b16cb6d..1b19df8 100644 --- a/movement/watch_faces/settings/set_time_face.c +++ b/movement/watch_faces/settings/set_time_face.c @@ -134,7 +134,7 @@ bool set_time_face_loop(movement_event_t event, movement_settings_t *settings, v return movement_default_loop_handler(event, settings); } - char buf[11]; + char buf[13]; if (current_page < 3) { watch_set_colon(); if (settings->bit.clock_mode_24h) { From 2824a62908b9f7b6e24b25c5ba46e0f3287ae80f Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sun, 4 Aug 2024 09:43:56 -0400 Subject: [PATCH 09/11] Bugfix on not registering the top of an hour --- movement/movement.c | 22 +++++++++++++++---- movement/movement.h | 2 +- movement/watch_faces/clock/clock_face.c | 7 +----- .../watch_faces/clock/simple_clock_face.c | 7 +----- watch-library/shared/watch/watch_utility.c | 6 ++--- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index 256aa8a..aead621 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -430,8 +430,8 @@ uint8_t movement_claim_backup_register(void) { return movement_state.next_available_backup_register++; } -uint8_t check_and_act_on_daylight_savings(watch_date_time date_time) { - if (movement_state.settings.bit.dst_active) return date_time.unit.hour; +bool check_and_act_on_daylight_savings(watch_date_time date_time) { + if (!movement_state.settings.bit.dst_active) return false; uint8_t dst_result = get_dst_status(date_time); bool dst_skip_rolling_back = get_dst_skip_rolling_back(); @@ -439,15 +439,17 @@ uint8_t check_and_act_on_daylight_savings(watch_date_time date_time) { clear_dst_skip_rolling_back(); } else if (dst_result == DST_ENDING && !dst_skip_rolling_back) { - set_dst_skip_rolling_back(); date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24; watch_rtc_set_date_time(date_time); + set_dst_skip_rolling_back(); + return true; } else if (dst_result == DST_STARTING) { date_time.unit.hour = (date_time.unit.hour + 1) % 24; watch_rtc_set_date_time(date_time); + return true; } - return date_time.unit.hour; + return false; } int16_t get_timezone_offset(uint8_t timezone_idx, watch_date_time date_time) { @@ -476,6 +478,18 @@ void app_init(void) { movement_state.settings.bit.le_interval = MOVEMENT_DEFAULT_LOW_ENERGY_INTERVAL; movement_state.settings.bit.led_duration = MOVEMENT_DEFAULT_LED_DURATION; movement_state.settings.bit.dst_active = MOVEMENT_DEFAULT_DST_ACTIVE; + +#ifdef MAKEFILE_TIMEZONE + timezone_offsets = dst_occurring(watch_rtc_get_date_time()) ? movement_timezone_dst_offsets : movement_timezone_offsets; + for (int i = 0; i < NUM_TIME_ZONES; i++) { + if (timezone_offsets[i] == MAKEFILE_TIMEZONE) { + movement_state.settings.bit.time_zone = i; + break; + } + } +#else + movement_state.settings.bit.time_zone = 35; // Atlantic Time as default +#endif movement_state.light_ticks = -1; movement_state.alarm_ticks = -1; movement_state.next_available_backup_register = 4; diff --git a/movement/movement.h b/movement/movement.h index 6dd38ba..e75f4e8 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -313,7 +313,7 @@ void movement_play_alarm(void); void movement_play_alarm_beeps(uint8_t rounds, BuzzerNote alarm_note); uint8_t movement_claim_backup_register(void); -uint8_t check_and_act_on_daylight_savings(watch_date_time date_time); // Returns the currently set hour +bool check_and_act_on_daylight_savings(watch_date_time date_time); // Returns if the time was changed due to DST int16_t get_timezone_offset(uint8_t timezone_idx, watch_date_time date_time); #endif // MOVEMENT_H_ diff --git a/movement/watch_faces/clock/clock_face.c b/movement/watch_faces/clock/clock_face.c index af601ce..e29d587 100644 --- a/movement/watch_faces/clock/clock_face.c +++ b/movement/watch_faces/clock/clock_face.c @@ -284,12 +284,7 @@ bool clock_face_wants_background_task(movement_settings_t *settings, void *conte (void) settings; clock_state_t *state = (clock_state_t *) context; watch_date_time date_time = watch_rtc_get_date_time(); - uint8_t hour_dst = check_and_act_on_daylight_savings(date_time); - if(hour_dst != date_time.unit.hour) { - char buf[3 + 1]; - sprintf(buf, "%2d", hour_dst); - watch_display_string(buf, 4); - } + check_and_act_on_daylight_savings(date_time); if (!state->time_signal_enabled) return false; return date_time.unit.minute == 0; diff --git a/movement/watch_faces/clock/simple_clock_face.c b/movement/watch_faces/clock/simple_clock_face.c index 20dfb54..118dc32 100644 --- a/movement/watch_faces/clock/simple_clock_face.c +++ b/movement/watch_faces/clock/simple_clock_face.c @@ -154,12 +154,7 @@ bool simple_clock_face_wants_background_task(movement_settings_t *settings, void (void) settings; simple_clock_state_t *state = (simple_clock_state_t *)context; watch_date_time date_time = watch_rtc_get_date_time(); - uint8_t hour_dst = check_and_act_on_daylight_savings(date_time); - if(hour_dst != date_time.unit.hour) { - char buf[3 + 1]; - sprintf(buf, "%2d", hour_dst); - watch_display_string(buf, 4); - } + check_and_act_on_daylight_savings(date_time); if (!state->signal_enabled) return false; return date_time.unit.minute == 0; diff --git a/watch-library/shared/watch/watch_utility.c b/watch-library/shared/watch/watch_utility.c index 5938b60..3dfb37b 100644 --- a/watch-library/shared/watch/watch_utility.c +++ b/watch-library/shared/watch/watch_utility.c @@ -106,10 +106,10 @@ uint8_t get_dst_status(watch_date_time date_time) { dst_end_time.unit.day = 15 - watch_utility_get_iso8601_weekday_number(dst_end_time.unit.year + WATCH_RTC_REFERENCE_YEAR, dst_end_time.unit.month, 1); unix_dst_end_time = watch_utility_date_time_to_unix_time(dst_end_time, 0); - if (date_time.unit.second > 45) // In emu, it's been seen that we may trigger at 59sec rather than exactly 0 each time - date_time.unit.minute = (date_time.unit.minute + 1) % 60; - date_time.unit.second = 0; unix_curr_time = watch_utility_date_time_to_unix_time(date_time, 0); + unix_curr_time -= date_time.unit.second; + if (date_time.unit.second > 45) // In emu, it's been seen that we may trigger at 59sec rather than exactly 0 each time + unix_curr_time += 60; if (unix_curr_time == unix_dst_start_time) return DST_STARTING; if (unix_curr_time == unix_dst_end_time) return DST_ENDING; From 598e87618654c53a5a41e4a77b981b07c738283f Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sun, 4 Aug 2024 10:11:33 -0400 Subject: [PATCH 10/11] check_and_act_on_daylight_savings now only occurs in one spot --- movement/movement.c | 48 ++++++++++--------- movement/movement.h | 1 - movement/watch_faces/clock/clock_face.c | 4 +- .../clock/minute_repeater_decimal_face.c | 4 +- .../clock/repetition_minute_face.c | 4 +- .../clock/simple_clock_bin_led_face.c | 4 +- .../watch_faces/clock/simple_clock_face.c | 4 +- 7 files changed, 36 insertions(+), 33 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index aead621..ebd831f 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -247,6 +247,31 @@ static inline void _movement_disable_fast_tick_if_possible(void) { } } +static bool _check_and_act_on_daylight_savings(void) { + if (!movement_state.settings.bit.dst_active) return false; + watch_date_time date_time = watch_rtc_get_date_time(); + // No need for all of the unix time calculations for times not at the beginning or end of the hour + if (date_time.unit.minute > 1 && date_time.unit.minute < 59) return false; + uint8_t dst_result = get_dst_status(date_time); + bool dst_skip_rolling_back = get_dst_skip_rolling_back(); + + if (dst_skip_rolling_back && (dst_result == DST_ENDED)) { + clear_dst_skip_rolling_back(); + } + else if (dst_result == DST_ENDING && !dst_skip_rolling_back) { + date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24; + watch_rtc_set_date_time(date_time); + set_dst_skip_rolling_back(); + return true; + } + else if (dst_result == DST_STARTING) { + date_time.unit.hour = (date_time.unit.hour + 1) % 24; + watch_rtc_set_date_time(date_time); + return true; + } + return false; +} + 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... @@ -256,6 +281,7 @@ static void _movement_handle_background_tasks(void) { watch_faces[i].loop(background_event, &movement_state.settings, watch_face_contexts[i]); } } + _check_and_act_on_daylight_savings(); movement_state.needs_background_tasks_handled = false; } @@ -430,28 +456,6 @@ uint8_t movement_claim_backup_register(void) { return movement_state.next_available_backup_register++; } -bool check_and_act_on_daylight_savings(watch_date_time date_time) { - if (!movement_state.settings.bit.dst_active) return false; - uint8_t dst_result = get_dst_status(date_time); - bool dst_skip_rolling_back = get_dst_skip_rolling_back(); - - if (dst_skip_rolling_back && (dst_result == DST_ENDED)) { - clear_dst_skip_rolling_back(); - } - else if (dst_result == DST_ENDING && !dst_skip_rolling_back) { - date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24; - watch_rtc_set_date_time(date_time); - set_dst_skip_rolling_back(); - return true; - } - else if (dst_result == DST_STARTING) { - date_time.unit.hour = (date_time.unit.hour + 1) % 24; - watch_rtc_set_date_time(date_time); - return true; - } - return false; -} - int16_t get_timezone_offset(uint8_t timezone_idx, watch_date_time date_time) { if (!movement_state.settings.bit.dst_active) return movement_timezone_offsets[timezone_idx]; if (dst_occurring(date_time)) diff --git a/movement/movement.h b/movement/movement.h index e75f4e8..d0595fb 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -313,7 +313,6 @@ void movement_play_alarm(void); void movement_play_alarm_beeps(uint8_t rounds, BuzzerNote alarm_note); uint8_t movement_claim_backup_register(void); -bool check_and_act_on_daylight_savings(watch_date_time date_time); // Returns if the time was changed due to DST int16_t get_timezone_offset(uint8_t timezone_idx, watch_date_time date_time); #endif // MOVEMENT_H_ diff --git a/movement/watch_faces/clock/clock_face.c b/movement/watch_faces/clock/clock_face.c index e29d587..eab5cd8 100644 --- a/movement/watch_faces/clock/clock_face.c +++ b/movement/watch_faces/clock/clock_face.c @@ -283,9 +283,9 @@ void clock_face_resign(movement_settings_t *settings, void *context) { bool clock_face_wants_background_task(movement_settings_t *settings, void *context) { (void) settings; clock_state_t *state = (clock_state_t *) context; - watch_date_time date_time = watch_rtc_get_date_time(); - check_and_act_on_daylight_savings(date_time); if (!state->time_signal_enabled) return false; + watch_date_time date_time = watch_rtc_get_date_time(); + return date_time.unit.minute == 0; } diff --git a/movement/watch_faces/clock/minute_repeater_decimal_face.c b/movement/watch_faces/clock/minute_repeater_decimal_face.c index ab0e6de..2cedc30 100644 --- a/movement/watch_faces/clock/minute_repeater_decimal_face.c +++ b/movement/watch_faces/clock/minute_repeater_decimal_face.c @@ -230,9 +230,9 @@ void minute_repeater_decimal_face_resign(movement_settings_t *settings, void *co bool minute_repeater_decimal_face_wants_background_task(movement_settings_t *settings, void *context) { (void) settings; minute_repeater_decimal_state_t *state = (minute_repeater_decimal_state_t *)context; - watch_date_time date_time = watch_rtc_get_date_time(); - check_and_act_on_daylight_savings(date_time); if (!state->signal_enabled) return false; + watch_date_time date_time = watch_rtc_get_date_time(); + return date_time.unit.minute == 0; } diff --git a/movement/watch_faces/clock/repetition_minute_face.c b/movement/watch_faces/clock/repetition_minute_face.c index 1afc4ce..e9e5e31 100644 --- a/movement/watch_faces/clock/repetition_minute_face.c +++ b/movement/watch_faces/clock/repetition_minute_face.c @@ -213,9 +213,9 @@ void repetition_minute_face_resign(movement_settings_t *settings, void *context) bool repetition_minute_face_wants_background_task(movement_settings_t *settings, void *context) { (void) settings; repetition_minute_state_t *state = (repetition_minute_state_t *)context; - watch_date_time date_time = watch_rtc_get_date_time(); - check_and_act_on_daylight_savings(date_time); if (!state->signal_enabled) return false; + watch_date_time date_time = watch_rtc_get_date_time(); + return date_time.unit.minute == 0; } diff --git a/movement/watch_faces/clock/simple_clock_bin_led_face.c b/movement/watch_faces/clock/simple_clock_bin_led_face.c index 1762cfa..cf39c18 100644 --- a/movement/watch_faces/clock/simple_clock_bin_led_face.c +++ b/movement/watch_faces/clock/simple_clock_bin_led_face.c @@ -214,9 +214,9 @@ void simple_clock_bin_led_face_resign(movement_settings_t *settings, void *conte bool simple_clock_bin_led_face_wants_background_task(movement_settings_t *settings, void *context) { (void) settings; simple_clock_bin_led_state_t *state = (simple_clock_bin_led_state_t *)context; - watch_date_time date_time = watch_rtc_get_date_time(); - check_and_act_on_daylight_savings(date_time); if (!state->signal_enabled) return false; + watch_date_time date_time = watch_rtc_get_date_time(); + return date_time.unit.minute == 0; } diff --git a/movement/watch_faces/clock/simple_clock_face.c b/movement/watch_faces/clock/simple_clock_face.c index 118dc32..fbc2c4b 100644 --- a/movement/watch_faces/clock/simple_clock_face.c +++ b/movement/watch_faces/clock/simple_clock_face.c @@ -153,9 +153,9 @@ void simple_clock_face_resign(movement_settings_t *settings, void *context) { bool simple_clock_face_wants_background_task(movement_settings_t *settings, void *context) { (void) settings; simple_clock_state_t *state = (simple_clock_state_t *)context; - watch_date_time date_time = watch_rtc_get_date_time(); - check_and_act_on_daylight_savings(date_time); if (!state->signal_enabled) return false; + watch_date_time date_time = watch_rtc_get_date_time(); + return date_time.unit.minute == 0; } From 5ae88e438d79bcdb6e18f58aa165d4cf9ef6f87f Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sun, 8 Sep 2024 10:50:09 -0400 Subject: [PATCH 11/11] Minot cleanup --- movement/movement.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index ebd831f..60e9106 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -457,8 +457,7 @@ uint8_t movement_claim_backup_register(void) { } int16_t get_timezone_offset(uint8_t timezone_idx, watch_date_time date_time) { - if (!movement_state.settings.bit.dst_active) return movement_timezone_offsets[timezone_idx]; - if (dst_occurring(date_time)) + if (movement_state.settings.bit.dst_active && dst_occurring(date_time)) return movement_timezone_dst_offsets[timezone_idx]; return movement_timezone_offsets[timezone_idx]; }