From 2ab1dcfe27b7fe9891aec12be407654db2a9f839 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 29 Sep 2023 14:34:58 +0000 Subject: first --- .gitignore | 1 + main/default-to-gsm | 20 ++ main/endstop | 0 main/fix-serial | 97 +++++++++ main/fix-wakeup | 42 ++++ main/jmm | 57 +++++ main/metric | 404 +++++++++++++++++++++++++++++++++++ main/moon | 601 ++++++++++++++++++++++++++++++++++++++++++++++++++++ main/series | 8 + main/siderial | 273 ++++++++++++++++++++++++ 10 files changed, 1503 insertions(+) create mode 100644 .gitignore create mode 100644 main/default-to-gsm create mode 100644 main/endstop create mode 100644 main/fix-serial create mode 100644 main/fix-wakeup create mode 100644 main/jmm create mode 100644 main/metric create mode 100644 main/moon create mode 100644 main/series create mode 100644 main/siderial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8be5547 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +status diff --git a/main/default-to-gsm b/main/default-to-gsm new file mode 100644 index 0000000..98de0a3 --- /dev/null +++ b/main/default-to-gsm @@ -0,0 +1,20 @@ +diff --git a/movement/watch_faces/complication/sunrise_sunset_face.c b/movement/watch_faces/complication/sunrise_sunset_face.c +index 1d08bb0..9bd3369 100644 +--- a/movement/watch_faces/complication/sunrise_sunset_face.c ++++ b/movement/watch_faces/complication/sunrise_sunset_face.c +@@ -49,8 +49,15 @@ static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_s + movement_location_t movement_location = (movement_location_t) watch_get_backup_data(1); + + if (movement_location.reg == 0) { ++#if 0 + watch_display_string("RI no Loc", 0); + return; ++#else ++ // Obviously we're at the east end of GSM ++ movement_location.bit.latitude = 5221; ++ movement_location.bit.longitude = 12; ++ watch_store_backup_data(movement_location.reg, 1); ++#endif + } + + watch_date_time date_time = watch_rtc_get_date_time(); // the current local date / time diff --git a/main/endstop b/main/endstop new file mode 100644 index 0000000..e69de29 diff --git a/main/fix-serial b/main/fix-serial new file mode 100644 index 0000000..80b11c5 --- /dev/null +++ b/main/fix-serial @@ -0,0 +1,97 @@ +diff --git a/movement/filesystem.c b/movement/filesystem.c +index 97e3545..d3c2f83 100644 +--- a/movement/filesystem.c ++++ b/movement/filesystem.c +@@ -275,6 +275,10 @@ void filesystem_process_command(char *line) { + filesystem_append_file(filename, "\n", 1); + } + free(text); ++ } else if (strcmp(command, "format") == 0) { ++ lfs_unmount(&lfs); ++ lfs_format(&lfs, &cfg); ++ lfs_mount(&lfs, &cfg); + } else { + printf("%s: command not found\n", command); + } +diff --git a/movement/movement.c b/movement/movement.c +index 825f130..c7066f7 100644 +--- a/movement/movement.c ++++ b/movement/movement.c +@@ -547,7 +547,29 @@ bool app_loop(void) { + tx = ""; + }); + #else +- read(0, line, 256); ++#if 0 ++ read(0, &line[ll], sizeof(line)-ll); ++#else ++ // JMM yuck just yuck, we do our best to patch this mess up ++ { ++ static char buf[sizeof(line) - 1]; ++ static int bl; //again really signed? ++ int red; ++ ++ red = read(0, &buf[bl], sizeof(buf) - 1); ++ ++ if (red > 0) { ++ write(0, &buf[bl], red); ++ bl += red; ++ if (buf[bl-1] == '\r') { ++ for (red = 0; red < bl; ++red) ++ line[red] = buf[red] == '\r' ? '\n' : buf[red]; ++ //memcpy(line,buf,bl-1); ++ bl = 0; ++ } ++ } ++ } ++#endif + #endif + if (strlen(line)) filesystem_process_command(line); + } +diff --git a/watch-library/hardware/watch/watch_private.c b/watch-library/hardware/watch/watch_private.c +index cd607b8..5081fdb 100644 +--- a/watch-library/hardware/watch/watch_private.c ++++ b/watch-library/hardware/watch/watch_private.c +@@ -246,9 +246,18 @@ void _watch_enable_usb(void) { + // this function ends up getting called by printf to log stuff to the USB console. + int _write(int file, char *ptr, int len) { + (void)file; ++ int i; //it's 2023 boys and girls you can use size_t and ssize_t + if (hri_usbdevice_get_CTRLA_ENABLE_bit(USB)) { +- tud_cdc_n_write(0, (void const*)ptr, len); +- tud_cdc_n_write_flush(0); ++ //tud_cdc_n_write(0, (void const*)ptr, len); ++ for (i = 0; i < len; ++i) ++ { ++ if (ptr[i]=='\n') { ++ tud_cdc_n_write(0, (void const*)"\r\n", 2); ++ } else { ++ tud_cdc_n_write(0, (void const*)&ptr[i], 1); ++ } ++ tud_cdc_n_write_flush(0); ++ } + return len; + } + +@@ -262,6 +271,8 @@ int _read(int file, char *ptr, int len) { + int actual_length = strlen(buf); + if (actual_length) { + memcpy(ptr, buf, min(len, actual_length)); ++ //JMM yuckity yuck yuck ++ buf[0] = 0; + return actual_length; + } + return 0; +diff --git a/watch-library/shared/watch/watch.h b/watch-library/shared/watch/watch.h +index 790f9a1..b280ae6 100644 +--- a/watch-library/shared/watch/watch.h ++++ b/watch-library/shared/watch/watch.h +@@ -95,5 +95,6 @@ void watch_reset_to_bootloader(void); + * @return The number of bytes read, or zero if no bytes were read. + */ + int read(int file, char *ptr, int len); ++int write(int file, char *ptr, int len); + +-#endif /* WATCH_H_ */ +\ No newline at end of file ++#endif /* WATCH_H_ */ diff --git a/main/fix-wakeup b/main/fix-wakeup new file mode 100644 index 0000000..e3933a2 --- /dev/null +++ b/main/fix-wakeup @@ -0,0 +1,42 @@ +diff --git a/movement/movement.c b/movement/movement.c +index ec20ce6..825f130 100644 +--- a/movement/movement.c ++++ b/movement/movement.c +@@ -132,7 +132,7 @@ const char movement_valid_position_1_chars[] = " ABCDEFHlJLNORTtUX-='01378"; + void cb_mode_btn_interrupt(void); + void cb_light_btn_interrupt(void); + void cb_alarm_btn_interrupt(void); +-void cb_alarm_btn_extwake(void); ++void cb_btn_extwake(void); + void cb_alarm_fired(void); + void cb_fast_tick(void); + void cb_tick(void); +@@ -382,6 +382,8 @@ void app_setup(void) { + } + if (movement_state.le_mode_ticks != -1) { + watch_disable_extwake_interrupt(BTN_ALARM); ++ watch_disable_extwake_interrupt(BTN_LIGHT); ++ watch_disable_extwake_interrupt(BTN_MODE); + + watch_enable_external_interrupts(); + watch_register_interrupt_callback(BTN_MODE, cb_mode_btn_interrupt, INTERRUPT_TRIGGER_BOTH); +@@ -464,7 +466,9 @@ bool app_loop(void) { + // if we have timed out of our low energy mode countdown, enter low energy mode. + if (movement_state.le_mode_ticks == 0) { + movement_state.le_mode_ticks = -1; +- watch_register_extwake_callback(BTN_ALARM, cb_alarm_btn_extwake, true); ++ watch_register_extwake_callback(BTN_ALARM, cb_btn_extwake, true); ++ watch_register_extwake_callback(BTN_MODE, cb_btn_extwake, true); ++ watch_register_extwake_callback(BTN_LIGHT, cb_btn_extwake, true); + event.event_type = EVENT_NONE; + event.subsecond = 0; + +@@ -600,7 +604,7 @@ void cb_alarm_btn_interrupt(void) { + event.event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp); + } + +-void cb_alarm_btn_extwake(void) { ++void cb_btn_extwake(void) { + // wake up! + _movement_reset_inactivity_countdown(); + } diff --git a/main/jmm b/main/jmm new file mode 100644 index 0000000..0bde666 --- /dev/null +++ b/main/jmm @@ -0,0 +1,57 @@ +diff --git a/movement/alt_fw/jmm.h b/movement/alt_fw/jmm.h +new file mode 100644 +index 0000000..878b4a4 +--- /dev/null ++++ b/movement/alt_fw/jmm.h +@@ -0,0 +1,28 @@ ++#ifndef MOVEMENT_CONFIG_H_ ++#define MOVEMENT_CONFIG_H_ ++ ++#include "movement_faces.h" ++ ++#define MOVEMENT_DEFAULT_RED_COLOR 0xf ++#define MOVEMENT_DEFAULT_GREEN_COLOR 0xf ++ ++const watch_face_t watch_faces[] = { ++ simple_clock_face, ++ stock_stopwatch_face, ++ world_clock_face, ++ totp_face_lfs, ++ moon_phase_face, ++ sunrise_sunset_face, ++ decimal_time_face, ++ beats_face, ++ astronomy_face, ++ preferences_face, ++ frequency_correction_face, ++ set_time_face, ++}; ++ ++#define MOVEMENT_NUM_FACES (sizeof(watch_faces) / sizeof(watch_face_t)) ++ ++#define SIGNAL_TUNE_DEFAULT ++ ++#endif // MOVEMENT_CONFIG_H_ +diff --git a/movement/make/Makefile b/movement/make/Makefile +index 625c772..db08929 100644 +--- a/movement/make/Makefile ++++ b/movement/make/Makefile +@@ -1,3 +1,5 @@ ++FIRMWARE=JMM ++COLOR=RED + # Leave this line at the top of the file; it has all the watch library sources and includes. + TOP = ../.. + include $(TOP)/make.mk +diff --git a/movement/movement.c b/movement/movement.c +index 0c6ed31..ec20ce6 100644 +--- a/movement/movement.c ++++ b/movement/movement.c +@@ -52,6 +52,8 @@ + #include "alt_fw/the_stargazer.h" + #elif MOVEMENT_FIRMWARE == MOVEMENT_FIRMWARE_DEEP_SPACE_NOW + #include "alt_fw/deep_space_now.h" ++#elif MOVEMENT_FIRMWARE == MOVEMENT_FIRMWARE_JMM ++#include "alt_fw/jmm.h" + #endif + + #include "movement_custom_signal_tunes.h" diff --git a/main/metric b/main/metric new file mode 100644 index 0000000..cbf0287 --- /dev/null +++ b/main/metric @@ -0,0 +1,404 @@ +diff --git a/movement/alt_fw/jmm.h b/movement/alt_fw/jmm.h +index 878b4a4..5c2cee7 100644 +--- a/movement/alt_fw/jmm.h ++++ b/movement/alt_fw/jmm.h +@@ -10,6 +10,7 @@ const watch_face_t watch_faces[] = { + simple_clock_face, + stock_stopwatch_face, + world_clock_face, ++ metric_face, + totp_face_lfs, + moon_phase_face, + sunrise_sunset_face, +diff --git a/movement/make/Makefile b/movement/make/Makefile +index db08929..e131bbb 100644 +--- a/movement/make/Makefile ++++ b/movement/make/Makefile +@@ -120,6 +120,7 @@ SRCS += \ + ../watch_faces/complication/flashlight_face.c \ + ../watch_faces/clock/decimal_time_face.c \ + ../watch_faces/clock/wyoscan_face.c \ ++ ../watch_faces/complication/metric_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 ff34c06..94316ce 100644 +--- a/movement/movement_faces.h ++++ b/movement/movement_faces.h +@@ -95,6 +95,7 @@ + #include "flashlight_face.h" + #include "decimal_time_face.h" + #include "wyoscan_face.h" ++#include "metric_face.h" + // New includes go above this line. + + #endif // MOVEMENT_FACES_H_ +diff --git a/movement/watch_faces/complication/equinox.c b/movement/watch_faces/complication/equinox.c +new file mode 100644 +index 0000000..e8d862e +--- /dev/null ++++ b/movement/watch_faces/complication/equinox.c +@@ -0,0 +1,101 @@ ++#define D2R(a) ((a)*(M_PI/180.)) ++ ++ ++ ++ ++// shamelessly stolen from Meeus Astronmical Algorithms Chapter 27 table 27.B ++// chapter 25 is probably more tractable, but this is easier to code up ++ ++# if 0 ++static double mean_vernal_equinox (unsigned year) ++{ ++ double y = year; ++ y -= 2000; ++ y *= 0.001; ++ return 2451623.80984 + 365242.37404 * y + 0.05169 * (y * y) - 0.00411 * (y * y * y) - 0.00057 * (y * y * y * y); ++} ++ ++static double mean_summer_solstice (unsigned year) ++{ ++ double y = year; ++ y -= 2000; ++ y *= 0.001; ++ return 2451716.56767 + 365241.62603 * y + 0.00325 * (y * y) + 0.00888 * (y * y * y) - 0.00030 * (y * y * y * y); ++} ++#endif ++ ++static double mean_autumnal_equinox (unsigned year) ++{ ++ double y = year; ++ y -= 2000; ++ y *= 0.001; ++ return 2451810.21715 + 365242.01767 * y - 0.11575 * (y * y) + 0.00337 * (y * y * y) + 0.00078 * (y * y * y * y); ++} ++ ++#if 0 ++static double mean_winter_solstice (unsigned year) ++{ ++ double y = year; ++ y -= 2000; ++ y *= 0.001; ++ return 2451900.05952 + 365242.74049 * y - 0.06223 * (y * y) - 0.00823 * (y * y * y) + 0.00032 * (y * y * y * y); ++} ++#endif ++ ++static double orbital_periodic_terms (double t) ++{ ++#define N 24 ++ const double A[N] = {485, 203, 199, 182, 156, 136, 77, 74, 70, 58, 52, 50, 45, ++ 44, 29, 18, 17, 16, 14, 12, 12, 12, 9, 8 ++ }; ++ const double B[N] = {D2R (324.96), D2R (337.23), D2R (342.08), D2R (27.85), ++ D2R (73.14), D2R (171.52), D2R (222.54), D2R (296.72), ++ D2R (243.58), D2R (119.81), D2R (297.17), D2R (21.02), ++ D2R (247.54), D2R (325.15), D2R (60.93), D2R (155.12), ++ D2R (288.79), D2R (198.04), D2R (199.76), D2R (95.39), ++ D2R (287.11), D2R (320.81), D2R (227.73), D2R (15.45) ++ }; ++ const double C[N] = {D2R (1934.136), D2R (32964.467), D2R (20.186), ++ D2R (445267.112), D2R (45036.886), D2R (22518.443), ++ D2R (65928.934), D2R (3034.906), D2R (9037.513), ++ D2R (33718.147), D2R (150.678), D2R (2281.226), ++ D2R (29929.562), D2R (31555.956), D2R (4443.417), ++ D2R (67555.328), D2R (4562.452), D2R (62894.029), ++ D2R (31436.921), D2R (14577.848), D2R (31931.756), ++ D2R (34777.259), D2R (1222.114), D2R (16859.074) ++ }; ++ double s = 0; ++ unsigned i; ++ ++ for (i = 0; i < N; ++i) ++ s += A[i] * cos (B[i] + (C[i] * t)); ++ ++ return s; ++} ++ ++ ++static double mean_to_real (double j0) ++{ ++ ++ double t = (j0 - 2451545.) / 36525.; ++ double w = D2R ((35999.373 * t) - 2.47); ++ double dl = 1 + 0.0334 * cos (w) + 0.0007 * cos (2. * w); ++ double s = orbital_periodic_terms (t); ++ ++#if 0 ++ printf ("j0=%.6f\r\n", j0); ++ printf ("t=%.6f\r\n", t); ++ printf ("w=%.6f\r\n", w); ++ printf ("dl=%.6f\r\n", dl); ++ printf ("s=%.6f\r\n", s); ++#endif ++ ++ return j0 + ((0.00001 * s) / dl); ++} ++ ++static double autumnal_equinox (unsigned y) ++{ ++ return mean_to_real (mean_autumnal_equinox (y)); ++ // return mean_to_real (mean_summer_solstice (y)); ++} ++ +diff --git a/movement/watch_faces/complication/metric_face.c b/movement/watch_faces/complication/metric_face.c +new file mode 100644 +index 0000000..9eaafbf +--- /dev/null ++++ b/movement/watch_faces/complication/metric_face.c +@@ -0,0 +1,198 @@ ++#include ++#include ++#include ++#include "watch.h" ++#include "watch_utility.h" ++#include "vsop87a_micro.h" // smaller size, less accurate ++#include "vsop87a_milli.h" ++#include "astrolib.h" ++#include "metric_face.h" ++ ++#define RATIO 8 ++ ++#include "equinox.c" ++ ++static const char *days[10] = ++ { "Pr", "Du", "Tr", "Qa", "Qi", "SH", "Sp", "Oc", "No", "De" }; ++ ++ ++static uint32_t ++jd_to_timestamp (double tjd) ++{ ++ tjd -= 2440587.5; ++ tjd *= 86400.; ++ return (uint32_t) floor (tjd); ++} ++ ++static uint32_t ++timestamp_start_of_year (int y) ++{ ++ double julian_equinox = autumnal_equinox (y); ++ julian_equinox += (2.3372305555 / 360); /* Offset of paris meridian from greenwich meridian */ ++ return jd_to_timestamp (julian_equinox); ++} ++ ++static int ++days_since_equinox (watch_date_time date_time) ++{ ++ uint32_t now = watch_utility_date_time_to_unix_time (date_time, 0); ++ uint32_t start_of_year = ++ timestamp_start_of_year (date_time.unit.year + 2020); ++ ++ start_of_year/=86400; ++ start_of_year*=86400; ++ ++ if (start_of_year > now) ++ start_of_year = ++ timestamp_start_of_year (date_time.unit.year + 2020 - 1); ++ ++ now -= start_of_year; ++ ++ now /= 86400; ++ ++ return (int) now; ++} ++ ++static void ++calculate_metric_date (metric_state_t * state, watch_date_time date_time) ++{ ++ int dse = days_since_equinox (date_time); ++ ++ state->m_day = (dse % 30) + 1; ++ state->m_wday = (dse % 10); ++ state->c_day = date_time.unit.day; ++ ++} ++ ++ ++static uint32_t ++date_time_to_ds (watch_date_time dt) ++{ ++ uint32_t ret; ++ ret = dt.unit.hour; ++ ret *= 60; ++ ret += dt.unit.minute; ++ ret *= 60; ++ ret += dt.unit.second; ++ return ret; ++} ++ ++static void ++_metric_face_sync (movement_settings_t * settings, metric_state_t * state) ++{ ++ watch_date_time date_time = watch_rtc_get_date_time (); ++ ++ (void) settings; ++ ++ if (date_time.unit.day != state->c_day) ++ calculate_metric_date (state, date_time); ++ ++ state->dt = date_time_to_ds (date_time) * RATIO; ++ state->resync_at = state->dt * (3600 * RATIO); ++ if (state->resync_at > (86400 * RATIO)) ++ state->resync_at = (86400 * RATIO); ++ ++} ++ ++static void ++_metric_face_update (movement_event_t event, movement_settings_t * settings, ++ metric_state_t * state, int show_secs) ++{ ++ uint64_t v; ++ char buf[14]; ++ ++ (void) event; ++ ++ if (state->dt >= state->resync_at) ++ _metric_face_sync (settings, state); ++ ++ v = state->dt; ++ v *= (uint64_t) 100000; ++ v /= (uint64_t) (RATIO * 86400); ++ ++ ++#if 0 ++ { ++ watch_date_time date_time = watch_rtc_get_date_time (); ++ printf ("%d %d\n", state->dt, date_time_to_ds (date_time) * RATIO); ++ } ++#endif ++ ++ ++ sprintf (buf, "%s%2d %05d", days[state->m_wday], (int) state->m_day, ++ (int) v); ++ ++ if (!show_secs) ++ { ++ buf[8] = ' '; ++ buf[9] = ' '; ++ } ++ ++ watch_display_string (buf, 0); ++} ++ ++void ++metric_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 (metric_state_t)); ++ memset (*context_ptr, 0, sizeof (metric_state_t)); ++ } ++} ++ ++void ++metric_face_activate (movement_settings_t * settings, void *context) ++{ ++ metric_state_t *state = (metric_state_t *) context; ++ (void) settings; ++ movement_request_tick_frequency (RATIO); ++ state->resync_at = 0; ++} ++ ++bool ++metric_face_loop (movement_event_t event, movement_settings_t * settings, ++ void *context) ++{ ++ (void) settings; ++ metric_state_t *state = (metric_state_t *) context; ++ ++ switch (event.event_type) ++ { ++ case EVENT_ACTIVATE: ++ watch_set_colon (); ++ /*fall through */ ++ case EVENT_TICK: ++ state->dt++; ++ _metric_face_update (event, settings, state, 1); ++ break; ++ case EVENT_LOW_ENERGY_UPDATE: ++ state->dt += RATIO * 60; ++ _metric_face_update (event, settings, state, 0); ++ break; ++ case EVENT_ALARM_BUTTON_UP: ++ break; ++ case EVENT_ALARM_LONG_PRESS: ++ break; ++ case EVENT_TIMEOUT: ++ state->resync_at = 0; ++ break; ++ default: ++ movement_default_loop_handler (event, settings); ++ break; ++ } ++ ++ return true; ++} ++ ++void ++metric_face_resign (movement_settings_t * settings, void *context) ++{ ++ (void) settings; ++ metric_state_t *state = (metric_state_t *) context; ++ state->resync_at = 0; ++ state->c_day = 0; ++} +diff --git a/movement/watch_faces/complication/metric_face.h b/movement/watch_faces/complication/metric_face.h +new file mode 100644 +index 0000000..1968e38 +--- /dev/null ++++ b/movement/watch_faces/complication/metric_face.h +@@ -0,0 +1,51 @@ ++/* ++ * 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 METRIC_FACE_H_ ++#define METRIC_FACE_H_ ++ ++#include "movement.h" ++ ++typedef struct { ++ uint32_t dt; ++ uint32_t resync_at; ++ uint32_t m_day; ++ uint32_t m_wday; ++ uint32_t c_day; ++} metric_state_t; ++ ++void metric_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); ++void metric_face_activate(movement_settings_t *settings, void *context); ++bool metric_face_loop(movement_event_t event, movement_settings_t *settings, void *context); ++void metric_face_resign(movement_settings_t *settings, void *context); ++ ++#define metric_face ((const watch_face_t){ \ ++ metric_face_setup, \ ++ metric_face_activate, \ ++ metric_face_loop, \ ++ metric_face_resign, \ ++ NULL, \ ++}) ++ ++#endif // METRIC_FACE_H_ diff --git a/main/moon b/main/moon new file mode 100644 index 0000000..0374f01 --- /dev/null +++ b/main/moon @@ -0,0 +1,601 @@ +diff --git a/movement/lib/sunriset/moonriset.c b/movement/lib/sunriset/moonriset.c +new file mode 100644 +index 0000000..ded9f33 +--- /dev/null ++++ b/movement/lib/sunriset/moonriset.c +@@ -0,0 +1,491 @@ ++#include ++#include ++#include "sunriset.h" ++ ++ ++#define E0BASE ((21.448 / 60. + 26.) / 60. + 23.) ++#define MOON_RADIUS 3474.8 ++ ++#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) ++ ++#define days_since_2000_Jan_0(y,m,d) \ ++ (367L*(y)-((7*((y)+(((m)+9)/12)))/4)+((275*(m))/9)+(d)-730530L) ++ ++typedef struct ++{ ++ int d; ++ int m; ++ int mprime; ++ int f; ++ int csin; ++ int ccos; ++} Table; ++ ++static const Table table_47a[] = { ++ {0, 0, 1, 0, 6288774, -20905355}, ++ {2, 0, -1, 0, 1274027, -3699111}, ++ {2, 0, 0, 0, 658314, -2955968}, ++ {0, 0, 2, 0, 213618, -569925}, ++ {0, 1, 0, 0, -185116, 48888}, ++ {0, 0, 0, 2, -114332, -3149}, ++ {2, 0, -2, 0, 58793, 246158}, ++ {2, -1, -1, 0, 57066, -152138}, ++ {2, 0, 1, 0, 53322, -170733}, ++ {2, -1, 0, 0, 45758, -204586}, ++ {0, 1, -1, 0, -40923, -129620}, ++ {1, 0, 0, 0, -34720, 108743}, ++ {0, 1, 1, 0, -30383, 104755}, ++ {2, 0, 0, -2, 15327, 10321}, ++ {0, 0, 1, 2, -12528, 0}, ++ {0, 0, 1, -2, 10980, 79661}, ++ {4, 0, -1, 0, 10675, -34782}, ++ {0, 0, 3, 0, 10034, -23210}, ++ {4, 0, -2, 0, 8548, -21636}, ++ {2, 1, -1, 0, -7888, 24208}, ++ {2, 1, 0, 0, -6766, 30824}, ++ {1, 0, -1, 0, -5163, -8379}, ++ {1, 1, 0, 0, 4987, -16675}, ++ {2, -1, 1, 0, 4036, -12831}, ++ {2, 0, 2, 0, 3994, -10445}, ++ {4, 0, 0, 0, 3861, -11650}, ++ {2, 0, -3, 0, 3665, 14403}, ++ {0, 1, -2, 0, -2689, -7003}, ++ {2, 0, -1, 2, -2602, 0}, ++ {2, -1, -2, 0, 2390, 10056}, ++ {1, 0, 1, 0, -2348, 6322}, ++ {2, -2, 0, 0, 2236, -9884}, ++ {0, 1, 2, 0, -2120, 5751}, ++ {0, 2, 0, 0, -2069, 0}, ++ {2, -2, -1, 0, 2048, -4950}, ++ {2, 0, 1, -2, -1773, 4130}, ++ {2, 0, 0, 2, -1595, 0}, ++ {4, -1, -1, 0, 1215, -3958}, ++ {0, 0, 2, 2, -1110, 0}, ++ {3, 0, -1, 0, -892, 3258}, ++ {2, 1, 1, 0, -810, 2616}, ++ {4, -1, -2, 0, 759, -1897}, ++ {0, 2, -1, 0, -713, -2117}, ++ {2, 2, -1, 0, -700, 2354}, ++ {2, 1, -2, 0, 691, 0}, ++ {2, -1, 0, -2, 596, 0}, ++ {4, 0, 1, 0, 549, -1423}, ++ {0, 0, 4, 0, 537, -1117}, ++ {4, -1, 0, 0, 520, -1571}, ++ {1, 0, -2, 0, -487, -1739}, ++ {2, 1, 0, -2, -399, 0}, ++ {0, 0, 2, -2, -381, -4421}, ++ {1, 1, 1, 0, 351, 0}, ++ {3, 0, -2, 0, -340, 0}, ++ {4, 0, -3, 0, 330, 0}, ++ {2, -1, 2, 0, 327, 0}, ++ {0, 2, 1, 0, -323, 1165}, ++ {1, 1, -1, 0, 299, 0}, ++ {2, 0, 3, 0, 294, 0}, ++ {2, 0, -1, -2, 0, 8752} ++}; ++ ++static const Table table_47b[] = { ++ {0, 0, 0, 1, 5128122, 0}, ++ {0, 0, 1, 1, 280602, 0}, ++ {0, 0, 1, -1, 277693, 0}, ++ {2, 0, 0, -1, 173237, 0}, ++ {2, 0, -1, 1, 55413, 0}, ++ {2, 0, -1, -1, 46271, 0}, ++ {2, 0, 0, 1, 32573, 0}, ++ {0, 0, 2, 1, 17198, 0}, ++ {2, 0, 1, -1, 9266, 0}, ++ {0, 0, 2, -1, 8822, 0}, ++ {2, -1, 0, -1, 8216, 0}, ++ {2, 0, -2, -1, 4324, 0}, ++ {2, 0, 1, 1, 4200, 0}, ++ {2, 1, 0, -1, -3359, 0}, ++ {2, -1, -1, 1, 2463, 0}, ++ {2, -1, 0, 1, 2211, 0}, ++ {2, -1, -1, -1, 2065, 0}, ++ {0, 1, -1, -1, -1870, 0}, ++ {4, 0, -1, -1, 1828, 0}, ++ {0, 1, 0, 1, -1794, 0}, ++ {0, 0, 0, 3, -1749, 0}, ++ {0, 1, -1, 1, -1565, 0}, ++ {1, 0, 0, 1, -1491, 0}, ++ {0, 1, 1, 1, -1475, 0}, ++ {0, 1, 1, -1, -1410, 0}, ++ {0, 1, 0, -1, -1344, 0}, ++ {1, 0, 0, -1, -1335, 0}, ++ {0, 0, 3, 1, 1107, 0}, ++ {4, 0, 0, -1, 1021, 0}, ++ {4, 0, -1, 1, 833, 0}, ++ {0, 0, 1, -3, 777, 0}, ++ {4, 0, -2, 1, 671, 0}, ++ {2, 0, 0, -3, 607, 0}, ++ {2, 0, 2, -1, 596, 0}, ++ {2, -1, 1, -1, 491, 0}, ++ {2, 0, -2, 1, -451, 0}, ++ {0, 0, 3, -1, 439, 0}, ++ {2, 0, 2, 1, 422, 0}, ++ {2, 0, -3, -1, 421, 0}, ++ {2, 1, -1, 1, -366, 0}, ++ {2, 1, 0, 1, -351, 0}, ++ {4, 0, 0, 1, 331, 0}, ++ {2, -1, 1, 1, 315, 0}, ++ {2, -2, 0, -1, 302, 0}, ++ {0, 0, 1, 3, -283, 0}, ++ {2, 1, 1, -1, -229, 0}, ++ {1, 1, 0, -1, 223, 0}, ++ {1, 1, 0, 1, 223, 0}, ++ {0, 1, -2, -1, -220, 0}, ++ {2, 1, -1, -1, -220, 0}, ++ {1, 0, 1, 1, -185, 0}, ++ {2, -1, -2, -1, 181, 0}, ++ {0, 1, 2, 1, -177, 0}, ++ {4, 0, -2, -1, 176, 0}, ++ {4, -1, -1, -1, 166, 0}, ++ {1, 0, 1, -1, -164, 0}, ++ {4, 0, 1, -1, 132, 0}, ++ {1, 0, -1, -1, -119, 0}, ++ {4, -1, 0, -1, 115, 0}, ++ {2, -2, 0, 1, 107, 0}, ++}; ++ ++ ++static double ++deg2rad (double d) ++{ ++ return d * (M_PI / 180.); ++} ++ ++static double ++fold_deg2rad (double d) ++{ ++ d /= 360.; ++ d = d - floor (d); ++ return d * 2.0 * M_PI; ++} ++ ++ ++static void ++compute_table (const Table * t, unsigned n, double *ret_sin, double *ret_cos, ++ double D, double M, double Mprime, double F, double E, ++ double E2) ++{ ++ unsigned i; ++ double sigma_sin = 0; ++ double sigma_cos = 0; ++ ++ for (i = 0; i < n; ++i) ++ { ++ double csin = t[i].csin; ++ double ccos = t[i].ccos; ++ double arg = 0; ++ ++ switch (t[i].m) ++ { ++ case -2: ++ case 2: ++ csin *= E2; ++ ++ if (t[i].ccos) ++ ccos *= E2; ++ ++ break; ++ ++ case -1: ++ case 1: ++ csin *= E; ++ ++ if (t[i].ccos) ++ ccos *= E; ++ ++ break; ++ } ++ ++ if (t[i].d) ++ arg += D * (double) t[i].d; ++ ++ if (t[i].m) ++ arg += M * (double) t[i].m; ++ ++ if (t[i].mprime) ++ arg += Mprime * (double) t[i].mprime; ++ ++ if (t[i].f) ++ arg += F * (double) t[i].f; ++ ++ sigma_sin += csin * sin (arg); ++ ++ if (t[i].ccos) ++ sigma_cos += ccos * cos (arg); ++ } ++ ++ *ret_sin = sigma_sin; ++ ++ if (ret_cos) ++ *ret_cos = sigma_cos; ++} ++ ++ ++static int ++moon_above_horizon (double jd, double lst, double lat, int limb, double altit) ++{ ++ double T = (jd) / 36525.; ++ double L, Lprime, D, M, Mprime, F, A1, A2, A3, E, E2; ++ double sigma_l, sigma_r, sigma_b; ++ double lambda, beta, big_delta; ++ double omega, delta_psi, delta_epsilon; ++ double epsilon; ++ double alpha, delta; ++ ++ //printf("j0=%f T=%f lst=%f alit=%f\n",jd+2451545.,T,lst,altit); ++ ++ ++ // Sun's mean longitude ++ L = fold_deg2rad (36000.7698 * T + 280.4665); ++ ++ // Moon's mean longitude. ++ Lprime = fold_deg2rad ((((-(T / 65194000.) + 1. / 538841.) * T - 0.0015786) * T + 481267.88123421) * T + 218.3164477); // Meeus (47.1) ++ ++ // Moon's mean elongation. ++ D = fold_deg2rad ((((T / 113065000. + 1. / 545868.) * T - 0.0018819) * T + 445267.1114034) * T + 297.8501921); //Meeus (47.2) ++ ++ // Sun's mean anomaly. ++ M = fold_deg2rad (((T / 24490000. - 0.0001536) * T + 35999.0502909) * T + 357.5291092); // Meeus (47.3) ++ ++ // Moon's mean anomaly. ++ Mprime = fold_deg2rad ((((-T / 14712000. + 1. / 69699.) * T + 0.0087414) * T + 477198.8675055) * T + 134.9633964); // Meeus (47.4) ++ ++ // Moon's argument of latitude (mean distance ++ // from ascending node). ++ ++ F = fold_deg2rad ((((T / 863310000. - 1. / 3526000.) * T - 0.0036539) * T + 483202.0175233) * T + 93.2720950); // Meeus (47.5) ++ ++ // further arguments ++ A1 = fold_deg2rad (131.849 * T + 119.75); // Venus ++ A2 = fold_deg2rad (479264.290 * T + 53.09); // Jupiter ++ A3 = fold_deg2rad (481266.484 * T + 313.45); // undocumented ++ ++ // Eccentricity correction factor. ++ E = (-0.0000074 * T - 0.002516) * T + 1.; // Meeus (47.6) ++ E2 = E * E; ++ ++ ++ compute_table (table_47a, ARRAY_SIZE (table_47a), &sigma_l, &sigma_r, D, ++ M, Mprime, F, E, E2); ++ compute_table (table_47b, ARRAY_SIZE (table_47b), &sigma_b, (void *) 0, D, ++ M, Mprime, F, E, E2); ++ ++ sigma_l += 3958. * sin (A1) + 1962. * sin (Lprime - F) + 318. * sin (A2); ++ sigma_b += ++ -2235. * sin (Lprime) + 382. * sin (A3) + 175. * sin (A1 - F) + ++ 175. * sin (A1 + F) + 127. * sin (Lprime - Mprime) - ++ 115. * sin (Lprime + Mprime); ++ ++ // Coordinates of Moon (finally!) ++ ++ lambda = deg2rad (sigma_l / 1000000.) + Lprime; ++ beta = deg2rad (sigma_b / 1000000.); ++ big_delta = sigma_r / 1000. + 385000.56; ++ ++#if 0 ++ printf ("JDE=%+f\n", j0); ++ printf ("T =%+f\n", T); ++ printf ("L' =%+f\n", Lprime * (180 / M_PI)); ++ printf ("D =%+f\n", D * (180 / M_PI)); ++ printf ("M =%+f\n", M * (180 / M_PI)); ++ printf ("M' =%+f\n", Mprime * (180 / M_PI)); ++ printf ("F =%+f\n", F * (180 / M_PI)); ++ printf ("A1 =%+f\n", A1 * (180 / M_PI)); ++ printf ("A2 =%+f\n", A2 * (180 / M_PI)); ++ printf ("A3 =%+f\n", A3 * (180 / M_PI)); ++ printf ("E =%+f\n", E); ++ printf ("Sl =%+f\n", sigma_l); ++ printf ("Sb =%+f\n", sigma_b); ++ printf ("Sr =%+f\n", sigma_r); ++ ++ printf ("l=%+f\n", lambda * (180 / M_PI)); ++ printf ("b=%+f\n", beta * (180 / M_PI)); ++ printf ("D=%+f\n", big_delta); ++#endif ++ ++ ++ omega = ++ fold_deg2rad (((T / 450000 + .0020708) * T - 1934.136261) * T + ++ 125.04452); ++ ++ //budget - not doing the whole of chapter 22 ++ delta_psi = ++ deg2rad ((-17.20 * sin (omega) - 1.32 * sin (2 * L) - ++ 0.23 * sin (2 * Lprime) + 0.21 * sin (2 * omega)) / 3600.); ++ delta_epsilon = ++ deg2rad ((9.20 * cos (omega) + 0.57 * cos (2 * L) + ++ 0.10 * cos (2 * Lprime) - 0.09 * cos (2 * omega)) / 3600); ++ ++ lambda += delta_psi; ++ ++ epsilon = ++ deg2rad (((0.001813 * T - 0.00059) * T - 46.8150) * T / 3600 + ++ E0BASE); ++ epsilon += delta_epsilon; ++ ++#if 0 ++ printf ("delta_psi=%+f\n", delta_psi * (180 / M_PI)); ++ printf ("delta_epsilon=%+f\n", delta_epsilon * (180 / M_PI)); ++ printf ("epsilon=%+f\n", epsilon * (180 / M_PI)); ++#endif ++ ++ ++ alpha = ++ atan2 (sin (lambda) * cos (epsilon) - tan (beta) * sin (epsilon), ++ cos (lambda)); ++ delta = ++ asin (sin (beta) * cos (epsilon) + ++ cos (beta) * sin (epsilon) * sin (lambda)); ++ ++#if 0 ++ printf ("alpha=%+f\n", alpha * (180. / M_PI)); ++ printf ("delta=%+f\n", delta * (180. / M_PI)); ++#endif ++ ++ double H = deg2rad (lst) - alpha; ++ ++ lat = deg2rad (lat); ++ ++ double h = ++ asin (sin (lat) * sin (delta) + cos (lat) * cos (delta) * cos (H)); ++ ++// printf("rawh=%f\n",h); ++ ++ if (limb) ++ h += atan2 (MOON_RADIUS / 2, big_delta); ++ ++ h += deg2rad (altit); ++ ++ return h > 0; ++} ++ ++#if 0 ++double ++correct_refraction (double a) ++{ ++ ++ ++ if (a > ((-2.0 / 180.) * (M_PI))) ++ { ++ //double deg = a * (180./M_PI); ++ //double correction = deg2rad( (1.02 / tan (deg2rad (deg + 10.3/(deg + 5.11))) + .0019279)/60.); ++ //a+= deg2rad (correction / 60.); ++ a += 0.0002967 / tan (a + 0.00312536 / (a + 0.08901179)); ++ } ++ return a; ++} ++#endif ++ ++static double ++localSiderealTime (double jd, double longitude) ++{ ++ double lSideTime = (15.0L * (6.697374558L + 0.06570982441908L * jd + ++ remainder (jd, 1) * 24 + 12 + ++ 0.000026 * (jd / 36525) * (jd / 36525)) ++ - longitude) / 360; ++ lSideTime -= floor (lSideTime); ++ lSideTime *= 360; // Convert to degrees. ++//printf("lst %f %f => %f\n",jd+2451545.,longitude,lSideTime); ++ return (lSideTime); ++} ++ ++ ++int ++__moonriset__ (int year, int month, int day, int hour, int min, double lon, ++ double lat, double altit, int upper_limb, double *when) ++{ ++ double jd, jo, jt, o, step; ++ double lst; ++ int up, start_up = -1; ++ ++ jd = days_since_2000_Jan_0 (year, month, day) - 1.5; ++ ++ ++ jo = (double) min; ++ jo = (jo / 60.) + (double) hour; ++ jo = (jo / 24.); ++ ++ jt = jd + jo; ++ ++ ++ step = 0.1; ++ ++ for (o = 0; o < 2.5; o += step) ++ { ++ jt = jd + jo + o; ++ ++ ++ lst = localSiderealTime (jt, lon); ++ up = moon_above_horizon (jt, lst, lat, upper_limb, altit); ++ ++//printf("%f %f %d %d\n",jt,jt-jd,start_up,up); ++ ++ if (start_up == -1) ++ { ++ start_up = up; ++ continue; ++ } ++ ++ if (up != start_up) ++ { ++ if (step < 30. / 86400.) ++ break; ++ o -= step; ++ step *= 0.5; ++ } ++ } ++ ++ if (up == start_up) ++ { ++ return -1; ++ } ++//printf("moon goes to state %d at jd=%f jo=%f o=%f s=%f l=%f\n",up,jd,jo,o,jd+jo+o,jt); ++ *when = 24. * (o + jo); ++ return up; ++} ++ ++ ++#if 0 ++static int ++show_time (char *p, double s) ++{ ++ double h, m; ++ ++ if (s < 0) ++ s += 24.; ++ ++ h = floor (s); ++ s = (s - h) * 60.; ++ m = floor (s); ++ s = (s - m) * 60.; ++ ++ printf ("%s %02d:%02d:%08.5f\n", p, (int) h, (int) m, s); ++} ++ ++ ++int ++main (int argc, char *argv[]) ++{ ++ double rise, set; ++ ++ moonriset (2023, 9, 23, 15, 36, 0.1280, 52.2202, -19.152 / 60., 1, &rise, ++ &set); ++ show_time ("RISE ", rise); ++ show_time ("SET ", set); ++ ++ moonriset (2023, 9, 24, 0, 00, 0.1280, 52.2202, -19.152 / 60., 1, &rise, ++ &set); ++ show_time ("RISE ", rise); ++ show_time ("SET ", set); ++ ++ ++} ++ ++ ++ ++ ++ ++#endif +diff --git a/movement/lib/sunriset/sunriset.h b/movement/lib/sunriset/sunriset.h +index 7b2b6c8..8a79e88 100644 +--- a/movement/lib/sunriset/sunriset.h ++++ b/movement/lib/sunriset/sunriset.h +@@ -22,9 +22,13 @@ double __daylen__( int year, int month, int day, double lon, double lat, + double altit, int upper_limb ); + + int __sunriset__( int year, int month, int day, double lon, double lat, +- double altit, int upper_limb, double *rise, double *set ); ++ double altit, int upper_limb, double *rise, double *set); ++ ++int __moonriset__( int year, int month, int day, int hour, int min, double lon, double lat, ++ double altit, int upper_limb, double *when); + + void sun_RA_dec( double d, double *RA, double *dec, double *r ); ++void moon_RA_dec( double d, double *RA, double *dec, double *r ); + + double revolution( double x ); + +@@ -65,6 +69,12 @@ double GMST0( double d ); + __daylen__( year, month, day, lon, lat, -18.0, 0 ) + + ++ ++/* This macro computes times for moonrise/moonset. */ ++/* It's right according to meeus but it's not matching anytihng else */ ++#define moon_rise_set(year,month, day, hour,min, lon, lat, when) \ ++ __moonriset__( year, month, day, hour,min, lon, lat, -19.152/60.0, 1,when) ++ + /* This macro computes times for sunrise/sunset. */ + /* Sunrise/set is considered to occur when the Sun's upper limb is */ + /* 35 arc minutes below the horizon (this accounts for the refraction */ +diff --git a/movement/make/Makefile b/movement/make/Makefile +index 7110be2..db93b19 100644 +--- a/movement/make/Makefile ++++ b/movement/make/Makefile +@@ -41,6 +41,7 @@ SRCS += \ + ../lib/TOTP/TOTP.c \ + ../lib/base32/base32.c \ + ../lib/sunriset/sunriset.c \ ++ ../lib/sunriset/moonriset.c \ + ../lib/vsop87/vsop87a_milli.c \ + ../lib/astrolib/astrolib.c \ + ../lib/morsecalc/calc.c \ +diff --git a/movement/watch_faces/complication/sunrise_sunset_face.c b/movement/watch_faces/complication/sunrise_sunset_face.c +index 2a929c8..9bd3369 100644 +--- a/movement/watch_faces/complication/sunrise_sunset_face.c ++++ b/movement/watch_faces/complication/sunrise_sunset_face.c +@@ -78,6 +78,46 @@ static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_s + // 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; + ++ ++ if (state->rise_index == 2) { ++ int wot; ++ watch_clear_display(); ++ watch_start_character_blink('C', 100); ++ ++ wot = moon_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day,scratch_time.unit.hour,scratch_time.unit.minute, lon, lat, &rise); ++ watch_stop_blink(); ++ ++ rise += hours_from_utc; ++ if (rise>24.) { ++ scratch_time.unit.day++; ++ rise -= 24.; ++ } ++ 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); ++ ++ if (scratch_time.unit.minute == 60) { ++ scratch_time.unit.minute = 0; ++ scratch_time.unit.hour = (scratch_time.unit.hour + 1) % 24; ++ } ++ ++ watch_set_colon(); ++ ++ 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); ++ } ++ ++ sprintf(buf, "LU%2d%2d%02d%s", scratch_time.unit.day, scratch_time.unit.hour, scratch_time.unit.minute,wot ? "RI":"SE"); ++ watch_display_string(buf, 0); ++ return; ++ } ++ ++ + // 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); +@@ -369,7 +409,7 @@ bool sunrise_sunset_face_loop(movement_event_t event, movement_settings_t *setti + _sunrise_sunset_face_advance_digit(state); + _sunrise_sunset_face_update_settings_display(event, context); + } else { +- state->rise_index = (state->rise_index + 1) % 2; ++ state->rise_index = (state->rise_index + 1) % 3; + _sunrise_sunset_face_update(settings, state); + } + break; diff --git a/main/series b/main/series new file mode 100644 index 0000000..43d4273 --- /dev/null +++ b/main/series @@ -0,0 +1,8 @@ +jmm +default-to-gsm +fix-wakeup +fix-serial +metric +siderial +moon +endstop diff --git a/main/siderial b/main/siderial new file mode 100644 index 0000000..2a2b894 --- /dev/null +++ b/main/siderial @@ -0,0 +1,273 @@ +diff --git a/movement/alt_fw/jmm.h b/movement/alt_fw/jmm.h +index 5c2cee7..061d058 100644 +--- a/movement/alt_fw/jmm.h ++++ b/movement/alt_fw/jmm.h +@@ -12,6 +12,7 @@ const watch_face_t watch_faces[] = { + world_clock_face, + metric_face, + totp_face_lfs, ++ siderial_face, + moon_phase_face, + sunrise_sunset_face, + decimal_time_face, +diff --git a/movement/make/Makefile b/movement/make/Makefile +index e131bbb..7110be2 100644 +--- a/movement/make/Makefile ++++ b/movement/make/Makefile +@@ -121,6 +121,7 @@ SRCS += \ + ../watch_faces/clock/decimal_time_face.c \ + ../watch_faces/clock/wyoscan_face.c \ + ../watch_faces/complication/metric_face.c \ ++ ../watch_faces/complication/siderial_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 94316ce..c605743 100644 +--- a/movement/movement_faces.h ++++ b/movement/movement_faces.h +@@ -96,6 +96,7 @@ + #include "decimal_time_face.h" + #include "wyoscan_face.h" + #include "metric_face.h" ++#include "siderial_face.h" + // New includes go above this line. + + #endif // MOVEMENT_FACES_H_ +diff --git a/movement/watch_faces/complication/siderial_face.c b/movement/watch_faces/complication/siderial_face.c +new file mode 100644 +index 0000000..b60f4a9 +--- /dev/null ++++ b/movement/watch_faces/complication/siderial_face.c +@@ -0,0 +1,175 @@ ++#include ++#include ++#include ++#include "watch.h" ++#include "watch_utility.h" ++#include "vsop87a_micro.h" // smaller size, less accurate ++#include "vsop87a_milli.h" ++#include "astrolib.h" ++#include "siderial_face.h" ++ ++#define TICK_MAX 14400 ++ ++ ++static uint32_t ++date_time_to_ds (watch_date_time dt) ++{ ++ uint32_t ret; ++ ret = dt.unit.hour; ++ ret *= 60; ++ ret += dt.unit.minute; ++ ret *= 60; ++ ret += dt.unit.second; ++ return ret; ++} ++ ++static void ++_siderial_face_recalculate (movement_settings_t * settings, ++ siderial_state_t * state) ++{ ++ watch_date_time date_time = watch_rtc_get_date_time (); ++ movement_location_t movement_location; ++ ++ double jd, days; ++ uint32_t timestamp = watch_utility_date_time_to_unix_time (date_time, ++ movement_timezone_offsets ++ [settings->bit. ++ time_zone] * ++ 60); ++ ++ state->ref_ds = date_time_to_ds (date_time); ++ ++ date_time = watch_utility_date_time_from_unix_time (timestamp, 0); ++ jd = astro_convert_date_to_julian_date (date_time.unit.year + ++ WATCH_RTC_REFERENCE_YEAR, ++ date_time.unit.month, ++ date_time.unit.day, ++ date_time.unit.hour, ++ date_time.unit.minute, ++ date_time.unit.second); ++ ++ jd -= .5; ++ ++ if (state->lst) ++ { ++ movement_location = (movement_location_t) watch_get_backup_data (1); ++ jd += ((double) movement_location.bit.longitude) / 36000.; ++ } ++ ++ ++ state->ref_st = (uint32_t) (modf (jd, &days) * 86400. + .5); ++ state->ticks = 0; ++} ++ ++static void ++_siderial_face_update (movement_event_t event, movement_settings_t * settings, ++ siderial_state_t * state, int show_secs) ++{ ++ watch_date_time date_time = watch_rtc_get_date_time (); ++ uint32_t ds = date_time_to_ds (date_time); ++ char buf[14]; ++ int sh, sm, ss; ++ ++ (void) event; ++ ++ if (state->ticks >= TICK_MAX) ++ _siderial_face_recalculate (settings, state); ++ ++ ++ ss = state->ref_st + (int) (.5 + ++ (86164.0905 / 86400.) * (double) (ds - ++ state->ref_ds)); ++ if (ss > 86400.) ++ ss -= 86400.; ++#if 0 //The compiler is too dumb to realize the bounds so generates a Werror for the sprintf ++ sm = ss / 60; ++ ss -= sm * 60; ++ sh = sm / 60; ++ sm -= sh * 60; ++#else ++ sm = ss / 60; ++ ss %= 60; ++ sh = sm / 60; ++ sm %= 60; ++ sh %= 64; ++#endif ++ ++ sprintf (buf, "ST %c%02d%02d%02d", state->lst ? 'L' : ' ', sh, sm, ss); ++ ++ if (!show_secs) ++ { ++ buf[8] = ' '; ++ buf[9] = ' '; ++ } ++ ++ watch_display_string (buf, 0); ++} ++ ++void ++siderial_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 (siderial_state_t)); ++ memset (*context_ptr, 0, sizeof (siderial_state_t)); ++ } ++} ++ ++void ++siderial_face_activate (movement_settings_t * settings, void *context) ++{ ++ siderial_state_t *state = (siderial_state_t *) context; ++ (void) settings; ++ movement_request_tick_frequency (2); ++ state->ticks = TICK_MAX; ++} ++ ++bool ++siderial_face_loop (movement_event_t event, movement_settings_t * settings, ++ void *context) ++{ ++ (void) settings; ++ siderial_state_t *state = (siderial_state_t *) context; ++ ++ switch (event.event_type) ++ { ++ case EVENT_ACTIVATE: ++ watch_set_colon (); ++ watch_set_indicator (WATCH_INDICATOR_24H); ++ /*fall through */ ++ case EVENT_TICK: ++ state->ticks++; ++ _siderial_face_update (event, settings, state, 1); ++ break; ++ case EVENT_LOW_ENERGY_UPDATE: ++ state->ticks += 60; ++ _siderial_face_update (event, settings, state, 0); ++ break; ++ case EVENT_ALARM_BUTTON_UP: ++ state->lst ^= 1; ++ state->ticks = TICK_MAX; ++ _siderial_face_update (event, settings, state, 1); ++ break; ++ case EVENT_ALARM_LONG_PRESS: ++ break; ++ case EVENT_TIMEOUT: ++ state->ticks = TICK_MAX; ++ break; ++ default: ++ movement_default_loop_handler (event, settings); ++ break; ++ } ++ ++ return true; ++} ++ ++void ++siderial_face_resign (movement_settings_t * settings, void *context) ++{ ++ (void) settings; ++ siderial_state_t *state = (siderial_state_t *) context; ++ state->ticks = TICK_MAX; ++} +diff --git a/movement/watch_faces/complication/siderial_face.h b/movement/watch_faces/complication/siderial_face.h +new file mode 100644 +index 0000000..a4ae67f +--- /dev/null ++++ b/movement/watch_faces/complication/siderial_face.h +@@ -0,0 +1,50 @@ ++/* ++ * 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 SIDERIAL_FACE_H_ ++#define SIDERIAL_FACE_H_ ++ ++#include "movement.h" ++ ++typedef struct { ++ int lst; ++ uint32_t ticks; ++ uint32_t ref_ds; ++ uint32_t ref_st; ++} siderial_state_t; ++ ++void siderial_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); ++void siderial_face_activate(movement_settings_t *settings, void *context); ++bool siderial_face_loop(movement_event_t event, movement_settings_t *settings, void *context); ++void siderial_face_resign(movement_settings_t *settings, void *context); ++ ++#define siderial_face ((const watch_face_t){ \ ++ siderial_face_setup, \ ++ siderial_face_activate, \ ++ siderial_face_loop, \ ++ siderial_face_resign, \ ++ NULL, \ ++}) ++ ++#endif // SIDERIAL_FACE_H_ -- cgit v1.2.3