From 12241386ea492757b7ca4f5bb0ec6b895e7456a5 Mon Sep 17 00:00:00 2001 From: joeycastillo Date: Sat, 5 Oct 2024 01:27:07 -0400 Subject: [PATCH] movement internal time is now UTC --- movement.c | 64 +++++++++++++++---- movement.h | 6 ++ movement_config.h | 1 + watch-faces/clock/beats_face.c | 4 +- watch-faces/clock/clock_face.c | 6 +- watch-faces/clock/world_clock_face.c | 8 +-- .../complication/advanced_alarm_face.c | 4 +- watch-faces/complication/countdown_face.c | 4 +- .../complication/sunrise_sunset_face.c | 4 +- watch-faces/sensor/voltage_face.c | 2 +- watch-faces/settings/set_time_face.c | 4 +- 11 files changed, 72 insertions(+), 35 deletions(-) diff --git a/movement.c b/movement.c index 27d55e42..dd3091ae 100644 --- a/movement.c +++ b/movement.c @@ -32,6 +32,7 @@ #include #include "app.h" #include "watch.h" +#include "watch_utility.h" #include "usb.h" #include "watch_usb_cdc.h" #include "watch_private.h" @@ -70,6 +71,19 @@ void yield(void) { tud_task(); cdc_task(); } + +static udatetime_t _movement_convert_date_time_to_udate(watch_date_time date_time) { + return (udatetime_t) { + .date.dayofmonth = date_time.unit.day, + .date.dayofweek = dayofweek(UYEAR_FROM_YEAR(date_time.unit.year + WATCH_RTC_REFERENCE_YEAR), date_time.unit.month, date_time.unit.day), + .date.month = date_time.unit.month, + .date.year = UYEAR_FROM_YEAR(date_time.unit.year + WATCH_RTC_REFERENCE_YEAR), + .time.hour = date_time.unit.hour, + .time.minute = date_time.unit.minute, + .time.second = date_time.unit.second + }; +} + static inline void _movement_reset_inactivity_countdown(void) { movement_state.le_mode_ticks = movement_le_inactivity_deadlines[movement_state.settings.bit.le_interval]; movement_state.timeout_ticks = movement_timeout_inactivity_deadlines[movement_state.settings.bit.to_interval]; @@ -314,22 +328,24 @@ uint8_t movement_claim_backup_register(void) { int32_t movement_get_current_timezone_offset_for_zone(uint8_t zone_index) { watch_date_time date_time = watch_rtc_get_date_time(); - uzone_t time_zone; - uoffset_t offset; - udatetime_t udate_time = { - .date.dayofmonth = date_time.unit.day, - .date.dayofweek = dayofweek(date_time.unit.year + WATCH_RTC_REFERENCE_YEAR - UYEAR_OFFSET, date_time.unit.month, date_time.unit.day), - .date.month = date_time.unit.month, - .date.year = date_time.unit.year + WATCH_RTC_REFERENCE_YEAR - UYEAR_OFFSET, - .time.hour = date_time.unit.hour, - .time.minute = date_time.unit.minute, - .time.second = date_time.unit.second - }; + udatetime_t udate_time = _movement_convert_date_time_to_udate(watch_rtc_get_date_time()); + uzone_t local_zone; - unpack_zone(&zone_defns[zone_index], "", &time_zone); - get_current_offset(&time_zone, &udate_time, &offset); + // first unpack the zone to get the baseline offset + unpack_zone(&zone_defns[zone_index], "", &local_zone); - return offset.hours * 3600 + offset.minutes * 60; + // offset the UTC time by that amount to get the local standard time + date_time = watch_utility_date_time_convert_zone(date_time, 0, local_zone.offset.hours * 3600 + local_zone.offset.minutes * 60); + + // if local zone has DST rules, we need to see if DST applies. + if (local_zone.rules_len) { + udate_time = _movement_convert_date_time_to_udate(date_time); + uoffset_t offset; + get_current_offset(&local_zone, &udate_time, &offset); + return offset.hours * 3600 + offset.minutes * 60; + } + + return local_zone.offset.hours * 3600 + local_zone.offset.minutes * 60; } int32_t movement_get_current_timezone_offset(void) { @@ -344,6 +360,26 @@ void movement_set_timezone_index(uint8_t value) { movement_state.settings.bit.time_zone = value; } +watch_date_time movement_get_utc_date_time(void) { + return watch_rtc_get_date_time(); +} + +watch_date_time movement_get_date_time_in_zone(uint8_t zone_index) { + int32_t offset = movement_get_current_timezone_offset_for_zone(zone_index); + return watch_utility_date_time_convert_zone(watch_rtc_get_date_time(), 0, offset); +} + +watch_date_time movement_get_local_date_time(void) { + watch_date_time date_time = watch_rtc_get_date_time(); + return watch_utility_date_time_convert_zone(date_time, 0, movement_get_current_timezone_offset()); +} + +void movement_set_local_date_time(watch_date_time date_time) { + int32_t current_offset = movement_get_current_timezone_offset(); + watch_date_time utc_date_time = watch_utility_date_time_convert_zone(date_time, current_offset, 0); + watch_rtc_set_date_time(utc_date_time); +} + bool movement_button_should_sound(void) { return movement_state.settings.bit.button_should_sound; } diff --git a/movement.h b/movement.h index d024179c..72ac9d7c 100644 --- a/movement.h +++ b/movement.h @@ -337,6 +337,12 @@ int32_t movement_get_current_timezone_offset(void); int32_t movement_get_timezone_index(void); void movement_set_timezone_index(uint8_t value); +watch_date_time movement_get_utc_date_time(void); +watch_date_time movement_get_local_date_time(void); +watch_date_time movement_get_date_time_in_zone(uint8_t zone_index); + +void movement_set_local_date_time(watch_date_time date_time); + bool movement_button_should_sound(void); void movement_set_button_should_sound(bool value); diff --git a/movement_config.h b/movement_config.h index 94564d95..349de1ea 100644 --- a/movement_config.h +++ b/movement_config.h @@ -29,6 +29,7 @@ const watch_face_t watch_faces[] = { clock_face, + world_clock_face, sunrise_sunset_face, beats_face, advanced_alarm_face, diff --git a/watch-faces/clock/beats_face.c b/watch-faces/clock/beats_face.c index f0e34a98..b2bde552 100644 --- a/watch-faces/clock/beats_face.c +++ b/watch-faces/clock/beats_face.c @@ -57,7 +57,7 @@ bool beats_face_loop(movement_event_t event, void *context) { switch (event.event_type) { case EVENT_ACTIVATE: case EVENT_TICK: - date_time = watch_rtc_get_date_time(); + date_time = movement_get_local_date_time(); centibeats = clock2beats(date_time.unit.hour, date_time.unit.minute, date_time.unit.second, event.subsecond, movement_get_current_timezone_offset()); if (centibeats == state->last_centibeat_displayed) { // we missed this update, try again next subsecond @@ -73,7 +73,7 @@ bool beats_face_loop(movement_event_t event, void *context) { break; case EVENT_LOW_ENERGY_UPDATE: if (!watch_sleep_animation_is_running()) watch_start_sleep_animation(432); - date_time = watch_rtc_get_date_time(); + date_time = movement_get_local_date_time(); centibeats = clock2beats(date_time.unit.hour, date_time.unit.minute, date_time.unit.second, event.subsecond, movement_get_current_timezone_offset()); sprintf(buf, "%4lu ", centibeats / 100); diff --git a/watch-faces/clock/clock_face.c b/watch-faces/clock/clock_face.c index 05280c91..0fb63451 100644 --- a/watch-faces/clock/clock_face.c +++ b/watch-faces/clock/clock_face.c @@ -245,11 +245,11 @@ bool clock_face_loop(movement_event_t event, void *context) { switch (event.event_type) { case EVENT_LOW_ENERGY_UPDATE: clock_start_tick_tock_animation(); - clock_display_low_energy(watch_rtc_get_date_time()); + clock_display_low_energy(movement_get_local_date_time()); break; case EVENT_TICK: case EVENT_ACTIVATE: - current = watch_rtc_get_date_time(); + current = movement_get_local_date_time(); clock_display_clock(state, current); @@ -282,7 +282,7 @@ movement_watch_face_advisory_t clock_face_advise(void *context) { clock_state_t *state = (clock_state_t *) context; if (state->time_signal_enabled) { - watch_date_time date_time = watch_rtc_get_date_time(); + watch_date_time date_time = movement_get_local_date_time(); retval.wants_background_task = date_time.unit.minute == 0; } diff --git a/watch-faces/clock/world_clock_face.c b/watch-faces/clock/world_clock_face.c index 5e34fd48..4e7cb7b9 100644 --- a/watch-faces/clock/world_clock_face.c +++ b/watch-faces/clock/world_clock_face.c @@ -42,11 +42,6 @@ void world_clock_face_setup(uint8_t watch_face_index, void ** context_ptr) { memset(*context_ptr, 0, sizeof(world_clock_state_t)); world_clock_state_t *state = (world_clock_state_t *)*context_ptr; state->settings.bit.timezone_index = 15; - uint8_t backup_register = movement_claim_backup_register(); - if (backup_register) { - state->settings.reg = watch_get_backup_data(backup_register); - state->backup_register = backup_register; - } } } @@ -72,8 +67,7 @@ static bool world_clock_face_do_display_mode(movement_event_t event, world_clock // fall through case EVENT_TICK: case EVENT_LOW_ENERGY_UPDATE: - date_time = watch_rtc_get_date_time(); - date_time = watch_utility_date_time_convert_zone(date_time, movement_get_current_timezone_offset(), state->current_offset); + date_time = movement_get_date_time_in_zone(state->settings.bit.timezone_index); previous_date_time = state->previous_date_time; state->previous_date_time = date_time.reg; if ((date_time.reg >> 6) == (previous_date_time >> 6) && event.event_type != EVENT_LOW_ENERGY_UPDATE) { diff --git a/watch-faces/complication/advanced_alarm_face.c b/watch-faces/complication/advanced_alarm_face.c index 19edb249..ea012a50 100644 --- a/watch-faces/complication/advanced_alarm_face.c +++ b/watch-faces/complication/advanced_alarm_face.c @@ -156,7 +156,7 @@ static void _alarm_update_alarm_enabled(alarm_state_t *state) { break; } else { if (!now_init) { - now = watch_rtc_get_date_time(); + now = movement_get_local_date_time(); now_init = true; weekday_idx = _get_weekday_idx(now); now_minutes_of_day = now.unit.hour * 60 + now.unit.minute; @@ -244,7 +244,7 @@ movement_watch_face_advisory_t advanced_alarm_face_advise(void *context) { alarm_state_t *state = (alarm_state_t *)context; movement_watch_face_advisory_t retval = { 0 }; - watch_date_time now = watch_rtc_get_date_time(); + watch_date_time now = movement_get_local_date_time(); // just a failsafe: never fire more than one alarm within a minute if (state->alarm_handled_minute == now.unit.minute) return retval; state->alarm_handled_minute = now.unit.minute; diff --git a/watch-faces/complication/countdown_face.c b/watch-faces/complication/countdown_face.c index 1f088c4c..34ea4341 100644 --- a/watch-faces/complication/countdown_face.c +++ b/watch-faces/complication/countdown_face.c @@ -69,7 +69,7 @@ static void schedule_countdown(countdown_state_t *state) { // Calculate the new state->now_ts but don't update it until we've updated the target - // avoid possible race where the old target is compared to the new time and immediately triggers - uint32_t new_now = watch_utility_date_time_to_unix_time(watch_rtc_get_date_time(), movement_get_current_timezone_offset()); + uint32_t new_now = watch_utility_date_time_to_unix_time(movement_get_utc_date_time(), movement_get_current_timezone_offset()); state->target_ts = watch_utility_offset_timestamp(new_now, state->hours, state->minutes, state->seconds); state->now_ts = new_now; watch_date_time target_dt = watch_utility_date_time_from_unix_time(state->target_ts, movement_get_current_timezone_offset()); @@ -196,7 +196,7 @@ void countdown_face_setup(uint8_t watch_face_index, void ** context_ptr) { void countdown_face_activate(void *context) { countdown_state_t *state = (countdown_state_t *)context; if(state->mode == cd_running) { - watch_date_time now = watch_rtc_get_date_time(); + watch_date_time now = movement_get_utc_date_time(); state->now_ts = watch_utility_date_time_to_unix_time(now, movement_get_current_timezone_offset()); watch_set_indicator(WATCH_INDICATOR_SIGNAL); } diff --git a/watch-faces/complication/sunrise_sunset_face.c b/watch-faces/complication/sunrise_sunset_face.c index 95cddfba..474fe9d7 100644 --- a/watch-faces/complication/sunrise_sunset_face.c +++ b/watch-faces/complication/sunrise_sunset_face.c @@ -62,7 +62,7 @@ static void _sunrise_sunset_face_update(sunrise_sunset_state_t *state) { return; } - watch_date_time date_time = watch_rtc_get_date_time(); // the current local date / time + watch_date_time date_time = movement_get_local_date_time(); // the current local date / time watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, movement_get_current_timezone_offset(), 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; @@ -338,7 +338,7 @@ bool sunrise_sunset_face_loop(movement_event_t event, void *context) { // if entering low energy mode, start tick animation if (event.event_type == EVENT_LOW_ENERGY_UPDATE && !watch_sleep_animation_is_running()) watch_start_sleep_animation(1000); // check if we need to update the display - watch_date_time date_time = watch_rtc_get_date_time(); + watch_date_time date_time = movement_get_local_date_time(); if (date_time.reg >= state->rise_set_expires.reg) { // and on the off chance that this happened before EVENT_TIMEOUT snapped us back to rise/set 0, go back now state->rise_index = 0; diff --git a/watch-faces/sensor/voltage_face.c b/watch-faces/sensor/voltage_face.c index b532c9d0..b172ec6b 100644 --- a/watch-faces/sensor/voltage_face.c +++ b/watch-faces/sensor/voltage_face.c @@ -53,7 +53,7 @@ bool voltage_face_loop(movement_event_t event, void *context) { _voltage_face_update_display(); break; case EVENT_TICK: - date_time = watch_rtc_get_date_time(); + date_time = movement_get_local_date_time(); if (date_time.unit.second % 5 == 4) { watch_set_indicator(WATCH_INDICATOR_SIGNAL); } else if (date_time.unit.second % 5 == 0) { diff --git a/watch-faces/settings/set_time_face.c b/watch-faces/settings/set_time_face.c index 70450e52..a1c41c97 100644 --- a/watch-faces/settings/set_time_face.c +++ b/watch-faces/settings/set_time_face.c @@ -66,7 +66,7 @@ static void _handle_alarm_button(watch_date_time date_time, uint8_t current_page } if (date_time.unit.day > days_in_month(date_time.unit.month, date_time.unit.year + WATCH_RTC_REFERENCE_YEAR)) date_time.unit.day = 1; - watch_rtc_set_date_time(date_time); + movement_set_local_date_time(date_time); } static void _abort_quick_ticks() { @@ -90,7 +90,7 @@ void set_time_face_activate(void *context) { bool set_time_face_loop(movement_event_t event, void *context) { uint8_t current_page = *((uint8_t *)context); - watch_date_time date_time = watch_rtc_get_date_time(); + watch_date_time date_time = movement_get_local_date_time(); switch (event.event_type) { case EVENT_TICK: