From 8b19ce4f1e73c85793a1c279831cff88f917e47f Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Wed, 16 Oct 2024 13:43:09 -0400 Subject: [PATCH 01/10] Add alternate sunrise sunset face --- .../complication/sunrise_sunset_face.c | 305 ++++++++++-------- .../complication/sunrise_sunset_face.h | 8 + 2 files changed, 187 insertions(+), 126 deletions(-) diff --git a/movement/watch_faces/complication/sunrise_sunset_face.c b/movement/watch_faces/complication/sunrise_sunset_face.c index 8747bd868..c04cd7747 100644 --- a/movement/watch_faces/complication/sunrise_sunset_face.c +++ b/movement/watch_faces/complication/sunrise_sunset_face.c @@ -39,15 +39,63 @@ static const uint8_t _location_count = sizeof(longLatPresets) / sizeof(long_lat_presets_t); -static void _sunrise_sunset_set_expiration(sunrise_sunset_state_t *state, watch_date_time next_rise_set) { - uint32_t timestamp = watch_utility_date_time_to_unix_time(next_rise_set, 0); - state->rise_set_expires = watch_utility_date_time_from_unix_time(timestamp + 60, 0); +static int compare(const void *a, const void *b) { + SolarEvent *eventA = (SolarEvent *)a; + SolarEvent *eventB = (SolarEvent *)b; + + return (eventA->timestamp - eventB->timestamp); +} + +static void set_sunriset(double time_value, watch_date_time *time_unit) { + // Calculate minutes and seconds + float minutes = 60.0 * fmod(time_value, 1); + float seconds = 60.0 * fmod(minutes, 1); + + // Set hour and minute + time_unit->unit.hour = floor(time_value); + if (seconds < 30) { + time_unit->unit.minute = floor(minutes); + } else { + time_unit->unit.minute = ceil(minutes); + } + + // Handle edge case where minutes equal 60 + if (time_unit->unit.minute == 60) { + time_unit->unit.minute = 0; + time_unit->unit.hour = (time_unit->unit.hour + 1) % 24; + } +} + +static void display_time(watch_date_time *time, const char *prefix, movement_settings_t *settings, watch_date_time *date_time, sunrise_sunset_state_t *state) { + bool set_leading_zero = false; + char buf[32]; // Adjust size as needed + + // Handle 12-hour mode and PM indicator + if (!settings->bit.clock_mode_24h) { + if (watch_utility_convert_to_12_hour(time)) { + watch_set_indicator(WATCH_INDICATOR_PM); + } else { + watch_clear_indicator(WATCH_INDICATOR_PM); + } + } + // Handle 24-hour mode with leading zero + else if (settings->bit.clock_24h_leading_zero && time->unit.hour < 10) { + set_leading_zero = true; + } + + // Format and display time + sprintf(buf, "%s%2d%2d%02d%s", prefix, time->unit.day, time->unit.hour, time->unit.minute, longLatPresets[state->longLatToUse].name); + watch_display_string(buf, 0); + + // Display leading zero if needed + if (set_leading_zero) { + watch_display_string("0", 4); + } } -static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_sunset_state_t *state) { +static void sunrise_sunset_face_update(movement_settings_t *settings, sunrise_sunset_state_t *state) { char buf[14]; - double rise, set, minutes, seconds; - bool show_next_match = false; + double civ_start, rise, set, civ_end; movement_location_t movement_location; if (state->longLatToUse == 0 || _location_count <= 1) movement_location = (movement_location_t) watch_get_backup_data(1); @@ -57,6 +105,8 @@ static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_s } if (movement_location.reg == 0) { + watch_clear_colon(); + watch_clear_indicator(WATCH_INDICATOR_PM); watch_display_string("RI no Loc", 0); return; } @@ -64,7 +114,15 @@ 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 scratch_time; // scratchpad, contains different values at different times + watch_date_time civ_start_time; + watch_date_time rise_time; + watch_date_time set_time; + watch_date_time civ_end_time; scratch_time.reg = utc_now.reg; + civ_start_time.reg = utc_now.reg; + rise_time.reg = utc_now.reg; + set_time.reg = utc_now.reg; + civ_end_time.reg = utc_now.reg; // Weird quirky unsigned things were happening when I tried to cast these directly to doubles below. // it looks redundant, but extracting them to local int16's seemed to fix it. @@ -80,96 +138,98 @@ static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_s double hours_from_utc = ((double)movement_timezone_offsets[settings->bit.time_zone]) / 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++) { - uint8_t result = sun_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &rise, &set); - - if (result != 0) { - watch_clear_colon(); - watch_clear_indicator(WATCH_INDICATOR_PM); - watch_clear_indicator(WATCH_INDICATOR_24H); - sprintf(buf, "%s%2d none ", (result == 1) ? "SE" : "rI", scratch_time.unit.day); - watch_display_string(buf, 0); - return; - } - - watch_set_colon(); - if (settings->bit.clock_mode_24h && !settings->bit.clock_24h_leading_zero) watch_set_indicator(WATCH_INDICATOR_24H); + uint8_t result = sun_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &rise, &set); + + if (result != 0) { + watch_clear_colon(); + watch_clear_indicator(WATCH_INDICATOR_PM); + watch_clear_indicator(WATCH_INDICATOR_24H); + sprintf(buf, "%s%2d none ", (result == 1) ? "SE" : "rI", scratch_time.unit.day); + watch_display_string(buf, 0); + return; + } + civil_twilight(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &civ_start, &civ_end); - rise += hours_from_utc; - set += hours_from_utc; + watch_set_colon(); + if (settings->bit.clock_mode_24h && !settings->bit.clock_24h_leading_zero) watch_set_indicator(WATCH_INDICATOR_24H); - minutes = 60.0 * fmod(rise, 1); - seconds = 60.0 * fmod(minutes, 1); - scratch_time.unit.hour = floor(rise); - if (seconds < 30) scratch_time.unit.minute = floor(minutes); - else scratch_time.unit.minute = ceil(minutes); + rise += hours_from_utc; + set += hours_from_utc; + civ_start += hours_from_utc; + civ_end += hours_from_utc; - if (scratch_time.unit.minute == 60) { - scratch_time.unit.minute = 0; - scratch_time.unit.hour = (scratch_time.unit.hour + 1) % 24; - } + set_sunriset(civ_start, &civ_start_time); + if (date_time.reg > civ_start_time.reg) { + // it's after sunset. we need to display sunrise/sunset for tomorrow. + uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); + timestamp += 86400; + civ_start_time = watch_utility_date_time_from_unix_time(timestamp, 0); + set_sunriset(civ_start, &civ_start_time); + } + //display_time(&civ_start_time, "CI", settings, &date_time, state); - if (date_time.reg < scratch_time.reg) _sunrise_sunset_set_expiration(state, scratch_time); + set_sunriset(rise, &rise_time); + if (date_time.reg > rise_time.reg) { + // it's after sunset. we need to display sunrise/sunset for tomorrow. + uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); + timestamp += 86400; + rise_time = watch_utility_date_time_from_unix_time(timestamp, 0); + set_sunriset(rise, &rise_time); + } + //display_time(&rise_time, "rI", settings, &date_time, state); - if (date_time.reg < scratch_time.reg || show_next_match) { - if (state->rise_index == 0 || show_next_match) { - bool set_leading_zero = false; - if (!settings->bit.clock_mode_24h) { - if (watch_utility_convert_to_12_hour(&scratch_time)) watch_set_indicator(WATCH_INDICATOR_PM); - else watch_clear_indicator(WATCH_INDICATOR_PM); - } else if (settings->bit.clock_24h_leading_zero && scratch_time.unit.hour < 10) { - set_leading_zero = true; - } - sprintf(buf, "rI%2d%2d%02d%s", scratch_time.unit.day, scratch_time.unit.hour, scratch_time.unit.minute,longLatPresets[state->longLatToUse].name); - watch_display_string(buf, 0); - if (set_leading_zero) - watch_display_string("0", 4); - return; - } else { - show_next_match = true; - } - } + set_sunriset(set, &set_time); + if (date_time.reg > set_time.reg) { + // it's after sunset. we need to display sunrise/sunset for tomorrow. + uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); + timestamp += 86400; + set_time = watch_utility_date_time_from_unix_time(timestamp, 0); + set_sunriset(set, &set_time); + } + //display_time(&set_time, "SE", settings, &date_time, state); - minutes = 60.0 * fmod(set, 1); - seconds = 60.0 * fmod(minutes, 1); - scratch_time.unit.hour = floor(set); - if (seconds < 30) scratch_time.unit.minute = floor(minutes); - else scratch_time.unit.minute = ceil(minutes); + set_sunriset(civ_end, &civ_end_time); + if (date_time.reg > civ_end_time.reg) { + // it's after sunset. we need to display sunrise/sunset for tomorrow. + uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); + timestamp += 86400; + civ_end_time = watch_utility_date_time_from_unix_time(timestamp, 0); + set_sunriset(civ_end, &civ_end_time); + } + //display_time(&civ_end_time, "SE", settings, &date_time, state); - if (scratch_time.unit.minute == 60) { - scratch_time.unit.minute = 0; - scratch_time.unit.hour = (scratch_time.unit.hour + 1) % 24; - } + SolarEvent events[] = { + {civ_start_time.reg, &civ_start_time, "civ_start_time", "cI"}, + {rise_time.reg, &rise_time, "rise_time", "rI"}, + {set_time.reg, &set_time, "set_time", "SE"}, + {civ_end_time.reg, &civ_end_time, "civ_end_time", "cI"} + }; - if (date_time.reg < scratch_time.reg) _sunrise_sunset_set_expiration(state, scratch_time); + int n = sizeof(events) / sizeof(events[0]); - if (date_time.reg < scratch_time.reg || show_next_match) { - if (state->rise_index == 0 || show_next_match) { - bool set_leading_zero = false; - if (!settings->bit.clock_mode_24h) { - if (watch_utility_convert_to_12_hour(&scratch_time)) watch_set_indicator(WATCH_INDICATOR_PM); - else watch_clear_indicator(WATCH_INDICATOR_PM); - } else if (settings->bit.clock_24h_leading_zero && scratch_time.unit.hour < 10) { - set_leading_zero = true; - } - sprintf(buf, "SE%2d%2d%02d%s", scratch_time.unit.day, scratch_time.unit.hour, scratch_time.unit.minute, longLatPresets[state->longLatToUse].name); - watch_display_string(buf, 0); - if (set_leading_zero) - watch_display_string("0", 4); - return; - } else { - show_next_match = true; - } - } + // Sort the array of events + qsort(events, n, sizeof(SolarEvent), compare); - // it's after sunset. we need to display sunrise/sunset for tomorrow. - uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); - timestamp += 86400; - scratch_time = watch_utility_date_time_from_unix_time(timestamp, 0); + switch (state->rise_index) { + case 0: + display_time(events[0].event, events[0].abreviation, settings, &date_time, state); + break; + case 1: + display_time(events[1].event, events[1].abreviation, settings, &date_time, state); + break; + case 2: + display_time(events[2].event, events[2].abreviation, settings, &date_time, state); + break; + case 3: + display_time(events[3].event, events[3].abreviation, settings, &date_time, state); + break; + default: + break; } + } -static int16_t _sunrise_sunset_face_latlon_from_struct(sunrise_sunset_lat_lon_settings_t val) { +static int16_t sunrise_sunset_face_latlon_from_struct(sunrise_sunset_lat_lon_settings_t val) { int16_t retval = (val.sign ? -1 : 1) * ( val.hundreds * 10000 + @@ -181,7 +241,7 @@ static int16_t _sunrise_sunset_face_latlon_from_struct(sunrise_sunset_lat_lon_se return retval; } -static sunrise_sunset_lat_lon_settings_t _sunrise_sunset_face_struct_from_latlon(int16_t val) { +static sunrise_sunset_lat_lon_settings_t sunrise_sunset_face_struct_from_latlon(int16_t val) { sunrise_sunset_lat_lon_settings_t retval; retval.sign = val < 0; @@ -199,11 +259,11 @@ static sunrise_sunset_lat_lon_settings_t _sunrise_sunset_face_struct_from_latlon return retval; } -static void _sunrise_sunset_face_update_location_register(sunrise_sunset_state_t *state) { +static void sunrise_sunset_face_update_location_register(sunrise_sunset_state_t *state) { if (state->location_changed) { movement_location_t movement_location; - int16_t lat = _sunrise_sunset_face_latlon_from_struct(state->working_latitude); - int16_t lon = _sunrise_sunset_face_latlon_from_struct(state->working_longitude); + int16_t lat = sunrise_sunset_face_latlon_from_struct(state->working_latitude); + int16_t lon = sunrise_sunset_face_latlon_from_struct(state->working_longitude); movement_location.bit.latitude = lat; movement_location.bit.longitude = lon; watch_store_backup_data(movement_location.reg, 1); @@ -211,17 +271,17 @@ static void _sunrise_sunset_face_update_location_register(sunrise_sunset_state_t } } -static void _sunrise_sunset_face_update_settings_display(movement_event_t event, sunrise_sunset_state_t *state) { +static void sunrise_sunset_face_update_settings_display(movement_event_t event, sunrise_sunset_state_t *state) { char buf[12]; switch (state->page) { case 0: return; case 1: - sprintf(buf, "LA %c %04d", state->working_latitude.sign ? '-' : '+', abs(_sunrise_sunset_face_latlon_from_struct(state->working_latitude))); + sprintf(buf, "LA %c %04d", state->working_latitude.sign ? '-' : '+', abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude))); break; case 2: - sprintf(buf, "LO %c%05d", state->working_longitude.sign ? '-' : '+', abs(_sunrise_sunset_face_latlon_from_struct(state->working_longitude))); + sprintf(buf, "LO %c%05d", state->working_longitude.sign ? '-' : '+', abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude))); break; } if (event.subsecond % 2) { @@ -230,7 +290,7 @@ static void _sunrise_sunset_face_update_settings_display(movement_event_t event, watch_display_string(buf, 0); } -static void _sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { +static void sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { state->location_changed = true; switch (state->page) { case 1: // latitude @@ -243,7 +303,7 @@ static void _sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { break; case 2: state->working_latitude.tens = (state->working_latitude.tens + 1) % 10; - if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) { + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) { // prevent latitude from going over ±90. // TODO: perform these checks when advancing the digit? state->working_latitude.ones = 0; @@ -253,15 +313,15 @@ static void _sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { break; case 3: state->working_latitude.ones = (state->working_latitude.ones + 1) % 10; - if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.ones = 0; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.ones = 0; break; case 4: state->working_latitude.tenths = (state->working_latitude.tenths + 1) % 10; - if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.tenths = 0; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.tenths = 0; break; case 5: state->working_latitude.hundredths = (state->working_latitude.hundredths + 1) % 10; - if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.hundredths = 0; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.hundredths = 0; break; } break; @@ -272,7 +332,7 @@ static void _sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { break; case 1: state->working_longitude.hundreds = (state->working_longitude.hundreds + 1) % 10; - if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) { + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) { // prevent longitude from going over ±180 state->working_longitude.tens = 8; state->working_longitude.ones = 0; @@ -282,19 +342,19 @@ static void _sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { break; case 2: state->working_longitude.tens = (state->working_longitude.tens + 1) % 10; - if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tens = 0; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tens = 0; break; case 3: state->working_longitude.ones = (state->working_longitude.ones + 1) % 10; - if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.ones = 0; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.ones = 0; break; case 4: state->working_longitude.tenths = (state->working_longitude.tenths + 1) % 10; - if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tenths = 0; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tenths = 0; break; case 5: state->working_longitude.hundredths = (state->working_longitude.hundredths + 1) % 10; - if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.hundredths = 0; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.hundredths = 0; break; } break; @@ -332,8 +392,8 @@ void sunrise_sunset_face_activate(movement_settings_t *settings, void *context) sunrise_sunset_state_t *state = (sunrise_sunset_state_t *)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->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); } bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { @@ -341,22 +401,15 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti switch (event.event_type) { case EVENT_ACTIVATE: - _sunrise_sunset_face_update(settings, state); + sunrise_sunset_face_update(settings, state); break; case EVENT_LOW_ENERGY_UPDATE: case EVENT_TICK: if (state->page == 0) { // if entering low energy mode, start tick animation if (event.event_type == EVENT_LOW_ENERGY_UPDATE && !watch_tick_animation_is_running()) watch_start_tick_animation(1000); - // check if we need to update the display - watch_date_time date_time = watch_rtc_get_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; - _sunrise_sunset_face_update(settings, state); - } - } else { - _sunrise_sunset_face_update_settings_display(event, state); + } else { + sunrise_sunset_face_update_settings_display(event, state); } break; case EVENT_LIGHT_BUTTON_DOWN: @@ -366,15 +419,15 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti if (state->active_digit > 5) { state->active_digit = 0; state->page = (state->page + 1) % 3; - _sunrise_sunset_face_update_location_register(state); + sunrise_sunset_face_update_location_register(state); } - _sunrise_sunset_face_update_settings_display(event, context); + sunrise_sunset_face_update_settings_display(event, context); } else if (_location_count <= 1) { movement_illuminate_led(); } if (state->page == 0) { movement_request_tick_frequency(1); - _sunrise_sunset_face_update(settings, state); + sunrise_sunset_face_update(settings, state); } break; case EVENT_LIGHT_LONG_PRESS: @@ -384,36 +437,36 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti case EVENT_LIGHT_BUTTON_UP: if (state->page == 0 && _location_count > 1) { state->longLatToUse = (state->longLatToUse + 1) % _location_count; - _sunrise_sunset_face_update(settings, state); + sunrise_sunset_face_update(settings, state); } break; case EVENT_ALARM_BUTTON_UP: if (state->page) { - _sunrise_sunset_face_advance_digit(state); - _sunrise_sunset_face_update_settings_display(event, context); + sunrise_sunset_face_advance_digit(state); + sunrise_sunset_face_update_settings_display(event, context); } else { - state->rise_index = (state->rise_index + 1) % 2; - _sunrise_sunset_face_update(settings, state); + state->rise_index = (state->rise_index + 1) % 4; + sunrise_sunset_face_update(settings, state); } break; case EVENT_ALARM_LONG_PRESS: if (state->page == 0) { if (state->longLatToUse != 0) { state->longLatToUse = 0; - _sunrise_sunset_face_update(settings, state); + sunrise_sunset_face_update(settings, state); break; } state->page++; state->active_digit = 0; watch_clear_display(); movement_request_tick_frequency(4); - _sunrise_sunset_face_update_settings_display(event, context); + sunrise_sunset_face_update_settings_display(event, context); } else { state->active_digit = 0; state->page = 0; - _sunrise_sunset_face_update_location_register(state); - _sunrise_sunset_face_update(settings, state); + sunrise_sunset_face_update_location_register(state); + sunrise_sunset_face_update(settings, state); } break; case EVENT_TIMEOUT: @@ -425,7 +478,7 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti state->page = 0; state->rise_index = 0; movement_request_tick_frequency(1); - _sunrise_sunset_face_update(settings, state); + sunrise_sunset_face_update(settings, state); } break; default: @@ -441,5 +494,5 @@ void sunrise_sunset_face_resign(movement_settings_t *settings, void *context) { state->page = 0; state->active_digit = 0; state->rise_index = 0; - _sunrise_sunset_face_update_location_register(state); + sunrise_sunset_face_update_location_register(state); } diff --git a/movement/watch_faces/complication/sunrise_sunset_face.h b/movement/watch_faces/complication/sunrise_sunset_face.h index df5fda5c1..814d47fcc 100644 --- a/movement/watch_faces/complication/sunrise_sunset_face.h +++ b/movement/watch_faces/complication/sunrise_sunset_face.h @@ -58,6 +58,13 @@ typedef struct { uint8_t longLatToUse; } sunrise_sunset_state_t; +typedef struct { + int timestamp; + watch_date_time *event; + const char *name; + const char *abreviation; +} SolarEvent; + void sunrise_sunset_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); void sunrise_sunset_face_activate(movement_settings_t *settings, void *context); bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *settings, void *context); @@ -80,6 +87,7 @@ typedef struct { static const long_lat_presets_t longLatPresets[] = { { .name = " "}, // Default, the long and lat get replaced by what's set in the watch + { .name = "dc", .latitude = 3883, .longitude = -7711 }, // Alexandria, VA // { .name = "Ny", .latitude = 4072, .longitude = -7401 }, // New York City, NY // { .name = "LA", .latitude = 3405, .longitude = -11824 }, // Los Angeles, CA // { .name = "dE", .latitude = 4221, .longitude = -8305 }, // Detroit, MI From 3d41a59eaa7d9400c54f75f4670eb2315db8c144 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Wed, 16 Oct 2024 15:46:59 -0400 Subject: [PATCH 02/10] new face (not replacing sunrise_sunset_face) --- movement/make/Makefile | 1 + movement/movement_faces.h | 1 + .../complication/sunrise_sunset_alt_face.c | 498 ++++++++++++++++++ .../complication/sunrise_sunset_alt_face.h | 96 ++++ 4 files changed, 596 insertions(+) create mode 100644 movement/watch_faces/complication/sunrise_sunset_alt_face.c create mode 100644 movement/watch_faces/complication/sunrise_sunset_alt_face.h diff --git a/movement/make/Makefile b/movement/make/Makefile index 2116ebaba..d787fb288 100644 --- a/movement/make/Makefile +++ b/movement/make/Makefile @@ -149,6 +149,7 @@ SRCS += \ ../watch_faces/sensor/accel_interrupt_count_face.c \ ../watch_faces/complication/metronome_face.c \ ../watch_faces/complication/smallchess_face.c \ + ../watch_faces/complication/sunrise_sunset_alt_face.c \ # New watch faces go above this line. # Leave this line at the bottom of the file; it has all the targets for making your project. diff --git a/movement/movement_faces.h b/movement/movement_faces.h index 630f264aa..d4069e864 100644 --- a/movement/movement_faces.h +++ b/movement/movement_faces.h @@ -123,6 +123,7 @@ #include "accel_interrupt_count_face.h" #include "metronome_face.h" #include "smallchess_face.h" +#include "sunrise_sunset_alt_face.h" // New includes go above this line. #endif // MOVEMENT_FACES_H_ diff --git a/movement/watch_faces/complication/sunrise_sunset_alt_face.c b/movement/watch_faces/complication/sunrise_sunset_alt_face.c new file mode 100644 index 000000000..c04cd7747 --- /dev/null +++ b/movement/watch_faces/complication/sunrise_sunset_alt_face.c @@ -0,0 +1,498 @@ +/* + * MIT License + * + * Copyright (c) 2022 Joey Castillo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Sunrise/sunset calculations are public domain code by Paul Schlyter, December 1992 + * + */ + +#include +#include +#include +#include "sunrise_sunset_face.h" +#include "watch.h" +#include "watch_utility.h" +#include "sunriset.h" + +#if __EMSCRIPTEN__ +#include +#endif + +static const uint8_t _location_count = sizeof(longLatPresets) / sizeof(long_lat_presets_t); + +static int compare(const void *a, const void *b) { + SolarEvent *eventA = (SolarEvent *)a; + SolarEvent *eventB = (SolarEvent *)b; + + return (eventA->timestamp - eventB->timestamp); +} + +static void set_sunriset(double time_value, watch_date_time *time_unit) { + // Calculate minutes and seconds + float minutes = 60.0 * fmod(time_value, 1); + float seconds = 60.0 * fmod(minutes, 1); + + // Set hour and minute + time_unit->unit.hour = floor(time_value); + if (seconds < 30) { + time_unit->unit.minute = floor(minutes); + } else { + time_unit->unit.minute = ceil(minutes); + } + + // Handle edge case where minutes equal 60 + if (time_unit->unit.minute == 60) { + time_unit->unit.minute = 0; + time_unit->unit.hour = (time_unit->unit.hour + 1) % 24; + } +} + +static void display_time(watch_date_time *time, const char *prefix, movement_settings_t *settings, watch_date_time *date_time, sunrise_sunset_state_t *state) { + bool set_leading_zero = false; + char buf[32]; // Adjust size as needed + + // Handle 12-hour mode and PM indicator + if (!settings->bit.clock_mode_24h) { + if (watch_utility_convert_to_12_hour(time)) { + watch_set_indicator(WATCH_INDICATOR_PM); + } else { + watch_clear_indicator(WATCH_INDICATOR_PM); + } + } + // Handle 24-hour mode with leading zero + else if (settings->bit.clock_24h_leading_zero && time->unit.hour < 10) { + set_leading_zero = true; + } + + // Format and display time + sprintf(buf, "%s%2d%2d%02d%s", prefix, time->unit.day, time->unit.hour, time->unit.minute, longLatPresets[state->longLatToUse].name); + watch_display_string(buf, 0); + + // Display leading zero if needed + if (set_leading_zero) { + watch_display_string("0", 4); + } +} + +static void sunrise_sunset_face_update(movement_settings_t *settings, sunrise_sunset_state_t *state) { + char buf[14]; + double civ_start, rise, set, civ_end; + movement_location_t movement_location; + if (state->longLatToUse == 0 || _location_count <= 1) + movement_location = (movement_location_t) watch_get_backup_data(1); + else{ + movement_location.bit.latitude = longLatPresets[state->longLatToUse].latitude; + movement_location.bit.longitude = longLatPresets[state->longLatToUse].longitude; + } + + if (movement_location.reg == 0) { + watch_clear_colon(); + watch_clear_indicator(WATCH_INDICATOR_PM); + watch_display_string("RI no Loc", 0); + return; + } + + 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 scratch_time; // scratchpad, contains different values at different times + watch_date_time civ_start_time; + watch_date_time rise_time; + watch_date_time set_time; + watch_date_time civ_end_time; + scratch_time.reg = utc_now.reg; + civ_start_time.reg = utc_now.reg; + rise_time.reg = utc_now.reg; + set_time.reg = utc_now.reg; + civ_end_time.reg = utc_now.reg; + + // Weird quirky unsigned things were happening when I tried to cast these directly to doubles below. + // it looks redundant, but extracting them to local int16's seemed to fix it. + int16_t lat_centi = (int16_t)movement_location.bit.latitude; + int16_t lon_centi = (int16_t)movement_location.bit.longitude; + + double lat = (double)lat_centi / 100.0; + double lon = (double)lon_centi / 100.0; + + // 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; + + // we loop twice because if it's after sunset today, we need to recalculate to display values for tomorrow. + uint8_t result = sun_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &rise, &set); + + if (result != 0) { + watch_clear_colon(); + watch_clear_indicator(WATCH_INDICATOR_PM); + watch_clear_indicator(WATCH_INDICATOR_24H); + sprintf(buf, "%s%2d none ", (result == 1) ? "SE" : "rI", scratch_time.unit.day); + watch_display_string(buf, 0); + return; + } + civil_twilight(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &civ_start, &civ_end); + + watch_set_colon(); + if (settings->bit.clock_mode_24h && !settings->bit.clock_24h_leading_zero) watch_set_indicator(WATCH_INDICATOR_24H); + + rise += hours_from_utc; + set += hours_from_utc; + civ_start += hours_from_utc; + civ_end += hours_from_utc; + + set_sunriset(civ_start, &civ_start_time); + if (date_time.reg > civ_start_time.reg) { + // it's after sunset. we need to display sunrise/sunset for tomorrow. + uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); + timestamp += 86400; + civ_start_time = watch_utility_date_time_from_unix_time(timestamp, 0); + set_sunriset(civ_start, &civ_start_time); + } + //display_time(&civ_start_time, "CI", settings, &date_time, state); + + set_sunriset(rise, &rise_time); + if (date_time.reg > rise_time.reg) { + // it's after sunset. we need to display sunrise/sunset for tomorrow. + uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); + timestamp += 86400; + rise_time = watch_utility_date_time_from_unix_time(timestamp, 0); + set_sunriset(rise, &rise_time); + } + //display_time(&rise_time, "rI", settings, &date_time, state); + + set_sunriset(set, &set_time); + if (date_time.reg > set_time.reg) { + // it's after sunset. we need to display sunrise/sunset for tomorrow. + uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); + timestamp += 86400; + set_time = watch_utility_date_time_from_unix_time(timestamp, 0); + set_sunriset(set, &set_time); + } + //display_time(&set_time, "SE", settings, &date_time, state); + + set_sunriset(civ_end, &civ_end_time); + if (date_time.reg > civ_end_time.reg) { + // it's after sunset. we need to display sunrise/sunset for tomorrow. + uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); + timestamp += 86400; + civ_end_time = watch_utility_date_time_from_unix_time(timestamp, 0); + set_sunriset(civ_end, &civ_end_time); + } + //display_time(&civ_end_time, "SE", settings, &date_time, state); + + SolarEvent events[] = { + {civ_start_time.reg, &civ_start_time, "civ_start_time", "cI"}, + {rise_time.reg, &rise_time, "rise_time", "rI"}, + {set_time.reg, &set_time, "set_time", "SE"}, + {civ_end_time.reg, &civ_end_time, "civ_end_time", "cI"} + }; + + int n = sizeof(events) / sizeof(events[0]); + + // Sort the array of events + qsort(events, n, sizeof(SolarEvent), compare); + + switch (state->rise_index) { + case 0: + display_time(events[0].event, events[0].abreviation, settings, &date_time, state); + break; + case 1: + display_time(events[1].event, events[1].abreviation, settings, &date_time, state); + break; + case 2: + display_time(events[2].event, events[2].abreviation, settings, &date_time, state); + break; + case 3: + display_time(events[3].event, events[3].abreviation, settings, &date_time, state); + break; + default: + break; + } + +} + +static int16_t sunrise_sunset_face_latlon_from_struct(sunrise_sunset_lat_lon_settings_t val) { + int16_t retval = (val.sign ? -1 : 1) * + ( + val.hundreds * 10000 + + val.tens * 1000 + + val.ones * 100 + + val.tenths * 10 + + val.hundredths + ); + return retval; +} + +static sunrise_sunset_lat_lon_settings_t sunrise_sunset_face_struct_from_latlon(int16_t val) { + sunrise_sunset_lat_lon_settings_t retval; + + retval.sign = val < 0; + val = abs(val); + retval.hundredths = val % 10; + val /= 10; + retval.tenths = val % 10; + val /= 10; + retval.ones = val % 10; + val /= 10; + retval.tens = val % 10; + val /= 10; + retval.hundreds = val % 10; + + return retval; +} + +static void sunrise_sunset_face_update_location_register(sunrise_sunset_state_t *state) { + if (state->location_changed) { + movement_location_t movement_location; + int16_t lat = sunrise_sunset_face_latlon_from_struct(state->working_latitude); + int16_t lon = sunrise_sunset_face_latlon_from_struct(state->working_longitude); + movement_location.bit.latitude = lat; + movement_location.bit.longitude = lon; + watch_store_backup_data(movement_location.reg, 1); + state->location_changed = false; + } +} + +static void sunrise_sunset_face_update_settings_display(movement_event_t event, sunrise_sunset_state_t *state) { + char buf[12]; + + switch (state->page) { + case 0: + return; + case 1: + sprintf(buf, "LA %c %04d", state->working_latitude.sign ? '-' : '+', abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude))); + break; + case 2: + sprintf(buf, "LO %c%05d", state->working_longitude.sign ? '-' : '+', abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude))); + break; + } + if (event.subsecond % 2) { + buf[state->active_digit + 4] = ' '; + } + watch_display_string(buf, 0); +} + +static void sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { + state->location_changed = true; + switch (state->page) { + case 1: // latitude + switch (state->active_digit) { + case 0: + state->working_latitude.sign++; + break; + case 1: + // we skip this digit + break; + case 2: + state->working_latitude.tens = (state->working_latitude.tens + 1) % 10; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) { + // prevent latitude from going over ±90. + // TODO: perform these checks when advancing the digit? + state->working_latitude.ones = 0; + state->working_latitude.tenths = 0; + state->working_latitude.hundredths = 0; + } + break; + case 3: + state->working_latitude.ones = (state->working_latitude.ones + 1) % 10; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.ones = 0; + break; + case 4: + state->working_latitude.tenths = (state->working_latitude.tenths + 1) % 10; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.tenths = 0; + break; + case 5: + state->working_latitude.hundredths = (state->working_latitude.hundredths + 1) % 10; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.hundredths = 0; + break; + } + break; + case 2: // longitude + switch (state->active_digit) { + case 0: + state->working_longitude.sign++; + break; + case 1: + state->working_longitude.hundreds = (state->working_longitude.hundreds + 1) % 10; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) { + // prevent longitude from going over ±180 + state->working_longitude.tens = 8; + state->working_longitude.ones = 0; + state->working_longitude.tenths = 0; + state->working_longitude.hundredths = 0; + } + break; + case 2: + state->working_longitude.tens = (state->working_longitude.tens + 1) % 10; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tens = 0; + break; + case 3: + state->working_longitude.ones = (state->working_longitude.ones + 1) % 10; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.ones = 0; + break; + case 4: + state->working_longitude.tenths = (state->working_longitude.tenths + 1) % 10; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tenths = 0; + break; + case 5: + state->working_longitude.hundredths = (state->working_longitude.hundredths + 1) % 10; + if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.hundredths = 0; + break; + } + break; + } +} + +void sunrise_sunset_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) { + (void) settings; + (void) watch_face_index; + if (*context_ptr == NULL) { + *context_ptr = malloc(sizeof(sunrise_sunset_state_t)); + memset(*context_ptr, 0, sizeof(sunrise_sunset_state_t)); + } +} + +void sunrise_sunset_face_activate(movement_settings_t *settings, void *context) { + (void) settings; + if (watch_tick_animation_is_running()) watch_stop_tick_animation(); + +#if __EMSCRIPTEN__ + int16_t browser_lat = EM_ASM_INT({ + return lat; + }); + int16_t browser_lon = EM_ASM_INT({ + return lon; + }); + if ((watch_get_backup_data(1) == 0) && (browser_lat || browser_lon)) { + movement_location_t browser_loc; + browser_loc.bit.latitude = browser_lat; + browser_loc.bit.longitude = browser_lon; + watch_store_backup_data(browser_loc.reg, 1); + } +#endif + + + sunrise_sunset_state_t *state = (sunrise_sunset_state_t *)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); +} + +bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + sunrise_sunset_state_t *state = (sunrise_sunset_state_t *)context; + + switch (event.event_type) { + case EVENT_ACTIVATE: + sunrise_sunset_face_update(settings, state); + break; + case EVENT_LOW_ENERGY_UPDATE: + case EVENT_TICK: + if (state->page == 0) { + // if entering low energy mode, start tick animation + if (event.event_type == EVENT_LOW_ENERGY_UPDATE && !watch_tick_animation_is_running()) watch_start_tick_animation(1000); + } else { + sunrise_sunset_face_update_settings_display(event, state); + } + break; + case EVENT_LIGHT_BUTTON_DOWN: + if (state->page) { + state->active_digit++; + if (state->page == 1 && state->active_digit == 1) state->active_digit++; // max latitude is +- 90, no hundreds place + if (state->active_digit > 5) { + state->active_digit = 0; + state->page = (state->page + 1) % 3; + sunrise_sunset_face_update_location_register(state); + } + sunrise_sunset_face_update_settings_display(event, context); + } else if (_location_count <= 1) { + movement_illuminate_led(); + } + if (state->page == 0) { + movement_request_tick_frequency(1); + sunrise_sunset_face_update(settings, state); + } + break; + case EVENT_LIGHT_LONG_PRESS: + if (_location_count <= 1) break; + else if (!state->page) movement_illuminate_led(); + break; + case EVENT_LIGHT_BUTTON_UP: + if (state->page == 0 && _location_count > 1) { + state->longLatToUse = (state->longLatToUse + 1) % _location_count; + sunrise_sunset_face_update(settings, state); + } + break; + case EVENT_ALARM_BUTTON_UP: + if (state->page) { + sunrise_sunset_face_advance_digit(state); + sunrise_sunset_face_update_settings_display(event, context); + } else { + state->rise_index = (state->rise_index + 1) % 4; + sunrise_sunset_face_update(settings, state); + } + break; + case EVENT_ALARM_LONG_PRESS: + if (state->page == 0) { + if (state->longLatToUse != 0) { + state->longLatToUse = 0; + sunrise_sunset_face_update(settings, state); + break; + } + state->page++; + state->active_digit = 0; + watch_clear_display(); + movement_request_tick_frequency(4); + sunrise_sunset_face_update_settings_display(event, context); + } + else { + state->active_digit = 0; + state->page = 0; + sunrise_sunset_face_update_location_register(state); + sunrise_sunset_face_update(settings, state); + } + break; + case EVENT_TIMEOUT: + if (watch_get_backup_data(1) == 0) { + // if no location set, return home + movement_move_to_face(0); + } else if (state->page || state->rise_index) { + // otherwise on timeout, exit settings mode and return to the next sunrise or sunset + state->page = 0; + state->rise_index = 0; + movement_request_tick_frequency(1); + sunrise_sunset_face_update(settings, state); + } + break; + default: + return movement_default_loop_handler(event, settings); + } + + return true; +} + +void sunrise_sunset_face_resign(movement_settings_t *settings, void *context) { + (void) settings; + sunrise_sunset_state_t *state = (sunrise_sunset_state_t *)context; + state->page = 0; + state->active_digit = 0; + state->rise_index = 0; + sunrise_sunset_face_update_location_register(state); +} diff --git a/movement/watch_faces/complication/sunrise_sunset_alt_face.h b/movement/watch_faces/complication/sunrise_sunset_alt_face.h new file mode 100644 index 000000000..814d47fcc --- /dev/null +++ b/movement/watch_faces/complication/sunrise_sunset_alt_face.h @@ -0,0 +1,96 @@ +/* + * MIT License + * + * Copyright (c) 2022 Joey Castillo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef SUNRISE_SUNSET_FACE_H_ +#define SUNRISE_SUNSET_FACE_H_ + +/* + * SUNRISE & SUNSET FACE + * + * The Sunrise/Sunset face is designed to display the next sunrise or sunset + * for a given location. It also functions as an interface for setting the + * location register, which other watch faces can use for various purposes. + * + * Refer to the wiki for usage instructions: + * https://www.sensorwatch.net/docs/watchfaces/complication/#sunrisesunset + */ + +#include "movement.h" + +typedef struct { + uint8_t sign: 1; // 0-1 + uint8_t hundreds: 1; // 0-1, ignored for latitude + uint8_t tens: 4; // 0-9 (must wrap at 10) + uint8_t ones: 4; // 0-9 (must wrap at 10) + uint8_t tenths: 4; // 0-9 (must wrap at 10) + uint8_t hundredths: 4; // 0-9 (must wrap at 10) +} sunrise_sunset_lat_lon_settings_t; + +typedef struct { + uint8_t page; + uint8_t rise_index; + uint8_t active_digit; + bool location_changed; + watch_date_time rise_set_expires; + sunrise_sunset_lat_lon_settings_t working_latitude; + sunrise_sunset_lat_lon_settings_t working_longitude; + uint8_t longLatToUse; +} sunrise_sunset_state_t; + +typedef struct { + int timestamp; + watch_date_time *event; + const char *name; + const char *abreviation; +} SolarEvent; + +void sunrise_sunset_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void sunrise_sunset_face_activate(movement_settings_t *settings, void *context); +bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void sunrise_sunset_face_resign(movement_settings_t *settings, void *context); + +#define sunrise_sunset_face ((const watch_face_t){ \ + sunrise_sunset_face_setup, \ + sunrise_sunset_face_activate, \ + sunrise_sunset_face_loop, \ + sunrise_sunset_face_resign, \ + NULL, \ +}) + +typedef struct { + char name[2]; + int16_t latitude; + int16_t longitude; +} long_lat_presets_t; + +static const long_lat_presets_t longLatPresets[] = +{ + { .name = " "}, // Default, the long and lat get replaced by what's set in the watch + { .name = "dc", .latitude = 3883, .longitude = -7711 }, // Alexandria, VA +// { .name = "Ny", .latitude = 4072, .longitude = -7401 }, // New York City, NY +// { .name = "LA", .latitude = 3405, .longitude = -11824 }, // Los Angeles, CA +// { .name = "dE", .latitude = 4221, .longitude = -8305 }, // Detroit, MI +}; + +#endif // SUNRISE_SUNSET_FACE_H_ From 4335ec6c95ff0e7d1068382da3d2e5e0cabf1fc4 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Wed, 16 Oct 2024 15:49:26 -0400 Subject: [PATCH 03/10] original sunrise_sunset_face.h --- movement/watch_faces/complication/sunrise_sunset_face.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/movement/watch_faces/complication/sunrise_sunset_face.h b/movement/watch_faces/complication/sunrise_sunset_face.h index 814d47fcc..df5fda5c1 100644 --- a/movement/watch_faces/complication/sunrise_sunset_face.h +++ b/movement/watch_faces/complication/sunrise_sunset_face.h @@ -58,13 +58,6 @@ typedef struct { uint8_t longLatToUse; } sunrise_sunset_state_t; -typedef struct { - int timestamp; - watch_date_time *event; - const char *name; - const char *abreviation; -} SolarEvent; - void sunrise_sunset_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); void sunrise_sunset_face_activate(movement_settings_t *settings, void *context); bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *settings, void *context); @@ -87,7 +80,6 @@ typedef struct { static const long_lat_presets_t longLatPresets[] = { { .name = " "}, // Default, the long and lat get replaced by what's set in the watch - { .name = "dc", .latitude = 3883, .longitude = -7711 }, // Alexandria, VA // { .name = "Ny", .latitude = 4072, .longitude = -7401 }, // New York City, NY // { .name = "LA", .latitude = 3405, .longitude = -11824 }, // Los Angeles, CA // { .name = "dE", .latitude = 4221, .longitude = -8305 }, // Detroit, MI From d8c9a5f138a83a7738b604a147e9f0e864bd8a4f Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Wed, 16 Oct 2024 15:51:08 -0400 Subject: [PATCH 04/10] and original sunrise_sunset_face.c --- .../complication/sunrise_sunset_face.c | 305 ++++++++---------- 1 file changed, 126 insertions(+), 179 deletions(-) diff --git a/movement/watch_faces/complication/sunrise_sunset_face.c b/movement/watch_faces/complication/sunrise_sunset_face.c index c04cd7747..8747bd868 100644 --- a/movement/watch_faces/complication/sunrise_sunset_face.c +++ b/movement/watch_faces/complication/sunrise_sunset_face.c @@ -39,63 +39,15 @@ static const uint8_t _location_count = sizeof(longLatPresets) / sizeof(long_lat_presets_t); -static int compare(const void *a, const void *b) { - SolarEvent *eventA = (SolarEvent *)a; - SolarEvent *eventB = (SolarEvent *)b; - - return (eventA->timestamp - eventB->timestamp); -} - -static void set_sunriset(double time_value, watch_date_time *time_unit) { - // Calculate minutes and seconds - float minutes = 60.0 * fmod(time_value, 1); - float seconds = 60.0 * fmod(minutes, 1); - - // Set hour and minute - time_unit->unit.hour = floor(time_value); - if (seconds < 30) { - time_unit->unit.minute = floor(minutes); - } else { - time_unit->unit.minute = ceil(minutes); - } - - // Handle edge case where minutes equal 60 - if (time_unit->unit.minute == 60) { - time_unit->unit.minute = 0; - time_unit->unit.hour = (time_unit->unit.hour + 1) % 24; - } -} - -static void display_time(watch_date_time *time, const char *prefix, movement_settings_t *settings, watch_date_time *date_time, sunrise_sunset_state_t *state) { - bool set_leading_zero = false; - char buf[32]; // Adjust size as needed - - // Handle 12-hour mode and PM indicator - if (!settings->bit.clock_mode_24h) { - if (watch_utility_convert_to_12_hour(time)) { - watch_set_indicator(WATCH_INDICATOR_PM); - } else { - watch_clear_indicator(WATCH_INDICATOR_PM); - } - } - // Handle 24-hour mode with leading zero - else if (settings->bit.clock_24h_leading_zero && time->unit.hour < 10) { - set_leading_zero = true; - } - - // Format and display time - sprintf(buf, "%s%2d%2d%02d%s", prefix, time->unit.day, time->unit.hour, time->unit.minute, longLatPresets[state->longLatToUse].name); - watch_display_string(buf, 0); - - // Display leading zero if needed - if (set_leading_zero) { - watch_display_string("0", 4); - } +static void _sunrise_sunset_set_expiration(sunrise_sunset_state_t *state, watch_date_time next_rise_set) { + uint32_t timestamp = watch_utility_date_time_to_unix_time(next_rise_set, 0); + state->rise_set_expires = watch_utility_date_time_from_unix_time(timestamp + 60, 0); } -static void sunrise_sunset_face_update(movement_settings_t *settings, sunrise_sunset_state_t *state) { +static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_sunset_state_t *state) { char buf[14]; - double civ_start, rise, set, civ_end; + double rise, set, minutes, seconds; + bool show_next_match = false; movement_location_t movement_location; if (state->longLatToUse == 0 || _location_count <= 1) movement_location = (movement_location_t) watch_get_backup_data(1); @@ -105,8 +57,6 @@ static void sunrise_sunset_face_update(movement_settings_t *settings, sunrise_su } if (movement_location.reg == 0) { - watch_clear_colon(); - watch_clear_indicator(WATCH_INDICATOR_PM); watch_display_string("RI no Loc", 0); return; } @@ -114,15 +64,7 @@ static void sunrise_sunset_face_update(movement_settings_t *settings, sunrise_su 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 scratch_time; // scratchpad, contains different values at different times - watch_date_time civ_start_time; - watch_date_time rise_time; - watch_date_time set_time; - watch_date_time civ_end_time; scratch_time.reg = utc_now.reg; - civ_start_time.reg = utc_now.reg; - rise_time.reg = utc_now.reg; - set_time.reg = utc_now.reg; - civ_end_time.reg = utc_now.reg; // Weird quirky unsigned things were happening when I tried to cast these directly to doubles below. // it looks redundant, but extracting them to local int16's seemed to fix it. @@ -138,98 +80,96 @@ static void sunrise_sunset_face_update(movement_settings_t *settings, sunrise_su double hours_from_utc = ((double)movement_timezone_offsets[settings->bit.time_zone]) / 60.0; // we loop twice because if it's after sunset today, we need to recalculate to display values for tomorrow. - uint8_t result = sun_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &rise, &set); - - if (result != 0) { - watch_clear_colon(); - watch_clear_indicator(WATCH_INDICATOR_PM); - watch_clear_indicator(WATCH_INDICATOR_24H); - sprintf(buf, "%s%2d none ", (result == 1) ? "SE" : "rI", scratch_time.unit.day); - watch_display_string(buf, 0); - return; - } - civil_twilight(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &civ_start, &civ_end); + for(int i = 0; i < 2; i++) { + uint8_t result = sun_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &rise, &set); - watch_set_colon(); - if (settings->bit.clock_mode_24h && !settings->bit.clock_24h_leading_zero) watch_set_indicator(WATCH_INDICATOR_24H); + if (result != 0) { + watch_clear_colon(); + watch_clear_indicator(WATCH_INDICATOR_PM); + watch_clear_indicator(WATCH_INDICATOR_24H); + sprintf(buf, "%s%2d none ", (result == 1) ? "SE" : "rI", scratch_time.unit.day); + watch_display_string(buf, 0); + return; + } - rise += hours_from_utc; - set += hours_from_utc; - civ_start += hours_from_utc; - civ_end += hours_from_utc; + watch_set_colon(); + if (settings->bit.clock_mode_24h && !settings->bit.clock_24h_leading_zero) watch_set_indicator(WATCH_INDICATOR_24H); - set_sunriset(civ_start, &civ_start_time); - if (date_time.reg > civ_start_time.reg) { - // it's after sunset. we need to display sunrise/sunset for tomorrow. - uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); - timestamp += 86400; - civ_start_time = watch_utility_date_time_from_unix_time(timestamp, 0); - set_sunriset(civ_start, &civ_start_time); - } - //display_time(&civ_start_time, "CI", settings, &date_time, state); + rise += hours_from_utc; + set += hours_from_utc; - set_sunriset(rise, &rise_time); - if (date_time.reg > rise_time.reg) { - // it's after sunset. we need to display sunrise/sunset for tomorrow. - uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); - timestamp += 86400; - rise_time = watch_utility_date_time_from_unix_time(timestamp, 0); - set_sunriset(rise, &rise_time); - } - //display_time(&rise_time, "rI", settings, &date_time, state); + minutes = 60.0 * fmod(rise, 1); + seconds = 60.0 * fmod(minutes, 1); + scratch_time.unit.hour = floor(rise); + if (seconds < 30) scratch_time.unit.minute = floor(minutes); + else scratch_time.unit.minute = ceil(minutes); - set_sunriset(set, &set_time); - if (date_time.reg > set_time.reg) { - // it's after sunset. we need to display sunrise/sunset for tomorrow. - uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); - timestamp += 86400; - set_time = watch_utility_date_time_from_unix_time(timestamp, 0); - set_sunriset(set, &set_time); - } - //display_time(&set_time, "SE", settings, &date_time, state); + if (scratch_time.unit.minute == 60) { + scratch_time.unit.minute = 0; + scratch_time.unit.hour = (scratch_time.unit.hour + 1) % 24; + } - set_sunriset(civ_end, &civ_end_time); - if (date_time.reg > civ_end_time.reg) { - // it's after sunset. we need to display sunrise/sunset for tomorrow. - uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); - timestamp += 86400; - civ_end_time = watch_utility_date_time_from_unix_time(timestamp, 0); - set_sunriset(civ_end, &civ_end_time); - } - //display_time(&civ_end_time, "SE", settings, &date_time, state); + if (date_time.reg < scratch_time.reg) _sunrise_sunset_set_expiration(state, scratch_time); - SolarEvent events[] = { - {civ_start_time.reg, &civ_start_time, "civ_start_time", "cI"}, - {rise_time.reg, &rise_time, "rise_time", "rI"}, - {set_time.reg, &set_time, "set_time", "SE"}, - {civ_end_time.reg, &civ_end_time, "civ_end_time", "cI"} - }; + if (date_time.reg < scratch_time.reg || show_next_match) { + if (state->rise_index == 0 || show_next_match) { + bool set_leading_zero = false; + if (!settings->bit.clock_mode_24h) { + if (watch_utility_convert_to_12_hour(&scratch_time)) watch_set_indicator(WATCH_INDICATOR_PM); + else watch_clear_indicator(WATCH_INDICATOR_PM); + } else if (settings->bit.clock_24h_leading_zero && scratch_time.unit.hour < 10) { + set_leading_zero = true; + } + sprintf(buf, "rI%2d%2d%02d%s", scratch_time.unit.day, scratch_time.unit.hour, scratch_time.unit.minute,longLatPresets[state->longLatToUse].name); + watch_display_string(buf, 0); + if (set_leading_zero) + watch_display_string("0", 4); + return; + } else { + show_next_match = true; + } + } - int n = sizeof(events) / sizeof(events[0]); + minutes = 60.0 * fmod(set, 1); + seconds = 60.0 * fmod(minutes, 1); + scratch_time.unit.hour = floor(set); + if (seconds < 30) scratch_time.unit.minute = floor(minutes); + else scratch_time.unit.minute = ceil(minutes); - // Sort the array of events - qsort(events, n, sizeof(SolarEvent), compare); + if (scratch_time.unit.minute == 60) { + scratch_time.unit.minute = 0; + scratch_time.unit.hour = (scratch_time.unit.hour + 1) % 24; + } - switch (state->rise_index) { - case 0: - display_time(events[0].event, events[0].abreviation, settings, &date_time, state); - break; - case 1: - display_time(events[1].event, events[1].abreviation, settings, &date_time, state); - break; - case 2: - display_time(events[2].event, events[2].abreviation, settings, &date_time, state); - break; - case 3: - display_time(events[3].event, events[3].abreviation, settings, &date_time, state); - break; - default: - break; - } + if (date_time.reg < scratch_time.reg) _sunrise_sunset_set_expiration(state, scratch_time); + + if (date_time.reg < scratch_time.reg || show_next_match) { + if (state->rise_index == 0 || show_next_match) { + bool set_leading_zero = false; + if (!settings->bit.clock_mode_24h) { + if (watch_utility_convert_to_12_hour(&scratch_time)) watch_set_indicator(WATCH_INDICATOR_PM); + else watch_clear_indicator(WATCH_INDICATOR_PM); + } else if (settings->bit.clock_24h_leading_zero && scratch_time.unit.hour < 10) { + set_leading_zero = true; + } + sprintf(buf, "SE%2d%2d%02d%s", scratch_time.unit.day, scratch_time.unit.hour, scratch_time.unit.minute, longLatPresets[state->longLatToUse].name); + watch_display_string(buf, 0); + if (set_leading_zero) + watch_display_string("0", 4); + return; + } else { + show_next_match = true; + } + } + // it's after sunset. we need to display sunrise/sunset for tomorrow. + uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); + timestamp += 86400; + scratch_time = watch_utility_date_time_from_unix_time(timestamp, 0); + } } -static int16_t sunrise_sunset_face_latlon_from_struct(sunrise_sunset_lat_lon_settings_t val) { +static int16_t _sunrise_sunset_face_latlon_from_struct(sunrise_sunset_lat_lon_settings_t val) { int16_t retval = (val.sign ? -1 : 1) * ( val.hundreds * 10000 + @@ -241,7 +181,7 @@ static int16_t sunrise_sunset_face_latlon_from_struct(sunrise_sunset_lat_lon_set return retval; } -static sunrise_sunset_lat_lon_settings_t sunrise_sunset_face_struct_from_latlon(int16_t val) { +static sunrise_sunset_lat_lon_settings_t _sunrise_sunset_face_struct_from_latlon(int16_t val) { sunrise_sunset_lat_lon_settings_t retval; retval.sign = val < 0; @@ -259,11 +199,11 @@ static sunrise_sunset_lat_lon_settings_t sunrise_sunset_face_struct_from_latlon( return retval; } -static void sunrise_sunset_face_update_location_register(sunrise_sunset_state_t *state) { +static void _sunrise_sunset_face_update_location_register(sunrise_sunset_state_t *state) { if (state->location_changed) { movement_location_t movement_location; - int16_t lat = sunrise_sunset_face_latlon_from_struct(state->working_latitude); - int16_t lon = sunrise_sunset_face_latlon_from_struct(state->working_longitude); + int16_t lat = _sunrise_sunset_face_latlon_from_struct(state->working_latitude); + int16_t lon = _sunrise_sunset_face_latlon_from_struct(state->working_longitude); movement_location.bit.latitude = lat; movement_location.bit.longitude = lon; watch_store_backup_data(movement_location.reg, 1); @@ -271,17 +211,17 @@ static void sunrise_sunset_face_update_location_register(sunrise_sunset_state_t } } -static void sunrise_sunset_face_update_settings_display(movement_event_t event, sunrise_sunset_state_t *state) { +static void _sunrise_sunset_face_update_settings_display(movement_event_t event, sunrise_sunset_state_t *state) { char buf[12]; switch (state->page) { case 0: return; case 1: - sprintf(buf, "LA %c %04d", state->working_latitude.sign ? '-' : '+', abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude))); + sprintf(buf, "LA %c %04d", state->working_latitude.sign ? '-' : '+', abs(_sunrise_sunset_face_latlon_from_struct(state->working_latitude))); break; case 2: - sprintf(buf, "LO %c%05d", state->working_longitude.sign ? '-' : '+', abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude))); + sprintf(buf, "LO %c%05d", state->working_longitude.sign ? '-' : '+', abs(_sunrise_sunset_face_latlon_from_struct(state->working_longitude))); break; } if (event.subsecond % 2) { @@ -290,7 +230,7 @@ static void sunrise_sunset_face_update_settings_display(movement_event_t event, watch_display_string(buf, 0); } -static void sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { +static void _sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { state->location_changed = true; switch (state->page) { case 1: // latitude @@ -303,7 +243,7 @@ static void sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { break; case 2: state->working_latitude.tens = (state->working_latitude.tens + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) { + if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) { // prevent latitude from going over ±90. // TODO: perform these checks when advancing the digit? state->working_latitude.ones = 0; @@ -313,15 +253,15 @@ static void sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { break; case 3: state->working_latitude.ones = (state->working_latitude.ones + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.ones = 0; + if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.ones = 0; break; case 4: state->working_latitude.tenths = (state->working_latitude.tenths + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.tenths = 0; + if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.tenths = 0; break; case 5: state->working_latitude.hundredths = (state->working_latitude.hundredths + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.hundredths = 0; + if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.hundredths = 0; break; } break; @@ -332,7 +272,7 @@ static void sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { break; case 1: state->working_longitude.hundreds = (state->working_longitude.hundreds + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) { + if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) { // prevent longitude from going over ±180 state->working_longitude.tens = 8; state->working_longitude.ones = 0; @@ -342,19 +282,19 @@ static void sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { break; case 2: state->working_longitude.tens = (state->working_longitude.tens + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tens = 0; + if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tens = 0; break; case 3: state->working_longitude.ones = (state->working_longitude.ones + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.ones = 0; + if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.ones = 0; break; case 4: state->working_longitude.tenths = (state->working_longitude.tenths + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tenths = 0; + if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tenths = 0; break; case 5: state->working_longitude.hundredths = (state->working_longitude.hundredths + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.hundredths = 0; + if (abs(_sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.hundredths = 0; break; } break; @@ -392,8 +332,8 @@ void sunrise_sunset_face_activate(movement_settings_t *settings, void *context) sunrise_sunset_state_t *state = (sunrise_sunset_state_t *)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->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); } bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { @@ -401,15 +341,22 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti switch (event.event_type) { case EVENT_ACTIVATE: - sunrise_sunset_face_update(settings, state); + _sunrise_sunset_face_update(settings, state); break; case EVENT_LOW_ENERGY_UPDATE: case EVENT_TICK: if (state->page == 0) { // if entering low energy mode, start tick animation if (event.event_type == EVENT_LOW_ENERGY_UPDATE && !watch_tick_animation_is_running()) watch_start_tick_animation(1000); - } else { - sunrise_sunset_face_update_settings_display(event, state); + // check if we need to update the display + watch_date_time date_time = watch_rtc_get_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; + _sunrise_sunset_face_update(settings, state); + } + } else { + _sunrise_sunset_face_update_settings_display(event, state); } break; case EVENT_LIGHT_BUTTON_DOWN: @@ -419,15 +366,15 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti if (state->active_digit > 5) { state->active_digit = 0; state->page = (state->page + 1) % 3; - sunrise_sunset_face_update_location_register(state); + _sunrise_sunset_face_update_location_register(state); } - sunrise_sunset_face_update_settings_display(event, context); + _sunrise_sunset_face_update_settings_display(event, context); } else if (_location_count <= 1) { movement_illuminate_led(); } if (state->page == 0) { movement_request_tick_frequency(1); - sunrise_sunset_face_update(settings, state); + _sunrise_sunset_face_update(settings, state); } break; case EVENT_LIGHT_LONG_PRESS: @@ -437,36 +384,36 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti case EVENT_LIGHT_BUTTON_UP: if (state->page == 0 && _location_count > 1) { state->longLatToUse = (state->longLatToUse + 1) % _location_count; - sunrise_sunset_face_update(settings, state); + _sunrise_sunset_face_update(settings, state); } break; case EVENT_ALARM_BUTTON_UP: if (state->page) { - sunrise_sunset_face_advance_digit(state); - sunrise_sunset_face_update_settings_display(event, context); + _sunrise_sunset_face_advance_digit(state); + _sunrise_sunset_face_update_settings_display(event, context); } else { - state->rise_index = (state->rise_index + 1) % 4; - sunrise_sunset_face_update(settings, state); + state->rise_index = (state->rise_index + 1) % 2; + _sunrise_sunset_face_update(settings, state); } break; case EVENT_ALARM_LONG_PRESS: if (state->page == 0) { if (state->longLatToUse != 0) { state->longLatToUse = 0; - sunrise_sunset_face_update(settings, state); + _sunrise_sunset_face_update(settings, state); break; } state->page++; state->active_digit = 0; watch_clear_display(); movement_request_tick_frequency(4); - sunrise_sunset_face_update_settings_display(event, context); + _sunrise_sunset_face_update_settings_display(event, context); } else { state->active_digit = 0; state->page = 0; - sunrise_sunset_face_update_location_register(state); - sunrise_sunset_face_update(settings, state); + _sunrise_sunset_face_update_location_register(state); + _sunrise_sunset_face_update(settings, state); } break; case EVENT_TIMEOUT: @@ -478,7 +425,7 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti state->page = 0; state->rise_index = 0; movement_request_tick_frequency(1); - sunrise_sunset_face_update(settings, state); + _sunrise_sunset_face_update(settings, state); } break; default: @@ -494,5 +441,5 @@ void sunrise_sunset_face_resign(movement_settings_t *settings, void *context) { state->page = 0; state->active_digit = 0; state->rise_index = 0; - sunrise_sunset_face_update_location_register(state); + _sunrise_sunset_face_update_location_register(state); } From 1d763d17fe688c4ecf91ffe8d40b494cee660aa5 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Wed, 16 Oct 2024 16:03:09 -0400 Subject: [PATCH 05/10] and all the other adjustments --- .../complication/sunrise_sunset_alt_face.c | 104 +++++++++--------- .../complication/sunrise_sunset_alt_face.h | 34 +++--- 2 files changed, 69 insertions(+), 69 deletions(-) diff --git a/movement/watch_faces/complication/sunrise_sunset_alt_face.c b/movement/watch_faces/complication/sunrise_sunset_alt_face.c index c04cd7747..1cebcfffb 100644 --- a/movement/watch_faces/complication/sunrise_sunset_alt_face.c +++ b/movement/watch_faces/complication/sunrise_sunset_alt_face.c @@ -28,7 +28,7 @@ #include #include #include -#include "sunrise_sunset_face.h" +#include "sunrise_sunset_alt_face.h" #include "watch.h" #include "watch_utility.h" #include "sunriset.h" @@ -37,7 +37,7 @@ #include #endif -static const uint8_t _location_count = sizeof(longLatPresets) / sizeof(long_lat_presets_t); +static const uint8_t _location_count = sizeof(alt_longLatPresets) / sizeof(alt_long_lat_presets_t); static int compare(const void *a, const void *b) { SolarEvent *eventA = (SolarEvent *)a; @@ -66,7 +66,7 @@ static void set_sunriset(double time_value, watch_date_time *time_unit) { } } -static void display_time(watch_date_time *time, const char *prefix, movement_settings_t *settings, watch_date_time *date_time, sunrise_sunset_state_t *state) { +static void display_time(watch_date_time *time, const char *prefix, movement_settings_t *settings, watch_date_time *date_time, sunrise_sunset_alt_state_t *state) { bool set_leading_zero = false; char buf[32]; // Adjust size as needed @@ -84,7 +84,7 @@ static void display_time(watch_date_time *time, const char *prefix, movement_set } // Format and display time - sprintf(buf, "%s%2d%2d%02d%s", prefix, time->unit.day, time->unit.hour, time->unit.minute, longLatPresets[state->longLatToUse].name); + sprintf(buf, "%s%2d%2d%02d%s", prefix, time->unit.day, time->unit.hour, time->unit.minute, alt_longLatPresets[state->longLatToUse].name); watch_display_string(buf, 0); // Display leading zero if needed @@ -93,15 +93,15 @@ static void display_time(watch_date_time *time, const char *prefix, movement_set } } -static void sunrise_sunset_face_update(movement_settings_t *settings, sunrise_sunset_state_t *state) { +static void sunrise_sunset_alt_face_update(movement_settings_t *settings, sunrise_sunset_alt_state_t *state) { char buf[14]; double civ_start, rise, set, civ_end; movement_location_t movement_location; if (state->longLatToUse == 0 || _location_count <= 1) movement_location = (movement_location_t) watch_get_backup_data(1); else{ - movement_location.bit.latitude = longLatPresets[state->longLatToUse].latitude; - movement_location.bit.longitude = longLatPresets[state->longLatToUse].longitude; + movement_location.bit.latitude = alt_longLatPresets[state->longLatToUse].latitude; + movement_location.bit.longitude = alt_longLatPresets[state->longLatToUse].longitude; } if (movement_location.reg == 0) { @@ -229,7 +229,7 @@ static void sunrise_sunset_face_update(movement_settings_t *settings, sunrise_su } -static int16_t sunrise_sunset_face_latlon_from_struct(sunrise_sunset_lat_lon_settings_t val) { +static int16_t sunrise_sunset_alt_face_latlon_from_struct(sunrise_sunset_alt_lat_lon_settings_t val) { int16_t retval = (val.sign ? -1 : 1) * ( val.hundreds * 10000 + @@ -241,8 +241,8 @@ static int16_t sunrise_sunset_face_latlon_from_struct(sunrise_sunset_lat_lon_set return retval; } -static sunrise_sunset_lat_lon_settings_t sunrise_sunset_face_struct_from_latlon(int16_t val) { - sunrise_sunset_lat_lon_settings_t retval; +static sunrise_sunset_alt_lat_lon_settings_t sunrise_sunset_alt_face_struct_from_latlon(int16_t val) { + sunrise_sunset_alt_lat_lon_settings_t retval; retval.sign = val < 0; val = abs(val); @@ -259,11 +259,11 @@ static sunrise_sunset_lat_lon_settings_t sunrise_sunset_face_struct_from_latlon( return retval; } -static void sunrise_sunset_face_update_location_register(sunrise_sunset_state_t *state) { +static void sunrise_sunset_alt_face_update_location_register(sunrise_sunset_alt_state_t *state) { if (state->location_changed) { movement_location_t movement_location; - int16_t lat = sunrise_sunset_face_latlon_from_struct(state->working_latitude); - int16_t lon = sunrise_sunset_face_latlon_from_struct(state->working_longitude); + int16_t lat = sunrise_sunset_alt_face_latlon_from_struct(state->working_latitude); + int16_t lon = sunrise_sunset_alt_face_latlon_from_struct(state->working_longitude); movement_location.bit.latitude = lat; movement_location.bit.longitude = lon; watch_store_backup_data(movement_location.reg, 1); @@ -271,17 +271,17 @@ static void sunrise_sunset_face_update_location_register(sunrise_sunset_state_t } } -static void sunrise_sunset_face_update_settings_display(movement_event_t event, sunrise_sunset_state_t *state) { +static void sunrise_sunset_alt_face_update_settings_display(movement_event_t event, sunrise_sunset_alt_state_t *state) { char buf[12]; switch (state->page) { case 0: return; case 1: - sprintf(buf, "LA %c %04d", state->working_latitude.sign ? '-' : '+', abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude))); + sprintf(buf, "LA %c %04d", state->working_latitude.sign ? '-' : '+', abs(sunrise_sunset_alt_face_latlon_from_struct(state->working_latitude))); break; case 2: - sprintf(buf, "LO %c%05d", state->working_longitude.sign ? '-' : '+', abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude))); + sprintf(buf, "LO %c%05d", state->working_longitude.sign ? '-' : '+', abs(sunrise_sunset_alt_face_latlon_from_struct(state->working_longitude))); break; } if (event.subsecond % 2) { @@ -290,7 +290,7 @@ static void sunrise_sunset_face_update_settings_display(movement_event_t event, watch_display_string(buf, 0); } -static void sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { +static void sunrise_sunset_alt_face_advance_digit(sunrise_sunset_alt_state_t *state) { state->location_changed = true; switch (state->page) { case 1: // latitude @@ -303,7 +303,7 @@ static void sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { break; case 2: state->working_latitude.tens = (state->working_latitude.tens + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) { + if (abs(sunrise_sunset_alt_face_latlon_from_struct(state->working_latitude)) > 9000) { // prevent latitude from going over ±90. // TODO: perform these checks when advancing the digit? state->working_latitude.ones = 0; @@ -313,15 +313,15 @@ static void sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { break; case 3: state->working_latitude.ones = (state->working_latitude.ones + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.ones = 0; + if (abs(sunrise_sunset_alt_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.ones = 0; break; case 4: state->working_latitude.tenths = (state->working_latitude.tenths + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.tenths = 0; + if (abs(sunrise_sunset_alt_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.tenths = 0; break; case 5: state->working_latitude.hundredths = (state->working_latitude.hundredths + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.hundredths = 0; + if (abs(sunrise_sunset_alt_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.hundredths = 0; break; } break; @@ -332,7 +332,7 @@ static void sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { break; case 1: state->working_longitude.hundreds = (state->working_longitude.hundreds + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) { + if (abs(sunrise_sunset_alt_face_latlon_from_struct(state->working_longitude)) > 18000) { // prevent longitude from going over ±180 state->working_longitude.tens = 8; state->working_longitude.ones = 0; @@ -342,35 +342,35 @@ static void sunrise_sunset_face_advance_digit(sunrise_sunset_state_t *state) { break; case 2: state->working_longitude.tens = (state->working_longitude.tens + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tens = 0; + if (abs(sunrise_sunset_alt_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tens = 0; break; case 3: state->working_longitude.ones = (state->working_longitude.ones + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.ones = 0; + if (abs(sunrise_sunset_alt_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.ones = 0; break; case 4: state->working_longitude.tenths = (state->working_longitude.tenths + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tenths = 0; + if (abs(sunrise_sunset_alt_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tenths = 0; break; case 5: state->working_longitude.hundredths = (state->working_longitude.hundredths + 1) % 10; - if (abs(sunrise_sunset_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.hundredths = 0; + if (abs(sunrise_sunset_alt_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.hundredths = 0; break; } break; } } -void sunrise_sunset_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) { +void sunrise_sunset_alt_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) { (void) settings; (void) watch_face_index; if (*context_ptr == NULL) { - *context_ptr = malloc(sizeof(sunrise_sunset_state_t)); - memset(*context_ptr, 0, sizeof(sunrise_sunset_state_t)); + *context_ptr = malloc(sizeof(sunrise_sunset_alt_state_t)); + memset(*context_ptr, 0, sizeof(sunrise_sunset_alt_state_t)); } } -void sunrise_sunset_face_activate(movement_settings_t *settings, void *context) { +void sunrise_sunset_alt_face_activate(movement_settings_t *settings, void *context) { (void) settings; if (watch_tick_animation_is_running()) watch_stop_tick_animation(); @@ -390,18 +390,18 @@ void sunrise_sunset_face_activate(movement_settings_t *settings, void *context) #endif - sunrise_sunset_state_t *state = (sunrise_sunset_state_t *)context; + sunrise_sunset_alt_state_t *state = (sunrise_sunset_alt_state_t *)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->working_latitude = sunrise_sunset_alt_face_struct_from_latlon(movement_location.bit.latitude); + state->working_longitude = sunrise_sunset_alt_face_struct_from_latlon(movement_location.bit.longitude); } -bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { - sunrise_sunset_state_t *state = (sunrise_sunset_state_t *)context; +bool sunrise_sunset_alt_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + sunrise_sunset_alt_state_t *state = (sunrise_sunset_alt_state_t *)context; switch (event.event_type) { case EVENT_ACTIVATE: - sunrise_sunset_face_update(settings, state); + sunrise_sunset_alt_face_update(settings, state); break; case EVENT_LOW_ENERGY_UPDATE: case EVENT_TICK: @@ -409,7 +409,7 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti // if entering low energy mode, start tick animation if (event.event_type == EVENT_LOW_ENERGY_UPDATE && !watch_tick_animation_is_running()) watch_start_tick_animation(1000); } else { - sunrise_sunset_face_update_settings_display(event, state); + sunrise_sunset_alt_face_update_settings_display(event, state); } break; case EVENT_LIGHT_BUTTON_DOWN: @@ -419,15 +419,15 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti if (state->active_digit > 5) { state->active_digit = 0; state->page = (state->page + 1) % 3; - sunrise_sunset_face_update_location_register(state); + sunrise_sunset_alt_face_update_location_register(state); } - sunrise_sunset_face_update_settings_display(event, context); + sunrise_sunset_alt_face_update_settings_display(event, context); } else if (_location_count <= 1) { movement_illuminate_led(); } if (state->page == 0) { movement_request_tick_frequency(1); - sunrise_sunset_face_update(settings, state); + sunrise_sunset_alt_face_update(settings, state); } break; case EVENT_LIGHT_LONG_PRESS: @@ -437,36 +437,36 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti case EVENT_LIGHT_BUTTON_UP: if (state->page == 0 && _location_count > 1) { state->longLatToUse = (state->longLatToUse + 1) % _location_count; - sunrise_sunset_face_update(settings, state); + sunrise_sunset_alt_face_update(settings, state); } break; case EVENT_ALARM_BUTTON_UP: if (state->page) { - sunrise_sunset_face_advance_digit(state); - sunrise_sunset_face_update_settings_display(event, context); + sunrise_sunset_alt_face_advance_digit(state); + sunrise_sunset_alt_face_update_settings_display(event, context); } else { state->rise_index = (state->rise_index + 1) % 4; - sunrise_sunset_face_update(settings, state); + sunrise_sunset_alt_face_update(settings, state); } break; case EVENT_ALARM_LONG_PRESS: if (state->page == 0) { if (state->longLatToUse != 0) { state->longLatToUse = 0; - sunrise_sunset_face_update(settings, state); + sunrise_sunset_alt_face_update(settings, state); break; } state->page++; state->active_digit = 0; watch_clear_display(); movement_request_tick_frequency(4); - sunrise_sunset_face_update_settings_display(event, context); + sunrise_sunset_alt_face_update_settings_display(event, context); } else { state->active_digit = 0; state->page = 0; - sunrise_sunset_face_update_location_register(state); - sunrise_sunset_face_update(settings, state); + sunrise_sunset_alt_face_update_location_register(state); + sunrise_sunset_alt_face_update(settings, state); } break; case EVENT_TIMEOUT: @@ -478,7 +478,7 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti state->page = 0; state->rise_index = 0; movement_request_tick_frequency(1); - sunrise_sunset_face_update(settings, state); + sunrise_sunset_alt_face_update(settings, state); } break; default: @@ -488,11 +488,11 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti return true; } -void sunrise_sunset_face_resign(movement_settings_t *settings, void *context) { +void sunrise_sunset_alt_face_resign(movement_settings_t *settings, void *context) { (void) settings; - sunrise_sunset_state_t *state = (sunrise_sunset_state_t *)context; + sunrise_sunset_alt_state_t *state = (sunrise_sunset_alt_state_t *)context; state->page = 0; state->active_digit = 0; state->rise_index = 0; - sunrise_sunset_face_update_location_register(state); + sunrise_sunset_alt_face_update_location_register(state); } diff --git a/movement/watch_faces/complication/sunrise_sunset_alt_face.h b/movement/watch_faces/complication/sunrise_sunset_alt_face.h index 814d47fcc..1b05dbabb 100644 --- a/movement/watch_faces/complication/sunrise_sunset_alt_face.h +++ b/movement/watch_faces/complication/sunrise_sunset_alt_face.h @@ -22,8 +22,8 @@ * SOFTWARE. */ -#ifndef SUNRISE_SUNSET_FACE_H_ -#define SUNRISE_SUNSET_FACE_H_ +#ifndef SUNRISE_SUNSET_ALT_FACE_H_ +#define SUNRISE_SUNSET_ALT_FACE_H_ /* * SUNRISE & SUNSET FACE @@ -45,7 +45,7 @@ typedef struct { uint8_t ones: 4; // 0-9 (must wrap at 10) uint8_t tenths: 4; // 0-9 (must wrap at 10) uint8_t hundredths: 4; // 0-9 (must wrap at 10) -} sunrise_sunset_lat_lon_settings_t; +} sunrise_sunset_alt_lat_lon_settings_t; typedef struct { uint8_t page; @@ -53,10 +53,10 @@ typedef struct { uint8_t active_digit; bool location_changed; watch_date_time rise_set_expires; - sunrise_sunset_lat_lon_settings_t working_latitude; - sunrise_sunset_lat_lon_settings_t working_longitude; + sunrise_sunset_alt_lat_lon_settings_t working_latitude; + sunrise_sunset_alt_lat_lon_settings_t working_longitude; uint8_t longLatToUse; -} sunrise_sunset_state_t; +} sunrise_sunset_alt_state_t; typedef struct { int timestamp; @@ -65,16 +65,16 @@ typedef struct { const char *abreviation; } SolarEvent; -void sunrise_sunset_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); -void sunrise_sunset_face_activate(movement_settings_t *settings, void *context); -bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *settings, void *context); -void sunrise_sunset_face_resign(movement_settings_t *settings, void *context); +void sunrise_sunset_alt_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void sunrise_sunset_alt_face_activate(movement_settings_t *settings, void *context); +bool sunrise_sunset_alt_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void sunrise_sunset_alt_face_resign(movement_settings_t *settings, void *context); -#define sunrise_sunset_face ((const watch_face_t){ \ - sunrise_sunset_face_setup, \ - sunrise_sunset_face_activate, \ - sunrise_sunset_face_loop, \ - sunrise_sunset_face_resign, \ +#define sunrise_sunset_alt_face ((const watch_face_t){ \ + sunrise_sunset_alt_face_setup, \ + sunrise_sunset_alt_face_activate, \ + sunrise_sunset_alt_face_loop, \ + sunrise_sunset_alt_face_resign, \ NULL, \ }) @@ -82,9 +82,9 @@ typedef struct { char name[2]; int16_t latitude; int16_t longitude; -} long_lat_presets_t; +} alt_long_lat_presets_t; -static const long_lat_presets_t longLatPresets[] = +static const alt_long_lat_presets_t alt_longLatPresets[] = { { .name = " "}, // Default, the long and lat get replaced by what's set in the watch { .name = "dc", .latitude = 3883, .longitude = -7711 }, // Alexandria, VA From 357335fa2df7c303b49ff7f18fb754332ef9be4d Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Fri, 18 Oct 2024 08:05:24 -0400 Subject: [PATCH 06/10] Most people probably don't want my preset --- movement/watch_faces/complication/sunrise_sunset_alt_face.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/movement/watch_faces/complication/sunrise_sunset_alt_face.h b/movement/watch_faces/complication/sunrise_sunset_alt_face.h index 1b05dbabb..0a949d8d5 100644 --- a/movement/watch_faces/complication/sunrise_sunset_alt_face.h +++ b/movement/watch_faces/complication/sunrise_sunset_alt_face.h @@ -87,7 +87,7 @@ typedef struct { static const alt_long_lat_presets_t alt_longLatPresets[] = { { .name = " "}, // Default, the long and lat get replaced by what's set in the watch - { .name = "dc", .latitude = 3883, .longitude = -7711 }, // Alexandria, VA +// { .name = "dc", .latitude = 3883, .longitude = -7711 }, // Alexandria, VA // { .name = "Ny", .latitude = 4072, .longitude = -7401 }, // New York City, NY // { .name = "LA", .latitude = 3405, .longitude = -11824 }, // Los Angeles, CA // { .name = "dE", .latitude = 4221, .longitude = -8305 }, // Detroit, MI From b9de5cf2e451104cdc5b345cc49f2d33db0783a2 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Sat, 19 Oct 2024 07:11:33 -0400 Subject: [PATCH 07/10] Adding nautical twilights as well --- .../complication/sunrise_sunset_alt_face.c | 95 ++++++++----------- .../complication/sunrise_sunset_alt_face.h | 3 +- 2 files changed, 41 insertions(+), 57 deletions(-) diff --git a/movement/watch_faces/complication/sunrise_sunset_alt_face.c b/movement/watch_faces/complication/sunrise_sunset_alt_face.c index 1cebcfffb..46d836d22 100644 --- a/movement/watch_faces/complication/sunrise_sunset_alt_face.c +++ b/movement/watch_faces/complication/sunrise_sunset_alt_face.c @@ -66,6 +66,17 @@ static void set_sunriset(double time_value, watch_date_time *time_unit) { } } +static void check_and_update_sunriset(double event_type, watch_date_time *event_time, watch_date_time utc_now, watch_date_time date_time) { + set_sunriset(event_type, event_time); + if (date_time.reg > event_time->reg) { + // It's after the specific solar event. We need to display the event time for tomorrow. + uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); + timestamp += 86400; // Advance by 24 hours + *event_time = watch_utility_date_time_from_unix_time(timestamp, 0); + set_sunriset(event_type, event_time); // Update for the next day + } +} + static void display_time(watch_date_time *time, const char *prefix, movement_settings_t *settings, watch_date_time *date_time, sunrise_sunset_alt_state_t *state) { bool set_leading_zero = false; char buf[32]; // Adjust size as needed @@ -94,8 +105,7 @@ static void display_time(watch_date_time *time, const char *prefix, movement_set } static void sunrise_sunset_alt_face_update(movement_settings_t *settings, sunrise_sunset_alt_state_t *state) { - char buf[14]; - double civ_start, rise, set, civ_end; + double naut_start, civ_start, rise, set, civ_end, naut_end; movement_location_t movement_location; if (state->longLatToUse == 0 || _location_count <= 1) movement_location = (movement_location_t) watch_get_backup_data(1); @@ -113,16 +123,22 @@ static void sunrise_sunset_alt_face_update(movement_settings_t *settings, sunris 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 scratch_time; // scratchpad, contains different values at different times + watch_date_time naut_start_time; watch_date_time civ_start_time; watch_date_time rise_time; watch_date_time set_time; watch_date_time civ_end_time; + watch_date_time naut_end_time; + scratch_time.reg = utc_now.reg; + naut_start_time.reg = utc_now.reg; civ_start_time.reg = utc_now.reg; rise_time.reg = utc_now.reg; set_time.reg = utc_now.reg; civ_end_time.reg = utc_now.reg; + naut_end_time.reg = utc_now.reg; // Weird quirky unsigned things were happening when I tried to cast these directly to doubles below. // it looks redundant, but extracting them to local int16's seemed to fix it. @@ -137,72 +153,34 @@ static void sunrise_sunset_alt_face_update(movement_settings_t *settings, sunris // 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; - // we loop twice because if it's after sunset today, we need to recalculate to display values for tomorrow. - uint8_t result = sun_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &rise, &set); - - if (result != 0) { - watch_clear_colon(); - watch_clear_indicator(WATCH_INDICATOR_PM); - watch_clear_indicator(WATCH_INDICATOR_24H); - sprintf(buf, "%s%2d none ", (result == 1) ? "SE" : "rI", scratch_time.unit.day); - watch_display_string(buf, 0); - return; - } + sun_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &rise, &set); civil_twilight(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &civ_start, &civ_end); + nautical_twilight(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &naut_start, &naut_end); watch_set_colon(); if (settings->bit.clock_mode_24h && !settings->bit.clock_24h_leading_zero) watch_set_indicator(WATCH_INDICATOR_24H); + naut_start += hours_from_utc; + civ_start += hours_from_utc; rise += hours_from_utc; set += hours_from_utc; - civ_start += hours_from_utc; civ_end += hours_from_utc; + naut_end += hours_from_utc; - set_sunriset(civ_start, &civ_start_time); - if (date_time.reg > civ_start_time.reg) { - // it's after sunset. we need to display sunrise/sunset for tomorrow. - uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); - timestamp += 86400; - civ_start_time = watch_utility_date_time_from_unix_time(timestamp, 0); - set_sunriset(civ_start, &civ_start_time); - } - //display_time(&civ_start_time, "CI", settings, &date_time, state); - - set_sunriset(rise, &rise_time); - if (date_time.reg > rise_time.reg) { - // it's after sunset. we need to display sunrise/sunset for tomorrow. - uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); - timestamp += 86400; - rise_time = watch_utility_date_time_from_unix_time(timestamp, 0); - set_sunriset(rise, &rise_time); - } - //display_time(&rise_time, "rI", settings, &date_time, state); - - set_sunriset(set, &set_time); - if (date_time.reg > set_time.reg) { - // it's after sunset. we need to display sunrise/sunset for tomorrow. - uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); - timestamp += 86400; - set_time = watch_utility_date_time_from_unix_time(timestamp, 0); - set_sunriset(set, &set_time); - } - //display_time(&set_time, "SE", settings, &date_time, state); - - set_sunriset(civ_end, &civ_end_time); - if (date_time.reg > civ_end_time.reg) { - // it's after sunset. we need to display sunrise/sunset for tomorrow. - uint32_t timestamp = watch_utility_date_time_to_unix_time(utc_now, 0); - timestamp += 86400; - civ_end_time = watch_utility_date_time_from_unix_time(timestamp, 0); - set_sunriset(civ_end, &civ_end_time); - } - //display_time(&civ_end_time, "SE", settings, &date_time, state); + check_and_update_sunriset(naut_start, &naut_start_time, utc_now, date_time); + check_and_update_sunriset(civ_start, &civ_start_time, utc_now, date_time); + check_and_update_sunriset(rise, &rise_time, utc_now, date_time); + check_and_update_sunriset(set, &set_time, utc_now, date_time); + check_and_update_sunriset(civ_end, &civ_end_time, utc_now, date_time); + check_and_update_sunriset(naut_end, &naut_end_time, utc_now, date_time); SolarEvent events[] = { + {naut_start_time.reg, &naut_start_time, "naut_start_time", "nt"}, {civ_start_time.reg, &civ_start_time, "civ_start_time", "cI"}, {rise_time.reg, &rise_time, "rise_time", "rI"}, {set_time.reg, &set_time, "set_time", "SE"}, - {civ_end_time.reg, &civ_end_time, "civ_end_time", "cI"} + {civ_end_time.reg, &civ_end_time, "civ_end_time", "cI"}, + {naut_end_time.reg, &naut_end_time, "naut_end_time", "nt"} }; int n = sizeof(events) / sizeof(events[0]); @@ -223,6 +201,12 @@ static void sunrise_sunset_alt_face_update(movement_settings_t *settings, sunris case 3: display_time(events[3].event, events[3].abreviation, settings, &date_time, state); break; + case 4: + display_time(events[4].event, events[4].abreviation, settings, &date_time, state); + break; + case 5: + display_time(events[5].event, events[5].abreviation, settings, &date_time, state); + break; default: break; } @@ -445,7 +429,8 @@ bool sunrise_sunset_alt_face_loop(movement_event_t event, movement_settings_t *s sunrise_sunset_alt_face_advance_digit(state); sunrise_sunset_alt_face_update_settings_display(event, context); } else { - state->rise_index = (state->rise_index + 1) % 4; + state->rise_index = (state->rise_index + 1) % 6; + printf("state->rise_index = %d\n", state->rise_index); sunrise_sunset_alt_face_update(settings, state); } break; diff --git a/movement/watch_faces/complication/sunrise_sunset_alt_face.h b/movement/watch_faces/complication/sunrise_sunset_alt_face.h index 0a949d8d5..968c6842a 100644 --- a/movement/watch_faces/complication/sunrise_sunset_alt_face.h +++ b/movement/watch_faces/complication/sunrise_sunset_alt_face.h @@ -52,7 +52,6 @@ typedef struct { uint8_t rise_index; uint8_t active_digit; bool location_changed; - watch_date_time rise_set_expires; sunrise_sunset_alt_lat_lon_settings_t working_latitude; sunrise_sunset_alt_lat_lon_settings_t working_longitude; uint8_t longLatToUse; @@ -87,7 +86,7 @@ typedef struct { static const alt_long_lat_presets_t alt_longLatPresets[] = { { .name = " "}, // Default, the long and lat get replaced by what's set in the watch -// { .name = "dc", .latitude = 3883, .longitude = -7711 }, // Alexandria, VA + { .name = "dc", .latitude = 3883, .longitude = -7711 }, // Alexandria, VA // { .name = "Ny", .latitude = 4072, .longitude = -7401 }, // New York City, NY // { .name = "LA", .latitude = 3405, .longitude = -11824 }, // Los Angeles, CA // { .name = "dE", .latitude = 4221, .longitude = -8305 }, // Detroit, MI From e3d50374bf77eec4f1bca14ecdfc05fb8cc6b537 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Sat, 19 Oct 2024 07:18:27 -0400 Subject: [PATCH 08/10] Removing my preset (again) --- movement/watch_faces/complication/sunrise_sunset_alt_face.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/movement/watch_faces/complication/sunrise_sunset_alt_face.h b/movement/watch_faces/complication/sunrise_sunset_alt_face.h index 968c6842a..289da2bf1 100644 --- a/movement/watch_faces/complication/sunrise_sunset_alt_face.h +++ b/movement/watch_faces/complication/sunrise_sunset_alt_face.h @@ -86,7 +86,7 @@ typedef struct { static const alt_long_lat_presets_t alt_longLatPresets[] = { { .name = " "}, // Default, the long and lat get replaced by what's set in the watch - { .name = "dc", .latitude = 3883, .longitude = -7711 }, // Alexandria, VA +// { .name = "dc", .latitude = 3883, .longitude = -7711 }, // Alexandria, VA // { .name = "Ny", .latitude = 4072, .longitude = -7401 }, // New York City, NY // { .name = "LA", .latitude = 3405, .longitude = -11824 }, // Los Angeles, CA // { .name = "dE", .latitude = 4221, .longitude = -8305 }, // Detroit, MI From 0e42b9dde0cc0310185dab0a11b9b337b2283105 Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Sat, 19 Oct 2024 07:25:23 -0400 Subject: [PATCH 09/10] smaller buf for the display --- movement/watch_faces/complication/sunrise_sunset_alt_face.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/movement/watch_faces/complication/sunrise_sunset_alt_face.c b/movement/watch_faces/complication/sunrise_sunset_alt_face.c index 46d836d22..0fcd09536 100644 --- a/movement/watch_faces/complication/sunrise_sunset_alt_face.c +++ b/movement/watch_faces/complication/sunrise_sunset_alt_face.c @@ -79,7 +79,7 @@ static void check_and_update_sunriset(double event_type, watch_date_time *event_ static void display_time(watch_date_time *time, const char *prefix, movement_settings_t *settings, watch_date_time *date_time, sunrise_sunset_alt_state_t *state) { bool set_leading_zero = false; - char buf[32]; // Adjust size as needed + char buf[14]; // Handle 12-hour mode and PM indicator if (!settings->bit.clock_mode_24h) { From 52e3247f455f1eeb32d58263d405483b3a2a8dfa Mon Sep 17 00:00:00 2001 From: mcguirepr89 Date: Mon, 21 Oct 2024 12:03:46 -0400 Subject: [PATCH 10/10] smaller int range for memory stack --- .../complication/sunrise_sunset_alt_face.c | 31 +++++++++---------- .../complication/sunrise_sunset_alt_face.h | 3 +- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/movement/watch_faces/complication/sunrise_sunset_alt_face.c b/movement/watch_faces/complication/sunrise_sunset_alt_face.c index 0fcd09536..445dae85b 100644 --- a/movement/watch_faces/complication/sunrise_sunset_alt_face.c +++ b/movement/watch_faces/complication/sunrise_sunset_alt_face.c @@ -77,10 +77,11 @@ static void check_and_update_sunriset(double event_type, watch_date_time *event_ } } -static void display_time(watch_date_time *time, const char *prefix, movement_settings_t *settings, watch_date_time *date_time, sunrise_sunset_alt_state_t *state) { +static void display_time(watch_date_time *time, const char *prefix, movement_settings_t *settings, sunrise_sunset_alt_state_t *state) { bool set_leading_zero = false; char buf[14]; + watch_set_colon(); // Handle 12-hour mode and PM indicator if (!settings->bit.clock_mode_24h) { if (watch_utility_convert_to_12_hour(time)) { @@ -157,7 +158,6 @@ static void sunrise_sunset_alt_face_update(movement_settings_t *settings, sunris civil_twilight(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &civ_start, &civ_end); nautical_twilight(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &naut_start, &naut_end); - watch_set_colon(); if (settings->bit.clock_mode_24h && !settings->bit.clock_24h_leading_zero) watch_set_indicator(WATCH_INDICATOR_24H); naut_start += hours_from_utc; @@ -175,37 +175,37 @@ static void sunrise_sunset_alt_face_update(movement_settings_t *settings, sunris check_and_update_sunriset(naut_end, &naut_end_time, utc_now, date_time); SolarEvent events[] = { - {naut_start_time.reg, &naut_start_time, "naut_start_time", "nt"}, - {civ_start_time.reg, &civ_start_time, "civ_start_time", "cI"}, - {rise_time.reg, &rise_time, "rise_time", "rI"}, - {set_time.reg, &set_time, "set_time", "SE"}, - {civ_end_time.reg, &civ_end_time, "civ_end_time", "cI"}, - {naut_end_time.reg, &naut_end_time, "naut_end_time", "nt"} + {naut_start_time.reg, &naut_start_time, "nt"}, + {civ_start_time.reg, &civ_start_time, "cI"}, + {rise_time.reg, &rise_time, "rI"}, + {set_time.reg, &set_time, "SE"}, + {civ_end_time.reg, &civ_end_time, "cI"}, + {naut_end_time.reg, &naut_end_time, "nt"} }; - int n = sizeof(events) / sizeof(events[0]); + uint8_t n = sizeof(events) / sizeof(events[0]); // Sort the array of events qsort(events, n, sizeof(SolarEvent), compare); switch (state->rise_index) { case 0: - display_time(events[0].event, events[0].abreviation, settings, &date_time, state); + display_time(events[0].event, events[0].abreviation, settings, state); break; case 1: - display_time(events[1].event, events[1].abreviation, settings, &date_time, state); + display_time(events[1].event, events[1].abreviation, settings, state); break; case 2: - display_time(events[2].event, events[2].abreviation, settings, &date_time, state); + display_time(events[2].event, events[2].abreviation, settings, state); break; case 3: - display_time(events[3].event, events[3].abreviation, settings, &date_time, state); + display_time(events[3].event, events[3].abreviation, settings, state); break; case 4: - display_time(events[4].event, events[4].abreviation, settings, &date_time, state); + display_time(events[4].event, events[4].abreviation, settings, state); break; case 5: - display_time(events[5].event, events[5].abreviation, settings, &date_time, state); + display_time(events[5].event, events[5].abreviation, settings, state); break; default: break; @@ -430,7 +430,6 @@ bool sunrise_sunset_alt_face_loop(movement_event_t event, movement_settings_t *s sunrise_sunset_alt_face_update_settings_display(event, context); } else { state->rise_index = (state->rise_index + 1) % 6; - printf("state->rise_index = %d\n", state->rise_index); sunrise_sunset_alt_face_update(settings, state); } break; diff --git a/movement/watch_faces/complication/sunrise_sunset_alt_face.h b/movement/watch_faces/complication/sunrise_sunset_alt_face.h index 289da2bf1..bf672e93f 100644 --- a/movement/watch_faces/complication/sunrise_sunset_alt_face.h +++ b/movement/watch_faces/complication/sunrise_sunset_alt_face.h @@ -58,9 +58,8 @@ typedef struct { } sunrise_sunset_alt_state_t; typedef struct { - int timestamp; + uint32_t timestamp; watch_date_time *event; - const char *name; const char *abreviation; } SolarEvent;