# codar-sounder
Opportunistic ionospheric sounder for the HamSCI (Ham Radio
Science Citizen Investigation) sigmond suite.
`codar-sounder` receives CODAR (Coastal Ocean Dynamics
Applications Radar) high-frequency (HF) chirp transmissions via
`radiod`, dechirps them, and produces a JSON Lines (JSONL) time
series of group range, virtual height, equivalent vertical
frequency, and per-peak amplitude / phase scintillation indices
along each oblique propagation path.
## Background
CODAR transmitters along the US east and west coasts radiate
**linear frequency-modulated continuous-wave (FMCW)** chirps at
well-characterised frequencies (4–50 MHz) 24/7, with timing
disciplined by the Global Positioning System (GPS). Each chirp
sweeps the transmit frequency linearly across a band of roughly
25–100 kHz and repeats at the sweep repetition frequency (SRF;
typically 1 Hz). Some sites use up-chirps (instantaneous
frequency rising through the sweep), others down-chirps; the
sweep parameters — start frequency, bandwidth, sweep rate,
direction — are stable and well-documented per site. Co-located
transmitters that share a band coordinate via time-division
multiple access (TDMA) slots, each transmitter starting its
chirp at a fixed phase within a shared repetition period.
Although the transmitters exist to image ocean surface currents,
the same signals are an excellent **opportunistic** source for
single-frequency oblique ionospheric sounding: the transmit power
is already paid for, the frequencies and chirp parameters are
public, and the coverage geometry is fixed and well-documented.
The FMCW waveform is well suited to dechirp-based ranging — beat
frequency after dechirping is proportional to the group-path
delay — so a receiver with the same chirp parameters and
coherent timing can recover ionospheric path information from a
transmitter it has no operational relationship with.
The instrument design follows Kaeppler et al. (2022, *Atmos.
Meas. Tech.* 15:4531–4545). We add multi-hop hypothesis
selection, two stages of median-absolute-deviation (MAD)
interference rejection, and per-peak amplitude / phase
scintillation indices on top of the original method; see
[`docs/METHODOLOGY.md`](docs/METHODOLOGY.md) for the technical
detail.
$ smd watch codar -v
━━━ CODAR ionospheric soundings (AC0G-B1) ━━━
stage: decoder (codar-sounder) → JSONL spool (pre-SQLite)
▸ 1 station(s): SEAB
▸ every 15 s (CPI cadence) — per-window rollup
+ ALL records in this window, one line each
Ctrl-C to exit.
─── win UTC 21:28:00 (15s) ──────────────────────────────────
(no detections this window)
─── win UTC 21:28:15 (15s) ──────────────────────────────────
SEAB : peaks=4 layers={E,F1,F2} SNR=+60.0 dB
21:38:21.373 SNR +60.0 dB GR 1431.6 km VH 103.1 km EVF 1.937 MHz E (0/4)
21:38:21.373 SNR +60.0 dB GR 1479.9 km VH 214.0 km EVF 3.890 MHz F1 (1/4)
21:38:21.373 SNR +60.0 dB GR 1510.2 km VH 261.5 km EVF 4.658 MHz F2 (2/4)
21:38:21.373 SNR +60.0 dB GR 1522.2 km VH 278.5 km EVF 4.921 MHz F2 (3/4)
→ peaks=4 stations=1/1 layers={E,F1,F2}
─── win UTC 21:28:30 (15s) ──────────────────────────────────
SEAB : peaks=4 layers={F2} SNR=+60.0 dB
21:38:36.373 SNR +60.0 dB GR 1516.2 km VH 270.1 km EVF 4.792 MHz F2 (0/4)
21:38:36.373 SNR +60.0 dB GR 1649.1 km VH 422.0 km EVF 6.884 MHz F2 (1/4)
21:38:36.373 SNR +60.0 dB GR 1763.8 km VH 262.7 km EVF 8.013 MHz F2 (2/4)
21:38:36.373 SNR +60.0 dB GR 1902.8 km VH 317.6 km EVF 8.979 MHz F2 (3/4)
→ peaks=4 stations=1/1 layers={F2}
─── win UTC 21:28:45 (15s) ──────────────────────────────────
SEAB : peaks=4 layers={F2} SNR=+8.4/+11.0 dB
21:38:51.373 SNR +11.0 dB GR 1775.9 km VH 267.7 km EVF 8.111 MHz F2 (0/4)
21:38:51.373 SNR +9.8 dB GR 2047.8 km VH 369.6 km EVF 9.712 MHz F2 (1/4)
21:38:51.373 SNR +9.2 dB GR 1667.2 km VH 439.5 km EVF 7.091 MHz F2 (2/4)
21:38:51.373 SNR +8.4 dB GR 1637.0 km VH 410.1 km EVF 6.739 MHz F2 (3/4)
→ peaks=4 stations=1/1 layers={F2}