A resilient, open-source software modem that turns any SSB shortwave transceiver into a long-range digital link โ carrying text, files and structured messages with no towers, no internet and no satellites.
Author: Simon Keimer ยท DC0SK
Architecture
Amateur radio does not map perfectly onto the OSI model, but the model shows where each part of OpenPulseHF lives. A message travels down the stack to the air โ and back up on receive at the far station.
Authenticates the remote station over the radio: Ed25519 signed handshake, an optional post-quantum path (ML-DSA / ML-KEM), and a trust store.
Authenticates the operator client that commands the transmitter: a PSK-authenticated, encrypted Noise channel between the daemon and the operator panel.
Abstract
OpenPulseHF is a software-defined data modem and messaging stack for HF (shortwave) radio. It turns an ordinary SSB transceiver and a computer sound interface into a resilient digital link over hundreds to thousands of kilometres โ without any intervening infrastructure. At its core is an adaptive modem that measures the channel and steps its speed and modulation up or down to keep the link alive as propagation changes. Messages are protected by forward error correction and automatic retransmission; station identities and message integrity by modern cryptographic signatures, including post-quantum-safe options.
Status
A multi-crate Rust workspace: DSP primitives and adaptive rate profiles through ARDOP/KISS TNC interfaces, B2F/Winlink support, QSY frequency agility, mesh networking and post-quantum key exchange. All tests run against a deterministic loopback backend โ no audio hardware is required to build or test.
HARQ soft-combining across retransmissions was quietly throwing away most of its own gain โ it discarded retained soft-decision data whose length varied between bursts (which it does, on every fade), and an abandoned message's data could dilute the next one's. Both fixed: decode rate on a moderate HF fade rises 0.840 โ 0.957 where a single burst manages 0.582.
The weak-signal sub-floor rung (MFSK16) now gets HARQ too, worth about 2.5 dB
there โ it decodes frames at โ6 dB that no single transmission ever recovers, which is exactly
where a link has nothing else left. Also: openpulse session --diagnostics now reports
a real afc_offset_hz instead of always null. No wire, config or API
change; nothing to do to upgrade.
v0.4.0 โ JS8-based station discovery + rendezvous and direct signed P2P file transfer. ยท v0.3.0 โ signed Ed25519 handshake over the air on connect, automatic ADIF logbook, opt-in ARDOP adaptive ARQ, reworked operator panel. ยท v0.2.1 โ CE-SSB transmit envelope conditioning (+1.18 dB confirmed on-air).
Why OpenPulseHF
Several capabilities here do not exist elsewhere in open HF software โ or exist only as stubs. These are the ones with working implementations behind them.
ML-DSA-44 signing + ML-KEM-768 key encapsulation negotiated in-band. Hybrid mode signs with both Ed25519 and ML-DSA-44 simultaneously. No other open HF modem does this.
Single-Carrier FDMA โ the LTE uplink waveform โ brought to HF with DFT-CE pilot-aided channel estimation and MMSE equalization.
Real rate-1/2 min-sum belief propagation โ not a stub. First open-source HF software modem with working LDPC.
Soft LLR values accumulate across retransmissions (PACTOR-style Memory-ARQ), turning each retry into a soft combining gain.
A single-carrier family (PILOT-QPSK500โฆPILOT-32APSK500, up to DVB-S2
32APSK) whose known in-band pilots drive carrier tracking instead of a decision-directed Costas
loop โ cycle-slip-immune on dense constellations and robust to soundcard sample-rate offset.
Gray-coded 64QAM with a max-log-MAP soft demodulator. An aggressive constellation for VHF/UHF links with proper soft FEC backing.
Six wgpu compute kernels (BPSK modulate/demodulate, timing search, RRC FIR matched filter, 256-pt FFT, soft LLR demod) accelerating BPSK, QPSK, 8PSK, 64QAM and SC-FDMA โ all with automatic CPU fallback.
Controlled-Envelope SSB (Hershberger W9GR, QEX 2014) โ a voice-SSB technique โ applied as an adaptive per-mode TX conditioner that raises average power at fixed PEP on high-PAPR multicarrier modes. Confirmed +1.18 dB on-air, with no added splatter on QPSK OFDM. Believed to be the first open-source HF data modem to do this.
When idle, a station QSYs to the band's JS8 calling frequency and participates as a real JS8
station (native 8-GFSK / LDPC(174,87) โ not a JS8Call bridge), marking itself with an in-band
@OPULSE hint. Off by default; RX-only until the operator opts into TX.
Offer/accept file transfer over an RF session with an inline signed TransferManifest
+ SHA-256 verified against the peer's handshake key โ a tampered or wrong-key file is
quarantined with an UNVERIFIED badge. VarAC's file transfer does not do this.
A signed QSY_REQ/LIST/VOTE/ACK wire protocol with initiator and responder roles wired into the daemon; SNR-ranked channel-list negotiation and rig CAT control via rigctld.
Ed25519-signed authentication beacons transmitted via the FreeDV Qt-GUI UDP data port
(openpulse-freedv-auth) โ no FreeDV fork required.
Validation status: on-air regulatory validation (spectral mask) has not been completed. Except for the CE-SSB average-power confirmation above, all tests use loopback and simulated-channel paths only.
Modulation modes
Sorted by occupied bandwidth. The mode-name number is the baud rate for
single-carrier modes; SC-FDMA/OFDM modes are named by data-subcarrier count and span
total_SCs ร 31.25 Hz. The PILOT-* modes are a pilot-framed single-carrier
family: known in-band pilot symbols drive carrier recovery (cycle-slip-immune,
sample-rate-offset-robust) instead of a decision-directed Costas loop.
| Mode | Plugin | Baud | Bits/sym | Gross bps | Occ. BW | Waveform | Notes |
|---|---|---|---|---|---|---|---|
| Narrowband ยท โค 550 Hz | |||||||
| BPSK31 | bpsk | 31.25 | 1 | 31 | ~50 | Single-carrier | Weak-signal narrowband HF |
| BPSK63 | bpsk | 62.5 | 1 | 63 | ~70 | Single-carrier | |
| BPSK100 | bpsk | 100 | 1 | 100 | ~110 | Single-carrier | |
| QPSK125 | qpsk | 125 | 2 | 250 | ~140 | Single-carrier | |
| BPSK250 | bpsk | 250 | 1 | 250 | ~275 | Single-carrier (+RRC) | |
| QPSK250 | qpsk | 250 | 2 | 500 | ~275 | Single-carrier | |
| FSK4-ACK | fsk4 | 100 | 2 | 200 | ~400 | 4-FSK | ACK control channel only |
| QPSK500 | qpsk | 500 | 2 | 1 000 | ~550 | Single-carrier (+RRC) | |
| 8PSK500 | psk8 | 500 | 3 | 1 500 | ~550 | Single-carrier (+RRC) | Gray-coded |
| 64QAM500 | 64qam | 500 | 6 | 3 000 | ~550 | Single-carrier | |
| PILOT-QPSK500 | pilot | 500 | 2 | 1 000 | ~550 | Single-carrier (pilot-framed) | In-band pilots โ cycle-slip-immune carrier tracking; SRO-robust |
| PILOT-8PSK500 | pilot | 500 | 3 | 1 500 | ~550 | Single-carrier (pilot-framed) | Gray-coded; pilot-aided |
| PILOT-16QAM500 | pilot | 500 | 4 | 2 000 | ~550 | Single-carrier (pilot-framed) | Pilot-amplitude-referenced demap |
| PILOT-32APSK500 | pilot | 500 | 5 | 2 500 | ~550 | Single-carrier (pilot-framed) | DVB-S2 32APSK geometry |
| Mid-band ยท 625 Hz โ 1.1 kHz | |||||||
| OFDM16 | ofdm | โ | 2 | ~889 | ~625 | OFDM (16 SCs, QPSK) | LS + ZF; โก SCFDMA16 throughput |
| SCFDMA16 | scfdma | โ | 2 | ~889 | ~625 | SC-FDMA (16 SCs, QPSK) | DFT-CE + MMSE |
| SCFDMA26-8PSK | scfdma | โ | 3 | ~2 167 | ~1 000 | SC-FDMA (26 SCs, 8PSK) | Narrowband HOM (+3 dB/SC) |
| SCFDMA26-16QAM | scfdma | โ | 4 | ~2 889 | ~1 000 | SC-FDMA (26 SCs, 16QAM) | Narrowband HOM (+3 dB/SC) |
| SCFDMA26-32QAM | scfdma | โ | 5 | ~3 611 | ~1 000 | SC-FDMA (26 SCs, cross-32QAM) | Narrowband HOM (+3 dB/SC) |
| QPSK1000 | qpsk | 1 000 | 2 | 2 000 | ~1 100 | Single-carrier (+RRC/HF) | |
| 8PSK1000 | psk8 | 1 000 | 3 | 3 000 | ~1 100 | Single-carrier (+RRC/HF) | |
| 64QAM1000 | 64qam | 1 000 | 6 | 6 000 | ~1 100 | Single-carrier | |
| Wideband ยท ~2 031 Hz (multicarrier) | |||||||
| OFDM52 | ofdm | โ | 2 | ~2 889 | ~2 031 | OFDM (52 SCs, QPSK) | โก SCFDMA52 throughput; OFDM trades PAPR for per-SC EQ |
| OFDM52-8PSK | ofdm | โ | 3 | ~4 333 | ~2 031 | OFDM (52 SCs, 8PSK) | OFDM higher-order ladder โ the HF high-throughput path |
| OFDM52-16QAM | ofdm | โ | 4 | ~5 778 | ~2 031 | OFDM (52 SCs, 16QAM) | OFDM higher-order ladder |
| OFDM52-32QAM | ofdm | โ | 5 | ~7 222 | ~2 031 | OFDM (52 SCs, cross-32QAM) | OFDM higher-order ladder |
| OFDM52-64QAM | ofdm | โ | 6 | ~8 667 | ~2 031 | OFDM (52 SCs, 64QAM) | OFDM higher-order ladder |
| SCFDMA52 | scfdma | โ | 2 | ~2 889 | ~2 031 | SC-FDMA (52 SCs, QPSK) | Adaptive pilot density |
| SCFDMA52-P2 | scfdma | โ | 2 | ~2 889 | ~2 031 | SC-FDMA (52 SCs, PN pilots) | Low-PAPR SCFDMA52: Zadoff-Chu-phase pilots cut envelope-CCDF PAPR ~2.15 dB (8.85โ6.70) at the same geometry/rate and keep full DFT-CE (beats the flat-CE SCFDMA52-LP); demonstrator, not in any profile |
| SCFDMA52-LP | scfdma | โ | 2 | ~3 389 | ~2 031 | SC-FDMA (61 SCs, localized) | Low-PAPR demonstrator (~2 dB lower mean PAPR: 11.9โ9.7 โ mostly from 4 pilots vs 13, only ~0.5 dB from localization); single-tap flat-channel CE โ AWGN/flat/well-timed only (silently mis-decodes on selectivity/tilt/timing error), not in any profile |
| SCFDMA52-8PSK | scfdma | โ | 3 | ~4 333 | ~2 031 | SC-FDMA (52 SCs, 8PSK) | |
| SCFDMA52-16QAM | scfdma | โ | 4 | ~5 778 | ~2 031 | SC-FDMA (52 SCs, 16QAM) | |
| SCFDMA52-32QAM | scfdma | โ | 5 | ~7 222 | ~2 031 | SC-FDMA (52 SCs, cross-32QAM) | |
| SCFDMA52-64QAM | scfdma | โ | 6 | ~8 667 | ~2 031 | SC-FDMA (52 SCs, 64QAM) | |
| SCFDMA52-64QAM-P4 | scfdma | โ | 6 | ~8 167 | ~2 031 | SC-FDMA (49 SCs, dense pilots) | |
| Wideband single-carrier ยท ~2 700 Hz | |||||||
| QPSK2000-RRC | qpsk | 2 000 | 2 | 4 000 | ~2 700 | Single-carrier + RRC | |
| 8PSK2000-RRC | psk8 | 2 000 | 3 | 6 000 | ~2 700 | Single-carrier + RRC | |
| 64QAM2000-RRC | 64qam | 2 000 | 6 | 12 000 | ~2 700 | Single-carrier + RRC | Requires SNR โฅ 25 dB |
| VHF / UHF ยท deferred post-1.0 | |||||||
| QPSK9600-RRC | qpsk | 9 600 | 2 | 19 200 | ~13 000 | Single-carrier + RRC | deferredVHF/UHF, needs โฅ38.4 kHz Fs |
| 8PSK9600-RRC | psk8 | 9 600 | 3 | 28 800 | ~13 000 | Single-carrier + RRC | deferredVHF/UHF, needs โฅ38.4 kHz Fs |
The single-carrier modes also have -RRC (ฮฑ = 0.35, ~+35 % bandwidth) and
-HF tuning variants not all listed here. The -RRC variants are the
operational, carrier-offset-robust ones at 2000 baud: the plain rectangular QPSK2000 /
8PSK2000 are registered but RRC-superseded โ their crossfade pulse is ISI-limited
at 4 samples/symbol, so use -RRC.
Each PILOT-* mode also has a -RRC variant (~half the
occupied bandwidth) and 1000 / 2000-RRC baud rungs โ e.g.
PILOT-16QAM1000-RRC โ all selectable by name and surfaced by the
hpx_pilot{,_rrc,_fast,_fast_rrc} profiles.
The mode/FEC selection ladder and which combinations are usable on HF is documented in docs/mode-fec-ladder.md.
Who it's for
Operator interfaces
| Interface | Description |
|---|---|
Operator panelopenpulse-panel |
Full iced GUI on the daemon control port (TCP/WS): controls band (connection, PTT, mode/frequency, RF peer, toggles, TX-atten/squelch, OTA, QSY), live spectrum + waterfall + rate ladder, tabbed lower panel. Dark/Light/Contrast/System themes. |
Twin-station viewopenpulse-twinview |
egui both-directions viewer โ one window over two daemons; per-station spectrum/waterfall plus rate/OTA/HPX readouts, so both link directions show at once. |
TUIopenpulse-tui |
ratatui terminal UI โ colour-coded HPX state, AFC/rate meters, DCD energy bar, scrollable transitions log. |
CLIopenpulse-cli |
Transmit, receive, benchmark, monitor, config init, calibrate (audio/PTT/AFC). |
Signal testbenchopenpulse-testbench |
egui 4-column live view: TX / channel / mixed / RX; waterfall, spectrum, scatter; 7 channel models; SNR slider. |
Quick start
The test suite runs entirely against a deterministic loopback backend. No audio hardware, radio or station is required to build or test.
# Toolchain preflight (required: rustc >= 1.94.0) ./scripts/check-toolchain.sh # Build (requires libasound2-dev on Linux for the CPAL audio feature) cargo build --workspace # Test suite โ no audio hardware required cargo test --workspace --no-default-features # Lint cargo clippy --workspace --no-default-features -- -D warnings cargo fmt --all -- --check
A purely rig-less demo to get a first impression of the GUIs and the adaptive modem. None of it transmits on the air.
# Two-station ARQ link simulator GUI โ simulates BOTH stations over a virtual # HF channel. Tweak SNR / channel model / mode live and watch the ladder adapt. cargo run -p openpulse-linksim --features gui --bin openpulse-linksim-gui # Want the operator panel too? The simulator stands in for the daemon. cargo run -p openpulse-linksim --features "gui,serve" --bin openpulse-linksim-gui -- --serve 127.0.0.1:9000 cargo run -p openpulse-panel # in another terminal โ Connect
Interoperability
OpenPulseHF is GPL v3, but these interfaces let non-GPL software interoperate without
GPL obligations โ each sits behind a process or network protocol boundary. Note that plugins which
statically link openpulse-core are derivative works and must be GPL-compatible.
| Interface | Transport | Description |
|---|---|---|
| ARDOP TNC | TCP 8515/8516 |
ARDOP ASCII command protocol; Pat, Winlink Express and JS8Call compatible |
| KISS/AX.25 TNC | TCP 8100 |
Standard KISS framing; works with Xastir, YAAC, APRX, Linux AX.25 tools |
| Daemon control port | NDJSON / TCP 9000 |
Full event stream + control commands; operator panel and scripting |
| Daemon WebSocket | JSON / WS 9001 |
Same protocol as the TCP port; browser and Electron clients |
| PKI REST API | HTTP/JSON 8080 |
Trust-bundle and key-management endpoints; read-only routes unauthenticated |
| CLI subprocess | stdin / stdout |
NDJSON output; invocation crosses the process boundary |
| Winlink CMS gateway | B2F / TCP 8772 |
Outbound-only client to cms.winlink.org |
Supporters
For providing access to a remote-controllable station for testing.
For helping stuff the budget sink-hole.
For providing space on their booth at HAM RADIO 2026.
OpenPulseHF is free and open source under GPL v3. If it is useful to you, a donation funds sustained time on the modem, on-air testing, and better documentation โ and keeps the whole stack open, auditable and vendor-independent.