# 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 ```powershell # 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 ```powershell .\fmrtx.exe --list-devices ``` ### Offline IQ file generation ```powershell .\fmrtx.exe --dry-run --dry-output build/dryrun/frame.json go run ./cmd/offline -duration 2s -output build/offline/composite.iqf32 ``` ### Real TX (PlutoSDR) ```powershell # 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 ```text 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 scripts/ examples/ ``` ## Legal note 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.