Native weather-satellite decoders (app/radio/sat)¶
A clean-room replacement for SatDump's common decode chains, built from published
standards (CCSDS 131.0-B, the NOAA KLM User's Guide, the LRIT/HRIT specs). No
SatDump source or binary is used as a source or oracle. SatDump is still driven as
an external program for the exotic instruments, map projections and Inmarsat that
these don't cover (see satdecode.py).
The stack¶
IQ (RTL/Lime/Airspy) or FM audio (the 705)
│
qpsk_rx ──────┤ AGC · RRC · Gardner timing · Costas (QPSK & BPSK)
│
ccsds ────────┤ r=1/2 K=7 Viterbi · ASM 0x1ACFFC1D · TM derandomiser
│ · RS(255,223) dual basis · CADU→VCDU (single & streaming)
│
extract_packets┤ VCDU M_PDU → CCSDS Space Packets (spanning frames)
│
per-mode ─────┴ APT / LRPT (Meteor JPEG) / xRIT / HRPT / AHRPT (AVHRR)
| Module | Role |
|---|---|
viterbi.py |
CCSDS r=1/2 K=7 conv code + vectorised soft Viterbi (numpy ACS) |
rs.py |
RS(255,223), CCSDS field 0x187, fcr=112, generated dual-basis transform |
ccsds.py |
ASM sync, TM PN (spec-exact), CADU chain, decode_stream (all CADUs) |
qpsk_rx.py |
real-IQ QPSK and BPSK receivers + impaired-capture generators |
apt.py |
NOAA APT — 2400 Hz AM subcarrier → line sync → image (FM audio, no SDR) |
meteor_jpeg.py |
Meteor MSU-MR image codec (JPEG-Huffman + DCT + Meteor quant) |
lrpt.py |
Meteor LRPT — QPSK → CCSDS → packets → image; single + full-pass |
xrit.py |
LRIT/HRIT file layer (GOES/Meteosat); uncompressed + JPEG (Pillow) |
hrpt.py |
NOAA HRPT/AVHRR — Manchester, 10-bit words, frame sync, de-interleave |
ahrpt.py |
MetOp/FengYun AHRPT — raw AVHRR over the CCSDS core |
avhrr.py |
image products — stretch, grayscale, RGB composite, montage |
decode_file.py |
offline CLI + the app's native SatDecoder backend |
Offline CLI¶
python -m app.radio.sat.decode_file apt noaa.wav -o img.png
python -m app.radio.sat.decode_file lrpt meteor.iq --fs 140000 -o img.png
python -m app.radio.sat.decode_file hrpt hrpt.iq --fs 2662000 -o avhrr.png
python -m app.radio.sat.decode_file ahrpt metop.iq --fs 2000000 --product rgb
In the app¶
- 🛰 per recording →
sat_decode_file→SatDecoder.decode_recording. A WAV decodes as APT; an IQ recording decodes with the mode from its JSON sidecar. - 📡 IQ REC →
record_iqcaptures SDR IQ torec-<ts>-iq.iq+ a sidecar, so the pass lands in the list and its 🛰 button decodes it natively. - 🛰 LIVE →
sat_stream→NativeSatStreamerdecodes off the SDR in real time, the image building up in the SATS pane during the pass.
What is validated, and what needs a real signal¶
Validated (self-consistent + spec-transcribed, 50 tests): the FEC/framing/ codecs, the real-IQ receivers, the in-app decode/dispatch, and the streaming accumulation logic (fed IQ chunks through an injectable source). Every mode round-trips through impaired synthetic captures (carrier offset, symbol-timing offset, phase, noise); the CCSDS PN matches the spec vector; RS corrects 16 errors; LRPT/HRPT/AHRPT recover images from raw IQ.
Hardware-gated (code complete, needs a real SDR/signal to run): - The IQ recording and live streaming capture paths — the decode side is tested; the SDR read loop needs a device. - The exact NOAA HRPT minor-frame sync word and a real-signal interop pass. - AVHRR radiometric calibration (albedo / brightness temperature) — the products here are display-grade (contrast-stretched), not calibrated.