From 81b486e475463a58cda2b706dcf4fb1a39f8612f Mon Sep 17 00:00:00 2001 From: James McKenzie Date: Mon, 2 Oct 2023 11:37:39 +0100 Subject: rename --- main/default-to-gsm | 20 -- main/default-to-gsm.patch | 20 ++ main/fix-serial | 97 -------- main/fix-serial.patch | 97 ++++++++ main/fix-wakeup | 42 ---- main/fix-wakeup.patch | 42 ++++ main/jmm | 57 ----- main/jmm.patch | 57 +++++ main/metric | 404 ------------------------------- main/metric.patch | 404 +++++++++++++++++++++++++++++++ main/moon | 601 ---------------------------------------------- main/moon.patch | 601 ++++++++++++++++++++++++++++++++++++++++++++++ main/series | 14 +- main/siderial | 273 --------------------- main/siderial.patch | 273 +++++++++++++++++++++ 15 files changed, 1501 insertions(+), 1501 deletions(-) delete mode 100644 main/default-to-gsm create mode 100644 main/default-to-gsm.patch delete mode 100644 main/fix-serial create mode 100644 main/fix-serial.patch delete mode 100644 main/fix-wakeup create mode 100644 main/fix-wakeup.patch delete mode 100644 main/jmm create mode 100644 main/jmm.patch delete mode 100644 main/metric create mode 100644 main/metric.patch delete mode 100644 main/moon create mode 100644 main/moon.patch delete mode 100644 main/siderial create mode 100644 main/siderial.patch diff --git a/main/default-to-gsm b/main/default-to-gsm deleted file mode 100644 index 98de0a3..0000000 --- a/main/default-to-gsm +++ /dev/null @@ -1,20 +0,0 @@ -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/default-to-gsm.patch b/main/default-to-gsm.patch new file mode 100644 index 0000000..98de0a3 --- /dev/null +++ b/main/default-to-gsm.patch @@ -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/fix-serial b/main/fix-serial deleted file mode 100644 index 80b11c5..0000000 --- a/main/fix-serial +++ /dev/null @@ -1,97 +0,0 @@ -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-serial.patch b/main/fix-serial.patch new file mode 100644 index 0000000..80b11c5 --- /dev/null +++ b/main/fix-serial.patch @@ -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 deleted file mode 100644 index e3933a2..0000000 --- a/main/fix-wakeup +++ /dev/null @@ -1,42 +0,0 @@ -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/fix-wakeup.patch b/main/fix-wakeup.patch new file mode 100644 index 0000000..e3933a2 --- /dev/null +++ b/main/fix-wakeup.patch @@ -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 deleted file mode 100644 index 0bde666..0000000 --- a/main/jmm +++ /dev/null @@ -1,57 +0,0 @@ -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/jmm.patch b/main/jmm.patch new file mode 100644 index 0000000..0bde666 --- /dev/null +++ b/main/jmm.patch @@ -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 deleted file mode 100644 index cbf0287..0000000 --- a/main/metric +++ /dev/null @@ -1,404 +0,0 @@ -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/metric.patch b/main/metric.patch new file mode 100644 index 0000000..cbf0287 --- /dev/null +++ b/main/metric.patch @@ -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 deleted file mode 100644 index 0374f01..0000000 --- a/main/moon +++ /dev/null @@ -1,601 +0,0 @@ -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/moon.patch b/main/moon.patch new file mode 100644 index 0000000..0374f01 --- /dev/null +++ b/main/moon.patch @@ -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 index 43d4273..e0d931c 100644 --- a/main/series +++ b/main/series @@ -1,8 +1,8 @@ -jmm -default-to-gsm -fix-wakeup -fix-serial -metric -siderial -moon +jmm.patch +default-to-gsm.patch +fix-wakeup.patch +fix-serial.patch +metric.patch +siderial.patch +moon.patch endstop diff --git a/main/siderial b/main/siderial deleted file mode 100644 index 2a2b894..0000000 --- a/main/siderial +++ /dev/null @@ -1,273 +0,0 @@ -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_ diff --git a/main/siderial.patch b/main/siderial.patch new file mode 100644 index 0000000..2a2b894 --- /dev/null +++ b/main/siderial.patch @@ -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