SDD V1.2 · 2026-08-04

MRRC-FT8
Software Design Description

Canonical design record for the headless FT8/FT4 server — architecture, interfaces, operational model, and runtime evolution.

SDD Scope

IBM TeamSD aligned, 15 chapters, implementation-grounded content.

AttributeValue
Document IDSDD-MRRC-FT8-2026-001
VersionV1.2
Baseline Date2026-08-04
PhaseLive on radio.vlsc.net:9988 (FT-710)
RuntimeWSJT-X 3.0.2 Improved DSP + FastAPI + Uvicorn + NumPy
FrontendHTML5, CSS3, vanilla JavaScript, Canvas PWA
Core InterfacesFastAPI REST/WS + supervised DSP Worker IPC + rigctld loopback

What Landed In V1.2

FT-710 Rig Levels via Raw CAT

ATT / PREAMP / AGC / RF gain now switch through raw \send_raw CAT frames instead of hamlib's L/l level path, which the FT-710 never answers (verified live 2026-08-04 against the station rigctld). Codes: RA01;=6 dB, PA01;=10 dB, GT06;=AUTO — hamlib 4.7.2 sends the wrong GT04; — and RG0<NNN>;=0..1. The drawer reads the rig's real state and drops the stale snapshot after every write.

FT-710 Filter Width Raw-SH

Hamlib 4.6.2 mis-framed the width command (SH0NN; instead of SH00NN;) so M <mode> <width> never changed the rig. The width now goes through raw \send_raw with the true SH-register readback (1.8 / 2.4 / 3.0 kHz), compatible with the hamlib 4.7.2 upgrade. TX power (PC0…;) is rejected by the FT-710 and is deliberately not exposed.

MRRC-FT8 web cockpit — live FT8 band activity and decodes on 14.074 MHz (20 m)

The live cockpit: 20 m FT8 band activity and decodes on 14.074 MHz.

What Landed In V1.1

UtcRing Eviction Root Cause

Physical ring positions were keyed to (absolute − base) % capacity, so once eviction advanced base, reads addressed samples with the new base while data never moved — a shift growing 1:1 with wall clock, wrapping at capacity. Positions now key to the absolute sample index alone (X % capacity): eviction never moves data, base is purely a bounds check.

Replay Opposite-TX-Slot Phase

The reply path was missing the UC-003 "opposite TX slot": TxDriver gated on a hard-coded even parity that never changed, so replies to partners on the same phase always collided. The sequencer now carries tx_phase = 1 − slot_id % 2 and the QSO alternates to completion.

Manual Reply Decision Window

Replies always missed the slot right after the message they answer. The TX decision is now provisional: the window stays open until decision_cutoff with polling instead of sleeping, and a fit guard defers past-fit-deadline replies to the next eligible slot.

3 kHz Waterfall + Band Selector

Spectrum frames now emit only the 3 kHz FT8 passband — no blank half-canvas, half the payload. A band selector in the cockpit top bar tunes 7/14/21/28 MHz FT8 dial frequencies via the lease-gated /radio/band mutation.

15 SDD Chapters

AD-001 ... AD-015

AD-001 Headless Layered Server AD-002 WSJT-X C ABI AD-003 Supervised DSP Worker AD-004 Fixed Audio Rate Domains AD-005 Single DSP Owner + Lock AD-006 UTC Epoch Slot Discipline AD-007 Sequencer/PTT Safety AD-008 rigctld Serial Owner AD-009 Caddy Edge + Cookie Auth AD-010 Single Control Lease AD-011 Landscape-First Cockpit AD-012 Human Selection, Single QSO AD-013 Separate Bounded Streams AD-014 SQLite + ADIF AD-015 Native Service Deployment