Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Jan Svabenik 3b6d9bdac6 docs: add pro runtime hardening workboard 1 kuukausi sitten
cmd perf: add runtime timing diagnostics for Linux Pluto TX path 1 kuukausi sitten
docs docs: add pro runtime hardening workboard 1 kuukausi sitten
examples Add output backend abstractions 1 kuukausi sitten
internal perf: add runtime timing diagnostics for Linux Pluto TX path 1 kuukausi sitten
libiio feat: add hardware TX mode with PlutoSDR and SoapySDR drivers 1 kuukausi sitten
scripts feat: add Linux PlutoSDR support and Orange Pi build tooling 1 kuukausi sitten
.gitignore feat: add driver/uri/deviceArgs backend config plumbing 1 kuukausi sitten
CHANGELOG.md docs: mark current hardware baseline as v0.7.0-pre 1 kuukausi sitten
PROJECT_PLAN.md docs: switch plan to windows-first and soapy-first 1 kuukausi sitten
README.md docs: add pro runtime hardening workboard 1 kuukausi sitten
RELEASE.md docs: mark current hardware baseline as v0.7.0-pre 1 kuukausi sitten
go.mod feat: add pre-emphasis, MPX limiter and FM IQ modulation DSP blocks 1 kuukausi sitten
stream_tx.bat config: switch stream_tx.bat to svabi.ch source 1 kuukausi sitten

README.md

fm-rds-tx

Go-based FM stereo transmitter with RDS. Supports ADALM-Pluto (PlutoSDR) and any SoapySDR-compatible TX device.

Status: v0.7.0-pre — hardware bring-up milestone

What works

  • Complete DSP chain: pre-emphasis → stereo encoding → RDS (IEC 62106) → MPX → limiter → FM modulation
  • Real hardware TX via SoapySDR CGO binding (PlutoSDR tested)
  • Continuous TX engine with Start/Stop/Stats
  • IQ resampling (composite rate → device rate)
  • HTTP control plane with /tx/start, /tx/stop, /runtime
  • 82 passing tests including spectral verification

Signal path

Audio Source → PreEmphasis(50µs) → StereoEncoder(19k+38k) → RDS(57k)
→ MPX Combiner → Limiter → FM Modulator(±75kHz)
→ IQ Resample(228k→528k) → SoapySDR → PlutoSDR RF

Build

# Without hardware (simulation/offline only):
go build ./cmd/fmrtx
go build ./cmd/offline

# With SoapySDR hardware support (requires PothosSDR installed):
go build -tags soapy ./cmd/fmrtx

Usage

List available SDR devices

.\fmrtx.exe --list-devices

Offline IQ file generation

.\fmrtx.exe --dry-run --dry-output build/dryrun/frame.json
go run ./cmd/offline -duration 2s -output build/offline/composite.iqf32

Real TX (PlutoSDR)

# Start with manual TX control via HTTP:
.\fmrtx.exe --tx --config docs/config.plutosdr.json

# Start with auto-TX on launch:
.\fmrtx.exe --tx --tx-auto-start --config docs/config.plutosdr.json

HTTP control

POST http://localhost:8088/tx/start    → start transmission
POST http://localhost:8088/tx/stop     → stop transmission
GET  http://localhost:8088/runtime     → engine + driver telemetry
GET  http://localhost:8088/status      → config status
GET  http://localhost:8088/config      → full config
POST http://localhost:8088/config      → patch config (freq, RDS, etc.)
GET  http://localhost:8088/dry-run     → dry-run summary
GET  http://localhost:8088/healthz     → health check

PlutoSDR notes

  • Device rate: 528 kHz (PlutoSDR minimum ~521 kHz)
  • IQ format: CF32 (float32 interleaved I/Q)
  • Gain range: 0–89 dB (outputDrive 0..1 maps to 0..89 dB)
  • SoapySDR driver name: plutosdr
  • Requires: PothosSDR or SoapySDR + SoapyPlutoSDR plugin installed

Repository layout

cmd/
  fmrtx/          main CLI (--tx, --dry-run, --simulate-tx, --list-devices)
  offline/        offline IQ file generator
internal/
  app/            TX engine (continuous chunk loop) + simulated transmit
  audio/          sample types, WAV loader, resampler, tone generator
  config/         config schema, validation, PI parsing
  control/        HTTP control plane (/tx/start, /tx/stop, /runtime)
  dryrun/         JSON dry-run summaries
  dsp/            oscillator, pre-emphasis, FM modulator, limiter, Goertzel, IQ resampler
  mpx/            MPX combiner
  offline/        offline composite generation (full DSP chain)
  output/         backend abstractions (file, dummy)
  platform/       SoapyDriver interface, SoapyBackend, SimulatedDriver
  platform/soapysdr/  CGO SoapySDR native binding (build tag: soapy)
  rds/            RDS encoder (IEC 62106, CRC, differential, group scheduler)
  stereo/         stereo encoder (19 kHz pilot, 38 kHz DSB-SC)
docs/
  config.sample.json                default config
  config.plutosdr.json              PlutoSDR-specific config
  pro-runtime-hardening-workboard.md  living workboard for pro runtime hardening
scripts/
examples/

Planning / workboard

For the current pro-runtime-hardening track, see:

  • docs/pro-runtime-hardening-workboard.md

This document is the detailed working board for status tracking, confirmed findings, open decisions, verification notes, and implementation progress.

This project is intended only for lawful use within relevant license and regulatory constraints. RF output, deviation, filtering, and transmitted power must be validated with proper measurement equipment.