Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions mk4-time/Core/Inc/astro.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ int moon_phase_index(double phase); /* 0..7, see ASTRO_MOON_NAMES
/* (d) Equation of time in minutes (+ = apparent sun ahead of mean/clock sun). */
double equation_of_time(double unix_s);

double local_sidereal_time(double unix_s, double lon); /* LMST, hours [0,24), lon E+ */
double local_solar_time(double unix_s, double lon); /* apparent solar, hours [0,24) */

/* (e) 6-character Maidenhead locator for (lat, lon). out must hold >= 7 bytes.
* Writes "----\0" if either coordinate is non-finite. */
void maidenhead(double lat, double lon, char out[7]);
Expand Down
9 changes: 8 additions & 1 deletion mk4-time/Core/Inc/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,20 @@ enum {
MODE_GRID, // Maidenhead grid locator
MODE_LATLON, // latitude / longitude, auto-paged

// Alternate-timebase TIME-ROW modes: the big digits tick Local Sidereal Time or
// apparent solar ("sundial") time, reseeded from the GPS-disciplined second; the
// date row keeps the civil date and a dedicated colon animation marks the mode.
MODE_LST,
MODE_SUNDIAL,

NUM_DISPLAY_MODES
};

enum {
COUNT_NORMAL =0,
COUNT_HIDDEN,
COUNT_DOWN
COUNT_DOWN,
COUNT_ALT // time row driven by the alternate timebase (MODE_LST / MODE_SUNDIAL)
};

enum {
Expand Down
36 changes: 35 additions & 1 deletion mk4-time/Core/Src/astro.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ const char *const ASTRO_MOON_NAMES[8] = {

static double days_since_j2000(double unix_s) { return (unix_s - J2000_UNIX) / 86400.0; }

/* Greenwich Mean Sidereal Time in hours [0,24). Factored out so sun_az_el and
* local_sidereal_time share one series and can never drift apart. The quadratic
* term keeps truncation below ~1 ms for decades (the linear series alone drifts to
* ~10 ms by 2033). Note the input is GPS-derived UTC, not UT1: true-sky sidereal
* accuracy is floored by DUT1 (up to +/-0.9 s) by design. */
static double gmst_hours(double n) {
double T = n / 36525.0;
double g = fmod(18.697374558 + 24.06570982441908 * n + 0.000026 * T * T, 24.0);
if (g < 0.0) g += 24.0;
if (g >= 24.0) g -= 24.0;
return g;
}

/* The shared low-precision solar block: from days-since-J2000 produce mean
* longitude L, anomaly g, ecliptic longitude lambda, obliquity eps, and the
* apparent right ascension alpha (deg) and declination delta (rad). */
Expand All @@ -46,7 +59,7 @@ void sun_az_el(double lat, double lon, double unix_s, double *az, double *el) {
double alpha, delta;
sun_ecliptic(n, NULL, NULL, NULL, NULL, &alpha, &delta);

double gmst = fmod(18.697374558 + 24.06570982441908 * n, 24.0); /* GMST in hours, used as-is */
double gmst = gmst_hours(n); /* hours */
double lst = gmst * 15.0 + lon; /* degrees */
double ha = (lst - alpha) * DEG; /* radians */

Expand All @@ -67,6 +80,27 @@ double equation_of_time(double unix_s) {
return 4.0 * diff; /* minutes */
}

/* Local Mean Sidereal Time, decimal hours [0,24). LMST = GMST + longitude/15
* (east-positive). Anchors: GMST(J2000.0) = 18.697374558 h (IAU); Meeus ex. 12.b. */
double local_sidereal_time(double unix_s, double lon) {
double lst = fmod(gmst_hours(days_since_j2000(unix_s)) + lon / 15.0, 24.0);
if (lst < 0.0) lst += 24.0;
if (lst >= 24.0) lst -= 24.0; /* fmod residue can round the wrap to exactly 24.0 */
return lst; /* hours [0,24) */
}

/* Local apparent solar ("sundial") time, decimal hours [0,24).
* Apparent solar = mean solar (UTC shifted by longitude) + equation of time.
* At the sun's meridian transit this equals 12.0 exactly, consistent with
* sun_times()'s solar_noon = 12 - eot/60 - lon/15. */
double local_solar_time(double unix_s, double lon) {
double utc_h = fmod(unix_s / 3600.0, 24.0);
double t = fmod(utc_h + lon / 15.0 + equation_of_time(unix_s) / 60.0, 24.0);
if (t < 0.0) t += 24.0;
if (t >= 24.0) t -= 24.0;
return t; /* hours [0,24) */
}

int sun_times(double lat, double lon, double unix_s,
double *sunrise, double *sunset, double *solar_noon,
double *civil_dusk, double *nautical_dusk, double *golden_dusk) {
Expand Down
Loading