Map ClientCommand::SetSdrLnaGain { gain_db } to and from
RigCommand::SetSdrLnaGain in both directions.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Add hardware AGC on/off control for SoapySDR backend, wired through the
full stack from RigCommand to the web UI:
- RigCommand::SetSdrAgc(bool) + ClientCommand::SetSdrAgc in protocol
- set_sdr_agc() on RigCat trait (not-supported default)
- SoapySdrRig: agc_enabled field, set_sdr_agc() via pipeline agc_cmd,
sdr_agc_enabled in filter_state(); removes the "not yet implemented"
warning — gain_mode="auto" now properly enables hardware AGC via
SoapySDR set_gain_mode()
- IqSource::set_gain_mode() trait method; RealIqSource implements it
- SdrPipeline: agc_cmd channel, read loop applies it each iteration
- POST /set_sdr_agc endpoint in trx-frontend-http
- New "SDR settings" full-row in index.html with Hardware AGC checkbox
and RF Gain (moved out of WFM controls); row hidden when
show_sdr_gain_control is false
- app.js: AGC checkbox handler, disables RF gain input while AGC is on,
syncs checkbox state from filter.sdr_agc_enabled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Add [workspace.package] version = "0.1.0" to the root Cargo.toml and
switch all 21 member crates to version.workspace = true so the entire
workspace is versioned from a single place.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
MARINE was a composite mode that ran both AIS and VDES decoders
simultaneously. It is now fully replaced by allocating two virtual
channels — one tuned to the AIS frequencies and one to VDES — each
decoded independently.
- trx-core/state: remove RigMode::MARINE variant
- trx-protocol/codec: remove MARINE parse/serialize
- trx-backend-ft817: remove MARINE from unsupported-mode guard
- trx-backend-ft450d: remove MARINE from FM CAT code mapping
- trx-backend-soapysdr: remove MARINE from bandwidth table, supported
modes list, AIS channel activity check, parse_rig_mode, vchan_impl
bandwidth table, demod selection, dsp/channel bandwidth / sample-rate
/ IQ-tap guards
- trx-server/audio: remove MARINE from AIS and VDES decoder activation
- trx-server/rig_task: remove MARINE from audio-streaming mode list
- trx-server/main: remove MARINE from bandwidth table, mode parser,
VDES channel subscription match
- app.js: remove isMarineMode(), MARINE entry in MODE_BW_SPECS, MARINE
bandwidth specs block in visibleBandwidthSpecs(), MARINE from
decoder status mode lists, MARINE BW-edge drag guard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Adds a second APRS demodulator path tuned for the HF APRS standard
(300 baud Bell 103-style AFSK, mark=1600 Hz / space=1800 Hz), active
on RigMode::DIG. Shares AX.25 framing, APRS parsing, APRS-IS uplink,
and frontend display with the existing VHF stack.
- trx-aprs: parameterise Demodulator::new(); add AprsDecoder::new_hf()
- trx-core: HfAprs variant in DecodedMessage; hf_aprs_decode_enabled /
hf_aprs_decode_reset_seq in RigState/RigSnapshot; SetHfAprsDecodeEnabled
and ResetHfAprsDecoder commands; handlers.rs fallback arm updated
- trx-protocol: client command variants + bidirectional mapping; test
fixture updated
- trx-server: run_hf_aprs_decoder() task (activates on DIG mode);
hf_aprs history in DecoderHistories; rig_task command dispatch;
aprsfi uplink forwards HfAprs via OR-pattern
- trx-frontend: hf_aprs_history in FrontendRuntimeContext
- trx-frontend-http: prune/record/snapshot/clear helpers; SSE history
replay; toggle_hf_aprs_decode + clear_hf_aprs_decode endpoints;
/hf-aprs.js endpoint; HF APRS tab in web UI
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Keep weak VDES bursts visible by emitting unsynced diagnostic frames instead of dropping them, remove receiver badges from FT8 and WSPR history rows, and carry the current MARINE composite-mode scaffolding through the shared mode enums and backend mappings.
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Add a new trx-vdes decoder path alongside AIS, wire VDES through the server/frontend decode pipeline, and fix the web map so AIS vessel symbols load correctly and the TRX receiver marker appears when location data arrives.
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Add dual-channel AIS decode support across the SoapySDR backend, server decode pipeline, and frontend plugins, including the new AIS tab, live bar, and map filtering.
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Wire the StereoDenoise processor through the full stack:
- Add SetWfmDenoise command variant and RigCat trait method (trx-core)
- Add wfm_denoise field to RigFilterState with default true
- Add protocol command and bidirectional mapping (trx-protocol)
- Add rig_task command handler (trx-server)
- Implement set_wfm_denoise in SoapySdrRig backend
- Add /set_wfm_denoise API endpoint (trx-frontend-http)
- Add denoise checkbox in WFM controls with SSE sync and
localStorage persistence
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Add a server-side toggle for the multiband stereo denoiser so it can be
enabled or disabled at runtime without restarting the server.
Backend (trx-backend-soapysdr):
- Add `denoise_enabled: bool` to `WfmStereoDecoder`; gate multiband
blend behind it (falls back to uniform single-band blend when off)
- Add `set_denoise_enabled()` method on `WfmStereoDecoder`
- Propagate `wfm_denoise: bool` through `ChannelDsp`, `SdrPipeline`,
and `SoapySdrRig`; add `set_wfm_denoise()` at each layer
- Include `wfm_denoise` in `filter_state()` so it flows into snapshots
Protocol / core (trx-core, trx-protocol, trx-server):
- Add `SetWfmDenoise(bool)` to `RigCommand` and `ClientCommand`
- Add default `set_wfm_denoise()` trait method to `RigCat`
- Handle `SetWfmDenoise` in `rig_task.rs` and update `RigFilterState`
- Add `wfm_denoise: bool` (default `true`) to `RigFilterState`
Frontend (trx-frontend-http):
- Add `POST /toggle_wfm_denoise` endpoint
- Add "Denoise On/Off" button next to the stereo/mono audio picker
- Sync button state from SSE filter snapshot (`update.filter.wfm_denoise`)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Add SpectrumData struct (bins, center_hz, sample_rate) to RigState and
RigSnapshot. Add GetSpectrum RigCommand and ClientCommand plumbed through
the protocol layer. SoapySDR DSP pipeline now computes a 1024-bin FFT
(Hann window, FFT-shifted, dBFS) every 4 IQ blocks (~10 Hz update rate)
and exposes it via RigCat::get_spectrum(). The rig_task handles
GetSpectrum without persisting spectrum data in ongoing state.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Include optional display_name field in GetRigs response to allow clients
to show friendly rig names instead of just identifiers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Improve assertion and struct literal formatting across test cases
for better code clarity and consistency.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add SetBandwidth { bandwidth_hz: u32 } and SetFirTaps { taps: u32 } to
ClientCommand with bidirectional mapping to RigCommand variants.
Add UC-09 protocol serialization tests confirming that RigSnapshot
serializes the filter field when Some and omits it when None.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Add GetRigs command, rig_id routing fields, and RigEntry type:
- ClientCommand::GetRigs (intercepted in listener before rig_task)
- rig_id: Option<String> on ClientEnvelope (absent = first rig)
- rig_id: Option<String> and rigs: Option<Vec<RigEntry>> on ClientResponse
- RigEntry { rig_id, state } for GetRigs aggregated response
- Sentinel unreachable!() arm for GetRigs in client_command_to_rig()
- MR-09 codec tests: rig_id parsing, GetRigs round-trip, serde omit-when-None
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>