summaryrefslogtreecommitdiffstats
path: root/main/siderial
diff options
context:
space:
mode:
Diffstat (limited to 'main/siderial')
-rw-r--r--main/siderial273
1 files changed, 273 insertions, 0 deletions
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 <stdlib.h>
++#include <string.h>
++#include <math.h>
++#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_