From ecc633fab44073f6c2f8a27b9ad7bed3247ea793 Mon Sep 17 00:00:00 2001 From: Joey Castillo Date: Sat, 15 Mar 2025 11:42:48 -0400 Subject: [PATCH] second movement: persist settings to file system --- movement.c | 77 +++++++++++++++++++++++++++++++++--------------------- movement.h | 12 +++++---- 2 files changed, 54 insertions(+), 35 deletions(-) diff --git a/movement.c b/movement.c index eba069c7..27bdf21c 100644 --- a/movement.c +++ b/movement.c @@ -514,15 +514,19 @@ void movement_set_backlight_dwell(uint8_t value) { } void movement_store_settings(void) { - watch_store_backup_data(movement_state.settings.reg, 0); + movement_settings_t old_settings; + filesystem_read_file("settings.u32", (char *)&old_settings, sizeof(movement_settings_t)); + if (movement_state.settings.reg != old_settings.reg) { + filesystem_write_file("settings.u32", (char *)&movement_state.settings, sizeof(movement_settings_t)); + } } bool movement_alarm_enabled(void) { - return movement_state.settings.bit.alarm_enabled; + return movement_state.alarm_enabled; } void movement_set_alarm_enabled(bool value) { - movement_state.settings.bit.alarm_enabled = value; + movement_state.alarm_enabled = value; } void movement_enable_tap_detection_if_available(void) { @@ -569,6 +573,8 @@ void movement_disable_tap_detection_if_available(void) { void app_init(void) { _watch_init(); + filesystem_init(); + watch_date_time_t date_time = watch_rtc_get_date_time(); if (date_time.reg == 0) { // at first boot, set year to 2024 @@ -597,41 +603,52 @@ void app_init(void) { memset(&movement_state, 0, sizeof(movement_state)); - movement_state.settings.bit.clock_mode_24h = MOVEMENT_DEFAULT_24H_MODE; - movement_state.settings.bit.time_zone = UTZ_UTC; - movement_state.settings.bit.led_red_color = MOVEMENT_DEFAULT_RED_COLOR; - movement_state.settings.bit.led_green_color = MOVEMENT_DEFAULT_GREEN_COLOR; -#if defined(WATCH_BLUE_TCC_CHANNEL) && !defined(WATCH_GREEN_TCC_CHANNEL) - // If there is a blue LED but no green LED, this is a blue Special Edition board. - // In the past, the "green color" showed up as the blue color on the blue board. - if (MOVEMENT_DEFAULT_RED_COLOR == 0 && MOVEMENT_DEFAULT_BLUE_COLOR == 0) { - // If the red color is 0 and the blue color is 0, we'll fall back to the old - // behavior, since otherwise there would be no default LED color. - movement_state.settings.bit.led_blue_color = MOVEMENT_DEFAULT_GREEN_COLOR; - } else { - // however if either the red or blue color is nonzero, we'll assume the user - // has used the new defaults and knows what color they want. this could be red - // if blue is 0, or a custom color if both are nonzero. - movement_state.settings.bit.led_blue_color = MOVEMENT_DEFAULT_BLUE_COLOR; + bool settings_file_exists = filesystem_file_exists("settings.u32"); + movement_settings_t maybe_settings; + if (settings_file_exists && maybe_settings.bit.version == 0) { + filesystem_read_file("settings.u32", (char *) &maybe_settings, sizeof(movement_settings_t)); } -#else - movement_state.settings.bit.led_blue_color = MOVEMENT_DEFAULT_BLUE_COLOR; -#endif - movement_state.settings.bit.button_should_sound = MOVEMENT_DEFAULT_BUTTON_SOUND; - 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; + if (settings_file_exists && maybe_settings.bit.version == 0) { + // If settings file exists and has a valid version, restore it! + movement_state.settings.reg = maybe_settings.reg; + } else { + // Otherwise set default values. + movement_state.settings.bit.version = 0; + movement_state.settings.bit.clock_mode_24h = MOVEMENT_DEFAULT_24H_MODE; + movement_state.settings.bit.time_zone = UTZ_UTC; + movement_state.settings.bit.led_red_color = MOVEMENT_DEFAULT_RED_COLOR; + movement_state.settings.bit.led_green_color = MOVEMENT_DEFAULT_GREEN_COLOR; + #if defined(WATCH_BLUE_TCC_CHANNEL) && !defined(WATCH_GREEN_TCC_CHANNEL) + // If there is a blue LED but no green LED, this is a blue Special Edition board. + // In the past, the "green color" showed up as the blue color on the blue board. + if (MOVEMENT_DEFAULT_RED_COLOR == 0 && MOVEMENT_DEFAULT_BLUE_COLOR == 0) { + // If the red color is 0 and the blue color is 0, we'll fall back to the old + // behavior, since otherwise there would be no default LED color. + movement_state.settings.bit.led_blue_color = MOVEMENT_DEFAULT_GREEN_COLOR; + } else { + // however if either the red or blue color is nonzero, we'll assume the user + // has used the new defaults and knows what color they want. this could be red + // if blue is 0, or a custom color if both are nonzero. + movement_state.settings.bit.led_blue_color = MOVEMENT_DEFAULT_BLUE_COLOR; + } + #else + movement_state.settings.bit.led_blue_color = MOVEMENT_DEFAULT_BLUE_COLOR; + #endif + movement_state.settings.bit.button_should_sound = MOVEMENT_DEFAULT_BUTTON_SOUND; + 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_store_settings(); + } movement_state.light_ticks = -1; movement_state.alarm_ticks = -1; - movement_state.next_available_backup_register = 4; + movement_state.next_available_backup_register = 2; _movement_reset_inactivity_countdown(); - - filesystem_init(); } void app_wake_from_backup(void) { - /// TODO: #SecondMovement needs to restore settings from file system. } void app_setup(void) { diff --git a/movement.h b/movement.h index 55a3b391..8031daeb 100644 --- a/movement.h +++ b/movement.h @@ -66,6 +66,7 @@ typedef struct { // display, time zones, buzzer behavior, LED color and low energy mode timeouts. typedef union { struct { + uint8_t version : 2; // A version number for the struct. 0-3; let's try not to update too often. bool button_should_sound : 1; // if true, pressing a button emits a sound. uint8_t to_interval : 2; // an inactivity interval for asking the active face to resign. uint8_t le_interval : 3; // 0 to disable low energy mode, or an inactivity interval for going into low energy mode. @@ -81,10 +82,9 @@ typedef union { // altimeter to display feet or meters as easily as it tells a thermometer to display degrees in F or C. bool clock_mode_24h : 1; // indicates whether clock should use 12 or 24 hour mode. bool use_imperial_units : 1; // indicates whether to use metric units (the default) or imperial. - - /// TODO: for #SecondMovement: move alarm_enabled out of preferences - bool alarm_enabled : 1; // indicates whether there is at least one alarm enabled. - uint8_t reserved : 2; // room for more preferences if needed. + + // That's 31 bits, leaving room for one more toggle if needed. + uint8_t reserved : 1; } bit; uint32_t reg; } movement_settings_t; @@ -260,7 +260,6 @@ typedef struct { } watch_face_t; typedef struct { - // properties stored in BACKUP register movement_settings_t settings; // transient properties @@ -301,6 +300,9 @@ typedef struct { // backup register stuff uint8_t next_available_backup_register; + + // temporary alarm enabled boolean, until we implement this in advisories + bool alarm_enabled; } movement_state_t; void movement_move_to_face(uint8_t watch_face_index);