ADS-B aircraft decoding → AetherMap (FLEX-8600 + 1090 transverter, in-app via VITA-49 IQ)

Open
#3,598 2 comments 0 reactions 0 assignees View on GitHub

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

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

external devices GUI maintainer-review New Feature priority: low protocol upstream VITA-49

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/0xFFFA0480 equivalents). 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, CRC 0xFFF409 + 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 (mirror AprsStationList): 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 → MapView aircraft 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 same ModeSDecoder from 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 external dump1090/readsb. Lets users without a transverter use a cheap dongle, and is an excellent test harness for Phases 1–2 (replay real message streams into ModeSDecoder).

Out of scope (v1)

  • UAT (978 MHz); MLAT; feeding aggregators; historical playback.
  • ADS-B transmit (RX only).

Open questions

  1. Phase 0 result — the commandable VITA-49 IQ rate on the 8600 (the one gating unknown).
  2. Transverter mapping via native XVTR config vs app-side offset.
  3. 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 XIModeSDecoder unit 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from aethersdr/AetherSDR

All issues in aethersdr/AetherSDR

Similar issues

More C++ issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.