A new decoder crate covering the modes SSTV is actually sent in: Martin M1/M2, Scottie S1/S2/DX, Robot 36/72, PD50 through PD290, and Wraase SC2-180. The mode comes from the VIS header every transmission opens with, so nothing has to be told what is arriving. Modes are a table rather than code: a list of segments -- sync, gaps, and one scan per colour channel -- plus a colour model and a geometry. The decoder reads the offset of each scan straight off that list, which is what makes fifteen modes cost about as much as one, and a new mode a table entry. The segment lists are checked against the published line durations in a test, because both are transcribed by hand from the same specification and a digit wrong in one is unlikely to be wrong identically in the other. Signal path: band-pass over the SSTV band, Hilbert FIR, instantaneous frequency by phase difference, then a state machine that walks the transmission a line at a time. Each line is looked for where the mode says it should be and nudged into place by the sync pulse found near it -- two sound cards never agree exactly, and over the two minutes of a Martin M1 frame an uncorrected error of a few parts per million shears the picture visibly. Rows are emitted as they decode, so a picture can be watched arriving, which is most of the appeal of the mode. Four things this cost, each now the reason a piece of it is shaped the way it is: The per-sample frequency estimate ripples by ±95 Hz at 1200 Hz, where the Hilbert approximation is weakest, though its mean is exact. Pixels average over their own window and were always right; the VIS bits and the sync detector classify individual samples and were reading the ripple. Both now read short means. Pixels deliberately still do not, so edges stay where they are. Broadband noise cost the whole picture, not part of it: a phase-difference detector answers whatever is loudest, and there was no input filter. Hence the band-pass, which is what every real decoder does first. A sync search window shorter than a sync pulse rejected every pulse arriving late in it, for being short. The first line's sync search locked onto the VIS stop bit -- 30 ms at exactly the sync frequency, immediately before the picture starts. The header already says where the picture begins, so the first line no longer searches. Tests: nine modes are encoded from a test card and decoded back, compared pixel by pixel, alongside silence around the signal, a transmission cut off part way, two transmissions back to back, 20 dB of noise, and a transmitter clock 0.1% fast. The encoder that produces those signals reads the same table as the decoder, so a round trip tests the decoder and not the timings; the timings are held to the published line durations separately. Nothing is wired into the server or the web UI yet: this is the decoder alone. Signed-off-by: Stan Grams <sjg@haxx.space>
trx-rs splits radio hardware access from user-facing interfaces so you can run
rig control, SDR DSP, decoding, audio streaming, and web access as separate,
composable pieces.
| Backends | Yaesu FT-817, Yaesu FT-450D, SoapySDR |
| Frontends | Web UI, rigctl-compatible TCP, JSON-over-TCP |
| Decoders | AIS, APRS, CW, FT8, RDS, VDES, WSPR |
| Audio | Opus streaming between server, client, and browser |
Quick Start
1. Install dependencies
Debian / Ubuntu
sudo apt install build-essential pkg-config cmake libopus-dev libasound2-dev
# Optional — SDR support
sudo apt install libsoapysdr-dev
Fedora
sudo dnf install gcc pkg-config cmake opus-devel alsa-lib-devel
# Optional — SDR support
sudo dnf install SoapySDR-devel
Arch Linux
sudo pacman -S base-devel pkgconf cmake opus alsa-lib
# Optional — SDR support
sudo pacman -S soapysdr
macOS (Homebrew)
brew install cmake opus
# Optional — SDR support
brew install soapysdr
See Build Requirements in the wiki for details on each library.
Note:
cmakeis required even when a system Opus library is installed. Theaudiopus_syscrate probes for Opus viapkg-config; if it is not found (orpkg-configis unavailable), it falls back to compiling a vendored copy of Opus with CMake. A missingcmaketherefore fails the build withis cmake not installed?rather than a missing-Opus error.
2. Build
cargo build --release
Build without SDR support: cargo build --release --no-default-features
3. Configure
Run the interactive setup wizard to generate config files for your station:
./target/release/trx-configurator
The wizard walks you through rig selection, serial port detection, audio
settings, and frontend options, then writes trx-server.toml and
trx-client.toml.
Alternatively, generate example configs and edit them by hand:
./target/release/trx-server --print-config > trx-server.toml
./target/release/trx-client --print-config > trx-client.toml
4. Run
./target/release/trx-server --config trx-server.toml
./target/release/trx-client --config trx-client.toml
Open the configured HTTP frontend address in a browser (default http://localhost:8080).
How It Works
graph TD
SDR1["SDR #1"] & SDR2["SDR #2"] <-->|USB| S1["trx-server A"]
SDR3["SDR #3"] & FT817["FT-817"] <-->|USB / serial| S2["trx-server B"]
S1 <-->|"JSON-TCP :4530"| C1["trx-client"]
S1 -->|"Opus-TCP per rig"| C1
S2 <-->|"JSON-TCP :4530"| C1
S2 -->|"Opus-TCP per rig"| C1
C1 <-->|internal channels| F1["Web UI :8080"]
C1 <-->|internal channels| F2["rigctl :4532"]
Each trx-server owns one or more rigs and runs DSP, decoding, and audio capture locally.
A trx-client connects to any number of servers over TCP and exposes them through
a unified set of frontends.
Documentation
| Resource | Description |
|---|---|
| User Manual | Configuration, features, and usage |
| Architecture | System design, crate layout, data flow, and internals |
| Optimization Guidelines | Performance guidelines for the real-time DSP pipeline |
| Planned Features | Roadmap and design notes |
| Contributing | Commit conventions, workflow, and code style |
License
GPL-2.0-or-later. See LICENSES for the full license text and
bundled third-party license files. Bundled third-party components retain their
original licenses: Leaflet is BSD-2-Clause, DSEG is OFL-1.1, and opus-decoder
is MIT. The APRS symbol sprites come from
hessu/aprs-symbols; their per-symbol
copyright status is catalogued in
LICENSES/LicenseRef-APRS-Symbols.txt.
