mirror of
https://github.com/firewalkwithm3/Sensor-Watch.git
synced 2024-11-22 11:10:29 +08:00
Merge PR #470 - implement automatic DST toggling
Implements logic to automatically offset daylight saving time settings when calculating timezone offsets. This should make the DST functions work automatically with no need for user input in most cases. Reviewed-by: Matheus Afonso Martins Moreira <matheus@matheusmoreira.com> GitHub-Pull-Request: https://github.com/joeycastillo/Sensor-Watch/pull/470
This commit is contained in:
commit
ac5bf8cfce
|
@ -44,6 +44,7 @@ of debounce time.
|
|||
#include "filesystem.h"
|
||||
#include "movement.h"
|
||||
#include "shell.h"
|
||||
#include "watch_utility.h"
|
||||
|
||||
#ifndef MOVEMENT_FIRMWARE
|
||||
#include "movement_config.h"
|
||||
|
@ -130,6 +131,11 @@ of debounce time.
|
|||
#define MOVEMENT_DEFAULT_BIRTHDATE_DAY 0
|
||||
#endif
|
||||
|
||||
// Default to having DST get set
|
||||
#ifndef MOVEMENT_DEFAULT_DST_ACTIVE
|
||||
#define MOVEMENT_DEFAULT_DST_ACTIVE true
|
||||
#endif
|
||||
|
||||
#if __EMSCRIPTEN__
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
@ -141,7 +147,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)
|
||||
|
@ -198,94 +205,50 @@ 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
|
||||
};
|
||||
|
||||
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";
|
||||
|
||||
|
@ -323,6 +286,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...
|
||||
|
@ -332,6 +320,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;
|
||||
}
|
||||
|
||||
|
@ -529,6 +518,12 @@ 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 && dst_occurring(date_time))
|
||||
return movement_timezone_dst_offsets[timezone_idx];
|
||||
return movement_timezone_offsets[timezone_idx];
|
||||
}
|
||||
|
||||
void app_init(void) {
|
||||
#if defined(NO_FREQCORR)
|
||||
watch_rtc_freqcorr_write(0, 0);
|
||||
|
@ -551,6 +546,20 @@ void app_init(void) {
|
|||
movement_state.birthdate.bit.year = MOVEMENT_DEFAULT_BIRTHDATE_YEAR;
|
||||
movement_state.birthdate.bit.month = MOVEMENT_DEFAULT_BIRTHDATE_MONTH;
|
||||
movement_state.birthdate.bit.day = MOVEMENT_DEFAULT_BIRTHDATE_DAY;
|
||||
movement_state.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;
|
||||
|
@ -559,11 +568,13 @@ 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();
|
||||
});
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -130,8 +130,7 @@ typedef struct {
|
|||
} movement_event_t;
|
||||
|
||||
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 int16_t movement_timezone_dst_offsets[];
|
||||
extern const char movement_valid_position_0_chars[];
|
||||
extern const char movement_valid_position_1_chars[];
|
||||
|
||||
|
@ -321,5 +320,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_
|
||||
|
|
|
@ -111,4 +111,11 @@ const watch_face_t watch_faces[] = {
|
|||
#define MOVEMENT_DEFAULT_BIRTHDATE_MONTH 0
|
||||
#define MOVEMENT_DEFAULT_BIRTHDATE_DAY 0
|
||||
|
||||
/* 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_
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -183,8 +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();
|
||||
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);
|
||||
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;
|
||||
|
||||
|
@ -289,7 +290,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(state->tz, 60);
|
||||
hours = result.quot;
|
||||
minutes = result.rem;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -60,15 +60,16 @@ static bool world_clock_face_do_display_mode(movement_event_t event, movement_se
|
|||
watch_date_time date_time;
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
if (settings->bit.clock_mode_24h && !settings->bit.clock_24h_leading_zero) watch_set_indicator(WATCH_INDICATOR_24H);
|
||||
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;
|
||||
// fall through
|
||||
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);
|
||||
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;
|
||||
|
||||
|
@ -176,8 +177,8 @@ static bool _world_clock_face_do_settings_mode(movement_event_t event, movement_
|
|||
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) (state->tz / 60),
|
||||
(int8_t) (state->tz % 60) * (state->tz < 0 ? -1 : 1));
|
||||
watch_set_colon();
|
||||
watch_clear_indicator(WATCH_INDICATOR_PM);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -45,8 +45,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,13 +70,15 @@ static inline void button_beep(movement_settings_t *settings) {
|
|||
}
|
||||
|
||||
static void schedule_countdown(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);
|
||||
|
||||
// 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(), get_tz_offset(settings));
|
||||
uint32_t new_now = watch_utility_date_time_to_unix_time(now, tz);
|
||||
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, get_tz_offset(settings));
|
||||
watch_date_time target_dt = watch_utility_date_time_from_unix_time(state->target_ts, tz);
|
||||
movement_schedule_background_task_for_face(state->watch_face_index, target_dt);
|
||||
}
|
||||
|
||||
|
@ -203,7 +205,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_SIGNAL);
|
||||
}
|
||||
watch_set_colon();
|
||||
|
|
|
@ -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;
|
||||
|
@ -138,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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
@ -238,7 +239,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
|
||||
|
|
|
@ -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);
|
||||
|
@ -207,11 +208,12 @@ static void _planetary_time(movement_event_t event, movement_settings_t *setting
|
|||
uint8_t weekday, planet, planetary_hour;
|
||||
double hour_duration, current_hour, current_minute, current_second;
|
||||
bool set_leading_zero = false;
|
||||
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 ) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,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
|
||||
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, 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;
|
||||
|
||||
|
@ -77,7 +77,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)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++) {
|
||||
|
@ -334,6 +334,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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -254,7 +254,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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -60,13 +60,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;
|
||||
}
|
||||
|
@ -135,8 +128,9 @@ 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];
|
||||
bool set_leading_zero = false;
|
||||
|
||||
if (current_page < 3) {
|
||||
watch_set_colon();
|
||||
if (settings->bit.clock_mode_24h) {
|
||||
|
@ -156,17 +150,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) (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 %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
|
||||
|
|
|
@ -132,8 +132,9 @@ 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);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_ALARM_LONG_UP://Setting seconds on long release
|
||||
|
@ -171,11 +172,16 @@ bool set_time_hackwatch_face_loop(movement_event_t event, movement_settings_t *s
|
|||
if (settings->bit.time_zone > 40) settings->bit.time_zone = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (date_time_settings.unit.day > days_in_month(date_time_settings.unit.month, date_time_settings.unit.year + WATCH_RTC_REFERENCE_YEAR))
|
||||
date_time_settings.unit.day = 1;
|
||||
if (current_page != 2) // Do not set time when we are at seconds, it was already set previously
|
||||
|
||||
if (current_page != 2) { // Do not set time when we are at seconds, it was already set previously
|
||||
watch_rtc_set_date_time(date_time_settings);
|
||||
}
|
||||
|
||||
//TODO: Do not update whole RTC, just what we are changing
|
||||
|
||||
break;
|
||||
case EVENT_TIMEOUT:
|
||||
movement_move_to_face(0);
|
||||
|
@ -231,12 +237,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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -83,6 +83,44 @@ uint8_t is_leap(uint16_t y)
|
|||
return !(y%4) && ((y%100) || !(y%400));
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
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);
|
||||
|
||||
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;
|
||||
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[] = {
|
||||
0, // Jan
|
||||
|
|
|
@ -45,6 +45,13 @@ typedef struct {
|
|||
uint32_t days; // 0-4294967295
|
||||
} watch_duration_t;
|
||||
|
||||
typedef enum {
|
||||
DST_STARTING,
|
||||
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,17 @@ 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 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.
|
||||
* @param year The year of the date you wish to convert.
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue