A modern GTK4 software-defined-radio application for HPSDR / ANAN transceivers, built on the proven piHPSDR engine with a new, high-detail user interface.
sdr-for-linux is a GPLv3 fork-in-spirit of
piHPSDR: it reuses piHPSDR's excellent
engine — the HPSDR Protocol 2 radio link and the WDSP DSP library — and
replaces the front-end with a native GTK4/libadwaita control surface and a
full-resolution floating-point panadapter. No DSP is reimplemented; WDSP
does the heavy lifting.
Status: 0.x — young but real. Everything below is implemented and verified live on an Apache Labs ANAN G2E, an ANAN 10E and a Hermes Lite 2 (all RX + TX), including a full CW contest deployment; see Supported hardware.
Receive
- Full-float panadapter + waterfall straight from the WDSP analyzer — no quantisation, no column cap; 6 colour palettes, adjustable averaging & FPS
- SSB / CW / AM / DIGU / DIGL / RTTY demodulation with piHPSDR filter presets, passband drawn on the spectrum (RTTY: dial = FSK pair centre, heard on the classic 2125/2295 Hz pair)
- Filter and AGC dialogs behind two header-bar icons: a passband graph you drag (edges or the whole band), the mode's presets + Var1/Var2, Low/High rows; AGC Off/Long/Slow/Med/Fast with a live gain bar and the AGC-T threshold. Any preset's edges also drag right on the spectrum (a dragged preset becomes Var1); LSB-family filters read as audio Hz
- Two VFOs: A/B swap and A=B, the other VFO shown under the frequency readout, free across bands; CTUN: drag pans the spectrum while the dial stays put — the green passband is the tuning handle
- Noise reduction (ANR), noise blanker (ANB), auto-notch (ANF), binaural mode
- Low-latency native PipeWire audio (~15 ms), 48/96/192 kHz; the AF slider's floor is a true mute
- Scroll/drag/click-to-tune, octave-snap zoom, draggable spectrum/waterfall divider, band buttons, band-plan overlay (IARU R1/R2/R3 + country overrides), DX-spot overlay with click-to-tune
- CW BFO offset done right: the dial reads the carrier, spots sound at your sidetone pitch
Transmit (SSB voice, CW, RTTY, digi via TCI)
- MOX / TUNE with separate drive levels, per-band PA calibration, true-PEP wattmeter, SWR metering with automatic drive-drop protection
- Mic via PipeWire with mic gain / noise gate / speech processor controls (digi audio stays a bit-exact clean chain, enforced by the engine), faithful TX monitor (plays the processed on-air audio), footswitch PTT
- CW keying with clean first-dit and contest-grade latency (TCI→RF ~35 ms, turnaround ~200 ms), adjustable WPM / sidetone / break-in hang; mode-aware TX HUD (CW/RTTY sent-text with playhead, digi TX level)
- Native RTTY: direct-FSK modulator (45.45 Bd / 170 Hz, phase-continuous),
keyed from text over TCI (
rtty_macros:) — pair with a TCI logger and the skimmer for decode - PureSignal linearization with Thetis-style auto-attenuate — calibrates continuously on voice, converges in seconds after drive/band changes (G2E and Hermes Lite 2; not available on old Hermes-class P2 firmware — see the hardware table)
- TX panadapter + waterfall of the transmitted spectrum, with the TX filter footprint drawn in red (the display's colour language: RX green, TX red)
Integration
- TCI server (ExpertSDR3-compatible, port 40001): control, CW macros,
RX audio, TX audio (digimodes), wideband IQ with optional per-block
centre stamps for skimmers, spots — verified live with SDC,
CW Skimmer and Decodium (complete FT8 QSOs on the air);
dds/vfogo out on every tuning step - CAT/hamlib applications are covered through the third-party tciadapter bridge (WSJT-X, fldigi, CQRLOG verified by its author) — no serial-port emulation needed here
Companion apps (same author, same stack — C, GTK4/libadwaita, TCI): skimmer-for-linux, a multi-channel CW/RTTY/PSK skimmer fed by this app's TCI IQ stream, and log-for-linux, a logbook that follows the dial over TCI.
Policy: a radio model is enabled only after it has been tested on real hardware. A wrong relay or filter bit in the HPSDR control words can physically damage a PA, so untested models are refused by a whitelist in the radio picker rather than left to luck.
| Radio | Protocol | Status |
|---|---|---|
| Apache Labs ANAN G2E | HPSDR Protocol 2 | ✅ supported, developed & verified on this radio |
| Apache Labs ANAN 10E / 100B (Hermes) | HPSDR Protocol 2 | ✅ supported — RX + TX live-verified (fw 10.3); per-radio PA calibration & 10 W scale. PureSignal disabled: the old Hermes firmware locks up on the P2 feedback-DDC switch mid-TX (power-cycle recovery); details in docs/TX-DESIGN.md §9 |
| Hermes Lite 2 | HPSDR Protocol 1 | ✅ supported — RX + TX + PureSignal live-verified (gw 73.2): panadapter, audio, LNA gain (−12..+48 dB), N2ADR filter-board band switching, die temperature + 60 °C thermal TX trip, ADC-overload badge, TCI/SDC skimming, 5 W PA with per-band calibration (20 m calibrated, other bands under-drive until walked in), CW/voice, PureSignal over P1 (RX3/RX4 feedback; PS needs a sample rate ≤ 192 kHz). Rates 48–384 kHz, 0–38.4 MHz |
| Apache Labs ANAN G2 (Saturn) | HPSDR Protocol 2 | 🟢 RX + TX + PureSignal — live-tested by an external operator (W1IZZ, issue #3, two rounds, 2026-08-22/24): RX probes clean, per-band PA calibration against an LP-100A with our wattmeter within 1–2 W, SWR tracking, a voice QSO; PureSignal correcting with the feedback inside its target window; the per-model supply readout confirmed on his radio. We still do not own a G2: the per-device values (two Alex boards, two ADCs, DDC2, ANAN-7000 band-pass knees and wattmeter constants, ps_setpk 0.6121) come from piHPSDR, pinned by an offline byte gate, and are confirmed by one operator's runs, not calibrated by us. It starts safe — PA off, ANT1, 1 W, no stored PA calibration — so ⛔ your first transmission still belongs into a dummy load: dry key, then 1 W, then walk the calibration up per band while watching the SWR (his numbers landed at 43–53 dB). Step-by-step in docs/RADIOS-SCOPE.md §7 (§7.1–7.2 = what his runs showed) |
| Other ANAN / Hermes P2 boards (ORION2: 7000/8000/DLE 7000) | Protocol 2 | ⛔ blocked until tested — the Saturn work above already carries their wire bytes, so this is mostly a whitelist + live test away; open an issue if you can lend hardware + a dummy load |
| Older P1 boards (HL1, Metis…) | Protocol 1 | ⛔ blocked until tested |
Each radio keeps its own TX calibration (PA calibration per band, wattmeter trim, drive/antenna/PA-enable) in its own config section — calibrating one model never touches another. A newly connected TX-capable model starts safe: PA off, ANT1, 1 W.
- A supported ANAN radio on your LAN (see above)
- Linux with PipeWire as the sound server (standard on 2024+ distros)
- For the AppImage: glibc ≥ 2.39 (Ubuntu 24.04+, Fedora 40+, Mint 22, openSUSE, Arch, …)
- To build from source: GTK ≥ 4.10 (enforced by meson) and libadwaita ≥ 1.5. GPU rendering additionally wants GTK ≥ 4.22, but the app runs fine below it on the Cairo renderer
Grab the latest from Releases — three formats, pick one:
AppImage (any distro, glibc ≥ 2.39):
chmod +x SDR_for_Linux-*.AppImage
./SDR_for_Linux-*.AppImage.deb (Ubuntu 24.04+ / Debian 13+ / Mint 22+):
sudo apt install ./sdr-for-linux_*_amd64.deb.rpm (Fedora 40+):
sudo dnf install ./sdr-for-linux-*.x86_64.rpmBoth packages are install-tested in fresh containers by the release CI.
Arch Linux (AUR) — sdr-for-linux:
paru -S sdr-for-linux # or: yay -S sdr-for-linuxOr without a helper: git clone https://aur.archlinux.org/sdr-for-linux.git && cd sdr-for-linux && makepkg -si. The AppImage also runs fine on Arch.
Build from source — the DSP engine (WDSP, plus rnnoise and
libspecbleach) is vendored in vendor/ and built from source; only
ubiquitous platform libraries come from your distribution:
| Need | Arch | Debian/Ubuntu | Fedora |
|---|---|---|---|
| GTK4 ≥ 4.10 + libadwaita ≥ 1.5 | gtk4 libadwaita |
libgtk-4-dev libadwaita-1-dev |
gtk4-devel libadwaita-devel |
| FFTW (single + double) | fftw |
libfftw3-dev |
fftw-devel |
| PipeWire client | libpipewire |
libpipewire-0.3-dev |
pipewire-devel |
| libwebsockets (TCI) | libwebsockets |
libwebsockets-dev |
libwebsockets-devel |
| Opus, OpenSSL, zlib | opus openssl zlib |
libopus-dev libssl-dev zlib1g-dev |
opus-devel openssl-devel zlib-devel |
| Build tools | base-devel meson |
build-essential meson |
gcc meson |
meson setup build
meson compile -C build
./build/sdr-for-linux # run in place, or:
sudo meson install -C build # install binary + desktop integration- FFTW wisdom build (~6 minutes, once). On first start the app plans
FFTW transforms for every panadapter FFT size (a progress window shows
the state) and caches them in
~/.config/sdr-for-linux/. Every later start imports the cache instantly. Without this, deep zoom would freeze for up to half a minute at a time — same approach as piHPSDR and Thetis. - Radio picker. The app broadcast-discovers HPSDR radios on the LAN (one entry per radio even when it answers on several interfaces; the data link takes the in-subnet one); pick yours, or add by IP for a different subnet. One client owns the radio at a time — close piHPSDR/Thetis first.
- Transmit is conservative by default: PA drive starts at zero and TX is gated (out-of-band, high SWR, or missing prerequisites refuse to key). Check Preferences → TX before your first transmission.
Settings persist in ~/.config/sdr-for-linux/config.ini.
Mouse & keys. Wheel = tune by the footer Step; left-drag = pan
(with CTUN on, the spectrum pans and the dial stays — drag the passband to
tune); right-drag = zoom; drag a passband edge to reshape the filter; drag
the spectrum/waterfall separator to resize (double-click resets). Keys:
u/l/c/a/r = USB/LSB/CW/AM/RTTY, b = VFO A/B, Esc = leave
select mode / abort a TX over.
Display rendering is chosen automatically: on GTK ≥ 4.22 the app uses
GTK's GPU (GL) renderer — the waterfall history is scaled by the graphics
card and the frame pacing is much steadier at high FPS; on older GTK
(including the AppImage's bundled 4.14) it stays on the proven CPU Cairo
renderer. The startup log prints the choice (renderer: GSK_RENDERER=…),
and setting GSK_RENDERER yourself always wins. Details in
docs/RENDERING.md.
- Radios: ANAN G2E, ANAN 10E/100B, Hermes Lite 2 (all live-verified here), ANAN G2/Saturn (enabled from an audit; live-tested by an external operator in two rounds, 2026-08, not calibrated by us) — whitelist, see above; one RX (RX2 planned)
- No FM yet, no built-in CAT (use tciadapter, see above)
- Audio flows through the PC only — the radio's own phones/mic jacks are not wired up
- Wattmeter uses a single per-band calibration factor — accurate on HF, over-reads ~25 % on 6 m (a guided nonlinear calibration is planned)
- GPU rendering needs GTK ≥ 4.22; on older GTK (e.g. the AppImage's bundled
4.14, where GL crashed on NVIDIA + Wayland) the display stays on the CPU
Cairo renderer (set
GSK_RENDERERyourself to override — seedocs/RENDERING.md)
Open an issue and paste the debug info from the app: menu → About → Troubleshooting → Debugging Information → Copy Text. It carries the app version, the GTK/libadwaita/WDSP/FFTW/PipeWire versions actually in use, the active renderer, the connected radio and protocol, and the config paths — which is most of what a diagnosis needs.
Radio (ANAN G2E / 10E — P2, Hermes Lite 2 — P1)
│ Ethernet (raw IQ)
▼
sdr-for-linux (single GTK4 process)
├─ HPSDR Protocol 1 + 2 links ┐
├─ WDSP DSP (demod, filters, AGC, │ engine (headless, GLib-only),
│ NR, TX chain, PureSignal, FFT) │ adapted from piHPSDR
├─ PipeWire audio I/O, TCI server ┘
└─ GTK4/libadwaita UI: panadapter, waterfall, controls (new)
Design notes live in docs/ — engine import scope, TX safety
rules (docs/TX-SAFETY.md), PureSignal scope, TCI
scope, band plans.
- piHPSDR — Christoph van Wüllen (DL1YCF) and John Melton (G0ORX) — the engine this project builds on.
- WDSP — Warren Pratt (NR0V) — the DSP library.
- Thetis — the PureSignal auto-attenuate behaviour follows its design.
- Dr. Lawrence W. Gray (W1IZZ) — live-tested and helped debug the ANAN G2/Saturn support on his radio (issue #3): RX probes, per-band PA calibration against an LP-100A, PureSignal numbers, and the fixes his two test rounds surfaced.
- Vendored: rnnoise (Xiph.Org/Mozilla), libspecbleach (Luciano Dato).
GPLv3. Builds on and derives from piHPSDR and WDSP, both GPLv3.
Richard Fakenberg — OK1BR — rifak.cz
