Skip to content

Latest commit

 

History

History
219 lines (172 loc) · 6.42 KB

File metadata and controls

219 lines (172 loc) · 6.42 KB

Location Customization Plan

Overview

Make the tide clock configurable for any location by generating a single location_config.h from scripts.

Supported Timezones

For simplicity, we'll support these common coastal timezone rules:

Rule Winter Offset Summer Offset DST Transition
UTC +0 +0 None
UK +0 (GMT) +1 (BST) Last Sun Mar/Oct
EU_CENTRAL +1 (CET) +2 (CEST) Last Sun Mar/Oct
EU_EASTERN +2 (EET) +3 (EEST) Last Sun Mar/Oct
US_EASTERN -5 (EST) -4 (EDT) 2nd Sun Mar / 1st Sun Nov
US_CENTRAL -6 (CST) -5 (CDT) 2nd Sun Mar / 1st Sun Nov
US_MOUNTAIN -7 (MST) -6 (MDT) 2nd Sun Mar / 1st Sun Nov
US_PACIFIC -8 (PST) -7 (PDT) 2nd Sun Mar / 1st Sun Nov
US_ALASKA -9 (AKST) -8 (AKDT) 2nd Sun Mar / 1st Sun Nov
US_HAWAII -10 (HST) -10 (HST) None
AU_EASTERN +10 (AEST) +11 (AEDT) 1st Sun Oct / 1st Sun Apr
AU_WESTERN +8 (AWST) +8 (AWST) None
NZ +12 (NZST) +13 (NZDT) Last Sun Sep / 1st Sun Apr

Users in unsupported timezones can use UTC and accept times in UTC, or request support.

Data Sources

US Locations (NOAA API)

  • NOAA CO-OPS provides harmonic constituents directly via API
  • No fitting required - just fetch and convert
  • ~3000 tide stations available
  • Script: scripts/fetch_noaa.py

Other Locations (Manual Data)

  • User supplies high/low water CSV data (or minute-by-minute)
  • Run existing fitting scripts to generate constituents
  • Script: scripts/harmonic_fitting/fit_nodal_fast.py (existing)

Output: location_config.h

Single header file included by firmware, containing:

// ===========================================
// AUTO-GENERATED - DO NOT EDIT
// Generated by: scripts/generate_location.py
// Location: Margate, UK
// Date: 2026-01-07
// ===========================================

#ifndef LOCATION_CONFIG_H
#define LOCATION_CONFIG_H

// --- Location ---
#define LOCATION_NAME "Margate"
#define LOCATION_LAT 51.3813f
#define LOCATION_LON 1.3862f

// --- Timezone ---
#define TZ_RULE TZ_RULE_UK
#define TZ_OFFSET_WINTER 0   // hours from UTC
#define TZ_OFFSET_SUMMER 1   // hours from UTC

// --- Tidal Model ---
#define TIDE_MODEL_EPOCH 1546301340L  // Unix timestamp
#define TIDE_MEAN_SEA_LEVEL 2.64f     // meters

// 31 harmonic constituents: {amplitude, speed (rad/hr), phase (rad)}
#define TIDE_NUM_CONSTITUENTS 31
static const float TIDE_CONSTITUENTS[31][3] = {
    {1.6236f, 0.5058681f, 3.6581f},  // M2
    {0.4758f, 0.5235988f, 0.5344f},  // S2
    // ... 29 more
};

// Empirical time corrections (nodal + seasonal)
#define NODAL_AMP      -4.922f
#define NODAL_PHASE    2015.522f
#define NODAL_OFFSET   0.424f
#define NODAL_PERIOD   18.61f
#define ANNUAL_AMP     1.674f
#define ANNUAL_PHASE  -0.263f
#define SEMIANN_AMP    0.699f
#define SEMIANN_PHASE -0.129f

#endif // LOCATION_CONFIG_H

Scripts to Create

1. scripts/generate_location.py (Master Script)

Usage:
  # For US locations (NOAA):
  python generate_location.py --noaa 8518750 --name "New York" --tz US_EASTERN

  # For other locations (from fitted JSON):
  python generate_location.py --json margate_nodal_fast.json --name "Margate" \
      --lat 51.3813 --lon 1.3862 --tz UK

Output:
  firmware/revA/include/location_config.h
  firmware/revB/include/location_config.h
  simulator/include/location_config.h

2. scripts/fetch_noaa.py (NOAA Data Fetcher)

Usage:
  python fetch_noaa.py 8518750  # Station ID

Output:
  - Fetches harmonic constituents from NOAA CO-OPS API
  - Outputs JSON in same format as fit_nodal_fast.py
  - Can be piped to generate_location.py

3. Existing Scripts (No Changes Needed)

  • scripts/harmonic_fitting/fit_nodal_fast.py - fits constituents from data
  • scripts/harmonic_fitting/fit_time_correction.py - fits empirical corrections

Firmware Changes

1. tide.c - Use location_config.h

Replace hardcoded arrays with:

#include "location_config.h"

static TideConstituent constituents[TIDE_NUM_CONSTITUENTS];

void tide_init(void) {
    for (int i = 0; i < TIDE_NUM_CONSTITUENTS; i++) {
        constituents[i].amplitude = TIDE_CONSTITUENTS[i][0];
        constituents[i].omega = TIDE_CONSTITUENTS[i][1];
        constituents[i].phase_rad = TIDE_CONSTITUENTS[i][2];
    }
}

2. astro.c - Use location_config.h

Replace:

#define MARGATE_LAT 51.3813f
#define MARGATE_LON 1.3862f

With:

#include "location_config.h"
// Use LOCATION_LAT, LOCATION_LON

3. timezone.c - Support multiple rules

Add timezone rule enum and dispatch:

#include "location_config.h"

typedef enum {
    TZ_RULE_UTC,
    TZ_RULE_UK,
    TZ_RULE_EU_CENTRAL,
    TZ_RULE_US_EASTERN,
    // ...
} TzRule;

int get_dst_offset(time64_t utc) {
    switch (TZ_RULE) {
        case TZ_RULE_UK: return is_bst(utc) ? 3600 : 0;
        case TZ_RULE_US_EASTERN: return is_us_dst(utc) ? 3600 : 0;
        // ...
    }
}

4. render.c - Use LOCATION_NAME

Replace:

display_draw_text(..., "Margate", ...);

With:

#include "location_config.h"
display_draw_text(..., LOCATION_NAME, ...);

Implementation Order

  1. Create location_config.h for Margate (current values, no behavior change)
  2. Refactor firmware to use location_config.h
  3. Test - verify simulator and firmware still work
  4. Create generate_location.py - generates config from JSON
  5. Create fetch_noaa.py - fetches NOAA data
  6. Add timezone rules to timezone.c
  7. Update README with customization instructions

File Changes Summary

All changes apply to all three targets: firmware/revA/, firmware/revB/, and simulator/.

File Change
*/include/location_config.h NEW - generated (identical in all 3)
*/src/tide.c Use config, add init function
*/src/astro.c Use config for lat/lon
*/src/timezone.c Add multi-timezone support
*/src/render.c Use LOCATION_NAME
scripts/generate_location.py NEW - writes to all 3 locations
scripts/fetch_noaa.py NEW
README.md Add customization section

Note: The generate_location.py script will write the same location_config.h to all three locations automatically.