ADS-B aircraft decoding → AetherMap (FLEX-8600 + 1090 transverter, in-app via VITA-49 IQ)
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 30/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- cpp
- Domain
- desktop, frontend, networking
Research direction
Start with src/core/PanadapterStream.h and src/models/DaxIqModel.h to investigate the FlexLib/SmartSDR VITA-49 IQ stream API and determine the commandable sample rate and format. Then review src/core/WfmDemodulator.h and the listed map integration points; Phase 0 is done when the achievable rate and transverter mapping are confirmed, or the external-decoder fallback is selected.
Written by the indexing model from the issue text.
Description
ADS-B aircraft decoding → AetherMap (FLEX-8600 + 1090 transverter, in-app via VITA-49 IQ)
Tracking issue + implementation plan for decoding 1090 MHz ADS-B (Mode S Extended Squitter) in-app on the FlexRadio, using a 1090→IF transverter into the 8600's transverter port and the radio's wideband VITA-49 IQ stream, then plotting live aircraft on the built-in Qt map ("AetherMap"). Backed by a verified deep-research pass + a repo integration survey.
Architecture
1090 MHz antenna
→ 1090→IF transverter (down-convert to an HF/6 m IF, e.g. 1090 MHz → 28 MHz)
→ FLEX-8600 transverter port (RX 30 kHz–54 MHz; dedicated XVTR ports)
→ radio direct-samples @ 16-bit / 245.76 Msps
→ wideband VITA-49 IF Data (time-domain IQ) stream over Gigabit Ethernet
→ AetherSDR: VITA-49 IQ ingest
→ 1090ES PPM demodulator (in-app) ← magnitude → preamble correlate → PPM slice → 112-bit frames
→ Mode S decoder (in-app) ← CRC/ICAO, DF17/18 typecodes, CPR
→ ICAO-keyed aircraft roster
→ AetherMap aircraft layer
No dongle, no DAX-IQ. The demod lives in AetherSDR (same model dump1090 uses: raw IQ in → messages out).
Why this is feasible (the numbers)
| Requirement | ADS-B needs | FLEX-8600 provides | Margin |
|---|---|---|---|
| RF capture bandwidth | ~2 MHz (1 channel @ 1090) | 14 MHz pan / 245.76 Msps ADC | ~7× |
| Time-domain sample rate | ≥~2 Msps to resolve 0.5 µs pulses | direct-sampling front end | ✓ |
| IQ transport over the wire | ~130 Mbps (2 Msps × 32-bit float I/Q) | Gigabit Ethernet (1000 Mbps) | ~13% of link |
| Decoded data out the far end | <1 kbps/aircraft (112-bit msgs, few/sec) | — | trivial |
The only thing the DAX-IQ 192 kHz cap ever told us is that the DAX export app is throttled — it streams ~12 Mbps when the link can do 1000. Nothing physical blocks a wider stream.
The one open empirical item (Phase 0)
What IQ sample rate will the 8600's firmware/FlexLib actually emit on a directly-commanded VITA-49 IF Data stream? We need ~2 Msps (≥~1.5 Msps workable with graceful sensitivity loss) across the ADS-B channel. This is now a software/API question, not physics — resolve it before committing Phase 2.
Verified signal & protocol facts (sources in the research report)
- Modulation: PPM at 1090 MHz, 1 Mbit/s, 8 µs four-pulse preamble (pulses at 0.0–0.5, 1.0–1.5, 3.5–4.0, 4.5–5.0 µs), then 56 or 112 µs of data. [mode-s.org, MathWorks]
- Frames: ADS-B = DF17/DF18, 112-bit. Structure: 5-bit DF + … + 24-bit parity. [mode-s.org]
- CRC: generator
0xFFF409(24-bit;0x1FFF409/0xFFFA0480equivalents). The 24 parity bits are XOR-overlaid with the ICAO address, so the ICAO addr is recovered by recomputing the CRC and XORing the received parity. [EUROCONTROL, mode-s.org] - Type codes (DF17/18): TC1–4 ident+category, TC5–8 surface position, TC9–18 airborne baro position, TC19 velocity, TC20–22 GNSS position, TC28 status, TC29 target state, TC31 op status. [pyModeS]
- CPR: even/odd pairing; global decode needs an even+odd pair in a time window; local decode needs a reference (airborne ≤180 NM, surface ≤45 NM). [pyModeS]
Decode references & licensing
antirez/dump1090— BSD. Best reference for the PPM demod + CRC (the algorithm we port for the in-app demodulator), no copyleft friction.readsb/pyModeS— GPLv3. Excellent references for CPR / typecode parsing; AetherSDR is already GPLv3 so linking is compatible, but per project precedent (HdlcCodec, Direwolf-derived AFSK demod) we implement in-tree from the BSD source + mode-s.org specs.
Codebase integration points (from survey)
| Need | Reuse / touch | File |
|---|---|---|
| VITA-49 IQ ingest | The radio→client IQ plumbing already exists for DAX-IQ — PanadapterStream::iqDataReady(channel, rawPayload, sampleRate) feeding DaxIqModel. Phase 0/2 determines whether this path can be commanded wideband or needs a new wide-IQ stream type. |
src/core/PanadapterStream.h, src/models/DaxIqModel.h |
| IQ-consumer pattern | WfmDemodulator shows the connect(iqSamplesReady → onIqSamples) worker pattern an ADS-B demod follows |
src/core/WfmDemodulator.h |
| Map rendering | MapView::setMarkers(QVector<Marker>), Marker{lat,lon,label,tooltip,color,clickInfo}, markerClicked, setLegend, MapPathItem trails |
src/gui/map/MapView.h |
| Map consumer template | PSK Reporter map (rebuild-markers + nested-JSON config) | src/gui/PskReporterMapDialog.cpp |
| Aircraft roster model | AprsStationList::Station ≈ an aircraft track (call/lat/lon/alt/course/speed) — clone as ICAO-keyed AdsbAircraftList |
src/core/aprs/AprsStationList.h |
| Host UI | AetherModem dialog is a QStackedWidget of tabs — add an "ADS-B" tab |
src/gui/Ax25HfPacketDecodeDialog.cpp |
| Worker threading | moveToThread + Qt::QueuedConnection (as the AX.25 shim) |
src/gui/Ax25HfPacketDecodeDialog.cpp |
| Config | nested-JSON via AppSettings (Principle V), e.g. TncSettings |
src/core/AppSettings.h |
Phased implementation plan
Phase 0 — pin the VITA-49 IQ rate (gates Phase 2)
- Investigate the FlexLib/SmartSDR
stream create/IQ-stream API: max commandable IF Data sample rate from a native client (vs the DAX-IQ 192 kHz default), sample format (expected 32-bit float I/Q), and per-stream bandwidth on the 8600. - Confirm transverter (XVTR) configuration: LO/offset so AetherSDR maps the IF ↔ 1090 MHz and labels the slice correctly; decide whether to use the radio's native XVTR config or app-side offset.
- Outcome: confirm ≥~1.5–2 Msps is achievable. If not, fall back to the optional external-decoder ingest (Phase 3).
Phase 1 — decode core + roster + map (no RF; build in parallel with Phase 0)
-
ModeSDecoder(in-tree, from antirez BSD + mode-s.org): DF demux, CRC0xFFF409+ ICAO recovery, DF17/18 typecode parse (ident/category, airborne+surface position, velocity), CPR global (even/odd) + local-with-reference. Unit-tested against known 112-bit message vectors (Principle XI). -
AdsbAircraftList— ICAO-hex-keyed roster (mirrorAprsStationList): callsign, lat/lon, alt_baro (number or on-ground), gs, track/heading, baro/geom rate, squawk, emergency, category (A0–D7), first/last-heard; TTL eviction of stale tracks. - ADS-B tab in the AetherModem dialog →
MapViewaircraft layer: markers + labels (callsign/alt/speed), click-card (full surveillance set), altitude/category color legend, optional track trails, home/QTH from radio GPS or grid. - Nested-JSON config: transverter offset, TTL, trail length, filters, units.
Phase 2 — wideband VITA-49 IQ ingest + in-app demodulator
- Command + receive the wideband VITA-49 IF Data stream tuned to the ADS-B IF (per Phase 0).
-
Mode1090Demod(from antirez BSD), on its own worker thread: magnitude|I+jQ|→ preamble correlation (8 µs template) → PPM bit slicing → 112-bit frames → feed the sameModeSDecoderfrom Phase 1. - UI: signal/rate stats, message-rate + CRC-pass meters; live decode → map.
Phase 3 — optional alternative source (nice-to-have)
-
AdsbBeastClient— also accept Beast (port 30005) / SBS-CSV (30003) from an externaldump1090/readsb. Lets users without a transverter use a cheap dongle, and is an excellent test harness for Phases 1–2 (replay real message streams intoModeSDecoder).
Out of scope (v1)
- UAT (978 MHz); MLAT; feeding aggregators; historical playback.
- ADS-B transmit (RX only).
Open questions
- Phase 0 result — the commandable VITA-49 IQ rate on the 8600 (the one gating unknown).
- Transverter mapping via native XVTR config vs app-side offset.
- Map performance with hundreds of simultaneous aircraft + trails (may need marker batching beyond the PSK Reporter pattern).
Constitution touchpoints
- Principle V — nested-JSON config per feature.
- Principle XI —
ModeSDecoderunit tests against known vectors; live decode → map screenshot. - Cross-platform — VITA-49 ingest + Qt are portable; verify Linux/macOS/Windows.
- License — derive demod/decode from BSD
antirez/dump1090; GPLv3 readsb/pyModeS as references.
The FLEX-8600 (245.76 Msps direct sampling, 14 MHz instantaneous bandwidth, Gigabit Ethernet, VITA-49 IQ) is a fully capable ADS-B front end via a 1090→IF transverter — no external dongle required. Plan synthesized from a verified deep-research report (5 angles, 20 sources, 25 claims adversarially verified) + a repo integration survey.
- Dominant language
- C++
- Stars
- 221
- Forks
- 117
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 299
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from aethersdr/AetherSDR
-
audio documentation good first issue maintainer-review
Difficulty 1/5 Under an hour Newbie friendliness 92/100
-
bug CW maintainer-review safety
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
docs(agents): family PRs must stay in the family tree (shared applet/pan/model edits stall review) Opendocumentation enhancement maintainer-review
Difficulty 1/5 1-3 hours Newbie friendliness 90/100
-
bug good first issue GUI maintainer-review priority: low
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 86/100
All issues in aethersdr/AetherSDR
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
-
Sensor initialization takes very long when `--initial-sim-time` is set to current UNIX timestamp Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
gazebosim/gz-sensors#662 · 1 comment ·
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
comp-datalake
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ClickHouse/ClickHouse#121222 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
LadybirdBrowser/ladybird#12123 ·