CardSat v0.9.15
A radio- and rotator-control refinement release, with several ideas adapted from
the open-source OscarWatch tracker (Peter Goodhall, MM9SQL) after studying its
Doppler and rotator source. The Doppler-correction math was already on par; the
improvements here are in when and how CardSat talks to the radio and rotator.
This release also documents that per-satellite calibrations can be hand-authored
on the SD card, and makes those files comment-friendly.
Hardware status. Pass prediction, plots, GPS, the AOS alarm, deep sleep, and
the offline caches are confirmed on hardware. The radio and rotator refinements
in this release are host-verified only (tokenizer-balanced, logic-checked)
and have not yet been exercised against a physical rig or rotator. The constants
below use OscarWatch's field-tuned values as a starting point and may want
adjustment for your specific CI-V latency or rotator slew rate.
Doppler / CAT control
Three refinements to the real-time Doppler service, gated so they do nothing on
slow, low-elevation passes and only engage where they help (fast overhead passes):
- Mode-aware write deadband. CardSat already skipped re-sending a leg that
hadn't moved; the deadband is now mode-aware — loose for FM (300 Hz, whose
passband absorbs Doppler) and tight for linear SSB/CW (50 Hz). This cuts
needless CI-V traffic and audible stepping, and matters most on slow-CI-V rigs. - Adaptive threshold near TCA. When the Doppler slew rate is high (the fast
geometry around closest approach), the deadband tightens automatically — ramping
down above 15 Hz/s, halving by 35 Hz/s, with a 25 Hz floor — so tracking keeps
up where it counts and stays relaxed elsewhere. - TCA-tapered predictive lead. The correction can be computed slightly ahead
(up to 50 ms) to mask CAT latency, blended in proportionally to how fast Doppler
is changing and tapered to zero near closest approach, where range rate is
small and a forward lead would overshoot.
All three are compile-time constants (DOPP_* in app.h) — no new settings. The
cost is one extra range-rate evaluation per service tick (a second only when the
lead is active), negligible on the ESP32-S3.
Rotator control
- 450° azimuth lookahead (shortest-path over north). On a 450° rotator,
CardSat already used the 361–450° overlap band to avoid unwinding ~360° when a
pass crosses north — but reactively, after the bearing had already crossed. It
now looks 3 s ahead (one extra propagation per ~1 Hz rotator tick) and
pre-commits to the overlap band before an imminent north wrap, turning a
long unwind into a short move. Two guards keep this safe: it is computed only on
a 450° rotator, and never when a pass is flipped (where the +180° azimuth
makes the overlap reasoning meaningless). The hint is single-shot, so it can
never leak into a later park, pre-position, Sun/Moon, or manual command.
Calibration & tones on the SD card
- Documented: hand-author per-satellite calibrations. Per-sat calibration has
always been stored as a plain-text file; this release documents the format
so you can bulk-edit it on a computer instead of nudging each bird in CAL
mode. Edit/CardSat/calib.txt— onenorad downlink_Hz uplink_Hzline per
satellite — and the values apply the next time you open that bird (no reflash).
CTCSS overrides work the same way in/CardSat/tones.txt
(norad tone_tenths). See Manual §10. - Comment-friendly files. Both files now ignore blank lines and lines starting
with#or;, so you can annotate your calibrations. Saving on the device
preserves your comment lines.
Tunable from Settings (no reflash)
The Doppler and rotator refinements above shipped with sensible compile-time
defaults; the four values most likely to want field-tuning are now adjustable on
the device under Settings, persisted across reboots:
- Dopp FM band (default 300 Hz) and Dopp linear band (default 50 Hz) — the
per-mode CAT write deadbands (Radio / CAT category). - Dopp lead (default 50 ms;
0= off) — the predictive-lead cap. Raise it for
a slow-CI-V rig, or disable it entirely. - Rot az lookahead (default 3 s;
0= off) — the 450° azimuth lookahead
horizon (Rotator category). Tune to your rotator's slew speed, or turn it off to
use the previous reactive-only overlap behaviour.
IC-820H CI-V band-select (bug fix)
CardSat previously shipped the IC-820H with the same MAIN/SUB band-select
sub-commands as the IC-821H — which turns out to be wrong. Confirmed from each
radio's own manual (CI-V command table, command 07):
| Radio | Address | Main band access | Sub band access |
|---|---|---|---|
| IC-821H | 4C |
0x07 D0 |
0x07 D1 |
| IC-820H | 42 |
0x07 D1 |
0x07 D0 |
The IC-820H reverses the two sub-commands relative to the IC-821H. CardSat now
ships the correct mapping for each (selMain/selSub swapped between the two
profiles), so an IC-820H tunes the right VFO out of the box. Previously it would
have Dopplered the wrong band. The IC-820 profile is now marked verified. See
Manual §16.
EQX table for OSCARLOCATOR use
A new EQX table screen (Satellites → e) lists equatorial crossing times
and longitudes for the selected satellite, for plotting passes on a classic
OSCARLOCATOR board.
- Each entry is an ascending-node crossing (ground track crossing the equator
northbound), with the UTC time and sub-satellite longitude in
West-positive notation (123.4 W) — the convention printed on Oscarlocator
dials. - Covers the next 3 days, day-grouped and scrollable (
;/.),rto
recompute,dto toggle ascending ↔ descending node (the header reads
EQX or DEQX), computed entirely on-device from the satellite's GP
elements via SGP4 (no network). Successive crossings step ~28.7°/orbit westward
for an AO-7-class orbit. - Works for any satellite in the catalog, not just AO-7. Mirrors the output of
the AO-7_OSCARLOCATOR generator (N8HM). See Manual §8.
Edit / delete manual satellites & transponders
You can now remove hand-entered data from the device — previously, manually-added
GP satellites and transponders could only be added, never cleaned up.
- Delete a manual satellite — on Satellites, select a sat you added with
nand pressxtwice (arm, then confirm). It's removed from
/CardSat/mgp.jsonand from your favorites. Network-cached sats are protected
(they can't be deleted this way, since Update would just re-fetch them). - Delete a manual transponder — on the Transponder database (
tfrom
Satellites), the list is now selectable (;/.), the selected entry is marked
>, and your own entries are tagged*. Pressxtwice to delete the selected
manual entry; its line is removed from/CardSat/mtx_<norad>.json. SatNOGS
entries are protected the same way. - Editing is delete-then-re-add: remove the entry and recreate it with
n.
This keeps the UI small (no separate edit screen) while covering the need.
Both deletes are two-press confirmed and only ever touch hand-entered data.
CelesTrak GP queries & 9-digit NORAD IDs
Verified CardSat's GP/element requests against CelesTrak's current
specification (A New Way to Obtain GP Data). Requests already conform: host
celestrak.org (the .com host 301-redirects and risks an IP firewall), path
/NORAD/elements/gp.php, uppercase query keys, group/special values matching
CelesTrak's own examples, and an explicit valid FORMAT=JSON (rather than relying
on the server default, which changed to CSV in 2026). Error handling also matches
their guidance — responses are checked for HTTP 200, redirects are followed, and
retries are bounded with backoff rather than hammering.
Also audited and confirmed forward-compatibility with 9-digit catalog
numbers (the Space-Fence / 18 SDS 799xxxxxx analyst ranges that exceed the
classic 5-digit TLE limit). CardSat stores every NORAD id as a 32-bit value
(good past 4.2 billion) and ingests GP only via OMM/JSON NORAD_CAT_ID, so
9-digit ids parse, store, dedup, cache, and propagate correctly — confirmed by a
host test across the full range up to 999999999. The only 5-digit-limited spot is
the catalog field of the synthesized TLE line fed to the SGP4 initializer, which
is cosmetic (the propagator uses the orbital elements, not that field, and CardSat
never reads it back as identity); this is now documented in satdb.cpp.
IC-910 CI-V satellite-mode & tone (bug fix), CAT cross-checked against manuals
Before release, the Icom CI-V profile constants were reconciled against Hamlib and
then against the official Icom manuals (IC-9700 CI-V Reference Guide, IC-910
instruction manual). This surfaced two real IC-910 bugs:
- Satellite mode. CardSat sent
0x16 0x07to engage sat mode on every Icom.
That's correct for the IC-9100/9700 (0x16 0x5A) once you account for the
sub-command, but the IC-910 puts satellite mode under a different command
entirely:0x1A 0x07(verified from the IC-910 CONTROL COMMAND table). The old
code's0x16 0x07doesn't exist on the IC-910, so sat mode silently never
engaged. Fixed: satmode now carries a per-rig command byte (satModeCmd), so
the IC-910 sends0x1A 0x07while the IC-9100/9700 send0x16 0x5A. - CTCSS tone encoder. On the IC-910,
0x16 0x42is the auto-notch filter;
the subaudible-tone encoder is0x16 0x43. CardSat had been sending0x42,
which would toggle the notch instead of the tone. Fixed with a per-rig
toneEncSub(IC-910 =0x43, IC-9100/9700 =0x42).
Confirmed-correct constants (no change needed):
- IC-9100/9700 satellite mode
0x16 0x5A— from the IC-9700 CI-V Reference
Guide ("5A … Send/read the satellite mode") and a live IC-9100 trace
fe fe 7c e0 16 5a fd. - MAIN/SUB band select
0x07 D0/D1— IC-9700 confirmed from its CI-V guide
(and the0x07 D2get/set variant); the IC-820H/821H reversal confirmed from
their manuals earlier this release. - Repeater-tone frequency
0x1B 0x00and read-freq0x03— from the
IC-9700 guide; Yaesu/Kenwood encoders cited against Hamlibft847.c/ts2000.c.
Both the direct CI-V path and the network/rigctld path got the fixes. The IC-910's
tone-frequency (0x1B) command isn't documented in its CI-V table, so it's left
in with a caveat (if the rig NAKs it, the encoder on/off still applies the tone set
on the radio). The Kenwood TS-790/TS-2000 family remains the least bench-verified.
Kenwood TS-790 serial framing (bug fix)
Reviewing the TS-790 manual (and the contemporary TS-850 External Control manual,
which shares the IF-232C interface) surfaced a framing bug: the IF-232C
generation of Kenwood rigs requires two stop bits at 4800 baud, not one. CardSat
had been opening the Kenwood port as 8N1 at every rate, so a TS-790 at 4800 baud
could mis-frame or ignore commands. Fixed: the Kenwood port now uses 8N2 at 4800
baud and 8N1 above it (so the TS-2000 at 57600 is unaffected), selected
automatically by baud.
The rest of the TS-790 profile was confirmed: the FA; frequency read-back was
verified against a live Hamlib TS-790 trace, and CTCSS is left disabled
(hasTone=false) because the rig's tone squelch needs the optional TSU-5 decoder
unit. The TS-790's CAT runs through the optional IF-232C adapter; its operating
manual documents the interface but not the command set, so this family stays the
least bench-verified and should be confirmed against a serial trace on real
hardware.
Notes
- The Doppler linear deadband (50 Hz) means up to ~50 Hz of uncorrected SSB drift
between writes — intended, and matches OscarWatch's linear default. - The rotator lookahead horizon (3 s) and the Doppler lead cap (50 ms) are the
two values most likely to want field-tuning for your hardware. - Credit: the Doppler-threshold/lead and azimuth-lookahead ideas were adapted from
OscarWatch (AGPL-3.0, github.com/magicbug/OscarWatch-Tracker). CardSat's
implementations are independent C++ for the Cardputer.