The Problem
Operators of software‑defined radios need a single tool that can ingest raw baseband recordings, demodulate many satellite protocols, and export decoded telemetry without writing custom pipelines for each mission. Maintaining separate decoders quickly becomes a maintenance burden and leads to inconsistent data quality.
What This Does
SatDump is a C/C++‑heavy application that ships both a GUI (src-ui/) and a CLI (src-cli/). Core signal‑processing lives in src-core/ and is extended through the large plugins/ directory (≈1.9 k files) that implements protocol‑specific demodulators, audio sinks, and hardware back‑ends. The top‑level CMakeLists.txt orchestrates compilation of all modules; the Android front‑end is built with Gradle (android/app/build.gradle). A Dockerfile and docker‑compose.yml provide an isolated build/runtime environment.
Key entry points:
| Platform | Entry file | Role |
|---|---|---|
| Desktop GUI | src-ui/main.cpp (indirect, called from CMakeLists.txt) | Starts ImGui‑based UI, loads pipelines from resources/ |
| CLI | src-cli/main.cpp (referenced in src-cli/ CMake target) | Parses satdump sub‑commands (pipeline, legacy live, record) |
| Android | android/main.cpp | Boots the native layer, forwards UI events to Java activity (MainActivity.kt) |
How It Is Wired
Execution begins in the platform‑specific main.cpp. For the desktop CLI, src-cli/main.cpp creates a CommandLineInterface object, registers sub‑commands defined in src-cli/commands/, and dispatches to the pipeline runner (src-core/pipeline_runner.cpp). The runner parses the JSON pipeline description from resources/pipelines/, instantiates the required modules (src-core/module_factory.cpp), and wires them together via a shared ProcessingContext.
Each module pulls data from a source object (e.g., plugins/airspy_support/airspy_source.cpp) that implements the abstract IDataSource interface. The source reads raw IQ samples, applies optional DSP blocks (DC‑block, IQ‑swap) located in src-core/dsp/, and pushes buffers into a lock‑free queue consumed by the first demodulator module.
Demodulators (e.g., plugins/dvb_s2_support/dvb_s2_decoder.cpp) decode frames and forward them to sink modules such as plugins/audio_sinks/portaudio_audio_sink/main.cpp or file writers (src-core/file_sink.cpp). The UI layer (src-ui/) mirrors this pipeline graph, allowing users to start/stop modules at runtime; the UI only interacts with the same ProcessingContext used by the CLI, ensuring functional parity.
The Dockerfile builds the entire CMake project in a Debian‑based image, exposing the compiled satdump binary. The Android Gradle module compiles the native code via android/CMakeLists.txt and packages it with a Kotlin activity that forwards UI commands to the native layer through JNI (android/backend.cpp).
Overall call depth from entry point to file output is typically ≤ 5 function calls, keeping the blast radius small. The only hub with higher fan‑in is module_factory.cpp, which knows every plugin class; changes here can affect all pipelines.
How To Use It
# Clone the repo
git clone https://github.com/moses-y/SatDump.git
cd SatDump
# Build inside Docker (reproducible)
docker build -t satdump .
docker run --rm -v $(pwd):/src satdump bash -c "cmake -B build -S . && cmake --build build -j$(nproc)"
# Or build locally (Linux/macOS)
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
# CLI example – decode a METOP AHRPT recording
./satdump pipeline metop_ahrpt baseband \
/path/to/metop_baseband.cs16 \
./output_dir \
--samplerate 6e6 --baseband_format cs16
# Run the GUI (Linux)
./satdump-gui # binary generated from src-ui target
# Android build (requires Android SDK)
cd android
./gradlew assembleRelease
Configuration files are JSON descriptors under resources/pipelines/ and hardware profiles under plugins/. No environment variables are required for basic operation.
Real‑World Use
A ground‑station operator can script nightly recordings:
#!/bin/bash
satdump legacy record metop_baseband \
--source airspy --samplerate 6e6 --frequency 1701.3e6 \
--general_gain 18 --bias --baseband_format cf32
satdump pipeline metop_ahrpt baseband metop_baseband \
./decoded --samplerate 6e6
The script runs on a headless Linux box, producing decoded telemetry ready for ingestion into a downstream database.
Code Health & Issues
- Low – Unlocked dependencies –
android/app/build.gradledeclares libraries without a lockfile, making builds non‑reproducible. - No lockfile for C++ dependencies either (CMake fetches external projects at configure time).
- Test suite exists (≈ 50 test files) but is not hooked into CI; GitHub Actions (
.github/workflows/all_build.yml) only builds, does not run tests. - Documentation is present (
docs/, Doxygen config) but the README lacks a quick‑start for non‑Docker builds. - License file (
LICENSE) is present, so legal compliance is clear.
The Bottom Line
SatDump delivers a mature, extensible satellite‑signal processing stack with both GUI and CLI interfaces. Its modular plugin architecture is well‑defined, and the build system supports native, Docker, and Android targets. The primary concerns are reproducibility of third‑party dependencies and the lack of automated test execution in CI. Teams needing a single, adaptable decoder for many satellite protocols will find the project immediately useful, provided they allocate effort to lock down external libraries and integrate the existing tests into their workflow.