Commit Graph

460 Commits

Author SHA1 Message Date
sjg 6dc26e48a3 [feat](trx-backend-soapysdr): improve WFM audio quality
Replace one-pole sum/diff filters with a proper 4th-order Butterworth
cascade (Q = 0.5412 / 1.3066) at 15 kHz.  This reduces pilot tone
leakage from −4 dB to −12 dB at 19 kHz and suppresses the 38 kHz DSB
carrier from −9 dB to −32 dB, significantly improving stereo crosstalk.

Add a biquad notch at 19 kHz on the L+R channel to eliminate the residual
pilot tone that would otherwise be audible after downsampling to 48 kHz.

Replace nearest-neighbor (sample-hold) resampling with linear interpolation
inside WfmStereoDecoder.  The output sample is now placed at the exact
fractional position between the two adjacent composite samples using the
phase accumulator state, removing timing jitter and harmonic distortion on
sustained tones.

Add DC blockers (pole at 0.9999, corner ≈ 0.75 Hz at 48 kHz) to all audio
outputs to remove carrier frequency-offset DC from the FM discriminator
without any audible bass roll-off.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 15:46:56 +01:00
sjg 42f61de502 [style](trx-frontend-http): tighten overview spacing
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 15:30:02 +01:00
sjg cf8d0743ce [feat](trx-rds,trx-frontend-http): expand rds metadata display
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 15:27:26 +01:00
sjg 8827131264 [fix](trx-frontend-http): copy formatted rds ps text
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 15:11:29 +01:00
sjg b1fab91e0e [fix](trx-frontend-http): shrink rds pi fallback display
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 15:08:53 +01:00
sjg 27c8018d89 [feat](trx-frontend-http): show rds pi before ps arrives
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:55:38 +01:00
sjg b172ace0ee [feat](trx-rds,trx-backend-soapysdr): condition weak-signal rds updates
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:52:31 +01:00
sjg e9fa27be3a [fix](trx-rds): restore prior recovery path
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:46:42 +01:00
sjg 5a27cb634d [feat](trx-backend-soapysdr): prefilter rds subcarrier
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:41:19 +01:00
sjg 2874c63dd1 [fix](trx-rds): relax weak-signal commit thresholds
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:36:46 +01:00
sjg a94fcd75af [feat](trx-rds): add early-late timing correction
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:32:23 +01:00
sjg 017b7be8a8 [fix](trx-rds,trx-backend-soapysdr,trx-frontend-http): relax rds filtering
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:26:11 +01:00
sjg 778e695941 [fix](trx-frontend-http): sanitize stale tune step options
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:21:39 +01:00
sjg 2ed68e4210 [feat](trx-rds,trx-backend-soapysdr): improve weak-signal rds recovery
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:19:36 +01:00
sjg 0329be6124 [fix](trx-frontend-http): clarify jog step controls
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:16:09 +01:00
sjg 8f7afed132 [fix](trx-backend-soapysdr,trx-frontend-http): keep rds state on bw changes
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:13:06 +01:00
sjg 976f66d383 [feat](trx-frontend-http): format copied rds overlay text
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:08:20 +01:00
sjg f48e2a6a81 [feat](trx-frontend-http): improve rds pty and ps display
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:03:46 +01:00
sjg adadcb4a77 [fix](trx-backend-soapysdr,trx-frontend-http): preserve raw rds ps text
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 12:01:27 +01:00
sjg abab89b89c [feat](trx-frontend-http): refine rds overlay interactions
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:58:12 +01:00
sjg 2cd33386ef [fix](trx-frontend-http): add rx audio jitter buffer
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:53:50 +01:00
sjg f509500877 [fix](trx-frontend-http): restore synced frequency and rds badge
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:48:20 +01:00
sjg 4b5dd36778 [feat](trx-server,trx-client): raise default audio opus bitrate
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:33:52 +01:00
sjg b0bf9e3ee0 [feat](trx-rds,trx-frontend-http): reset rds on tune changes
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:31:42 +01:00
sjg e886f97eb9 [fix](trx-backend-soapysdr): back off after stream overruns
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:24:09 +01:00
sjg ee9add1b53 [feat](trx-frontend-http): move map into dedicated tab
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:22:14 +01:00
sjg b131b1d313 [fix](trx-rds): improve biphase symbol decoding
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:20:22 +01:00
sjg ab8a3f4889 [fix](trx-client): remove unused rigctl port local
Drop the now-unused rigctl_port local after removing\nthe shared rigctl listener path.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:11:31 +01:00
sjg 5428d063a7 [fix](trx-client): require per-rig rigctl listeners
Remove the shared rigctl listener path so rigctl only\nruns as per-rig listeners configured through\nfrontends.rigctl.rig_ports.\n\nTighten client config validation to require at least one\nper-rig rigctl port when the rigctl frontend is enabled.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:09:44 +01:00
sjg 6f09022563 [fix](trx-rs): sync sdr rds tuning and deemphasis default
Make the primary SoapySDR DSP channel follow the tuned\nfrequency so RDS decoding stays aligned with the active\nfrequency rather than the hardware center.\n\nMove the default WFM deemphasis setting to server SDR\nconfig and default it to 50 us, then pass that value into\nthe SoapySDR backend.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 11:04:40 +01:00
sjg 855d21fd8a [debug](trx-backend-soapysdr,trx-frontend-http): add RDS diagnostics
Add server-side debug log when RDS data is decoded (PI, PS, PTY).
Extend the RDS panel with active mode, frame counter, and a raw JSON
dump of the last spectrum frame (bins excluded) to help diagnose why
RDS remains absent from the SSE stream.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:31:24 +01:00
sjg 88e0be0cdd [feat](trx-frontend-http): mark spectrum peaks
Draw small peak markers on strong visible spectrum maxima\nso snap-tune targets are easier to spot.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:25:56 +01:00
sjg ff8625f04e [style](trx-frontend-http): align auto bw button sizing
Apply the same explicit height and padding rules to the\nAuto BW button as the Set button in the spectrum\ncontrols, including the mobile layout.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:17:47 +01:00
sjg f7367e6270 [feat](trx-frontend-http): add RDS debug panel in Plugins tab
Add an RDS sub-tab to the Plugins panel showing PI code, PS name, PTY
number and name, decoder status, and a raw JSON dump of the latest RDS
data received via SSE. Also list the RDS decoder in the Overview tab.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:16:15 +01:00
sjg 8b3951d99d [fix](trx-frontend-http): show peak level in tooltip
Include the snapped peak signal level in the spectrum\nhover tooltip alongside the peak frequency.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:11:09 +01:00
sjg d5b1b6f020 [fix](trx-backend-soapysdr): widen WFM IQ filter to preserve RDS subcarrier
The FIR LPF cutoff was audio_bandwidth_hz/2; with wfm_bandwidth_hz=75000
this gave 37.5 kHz, stripping the 57 kHz RDS subcarrier before FM
demodulation. Clamp the IQ filter bandwidth to at least 130 kHz (cutoff
≥ 65 kHz) for WFM so the RDS subcarrier always reaches the decoder,
regardless of the configured audio bandwidth.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:10:14 +01:00
sjg e1ab2ae9dc [feat](trx-frontend-http): add automatic bandwidth sizing
Add an Auto BW control that estimates a suitable\nreceive bandwidth from the live spectrum around the\ncurrently tuned peak and applies it to the server.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:09:39 +01:00
sjg 454cf33d6b [fix](trx-frontend-http): sync tuned marker after set_freq
Update the local tuned-frequency state immediately after\nsuccessful set_freq requests so the marker and display stay\nin sync with click-to-tune, manual entry, and jog tuning.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:07:22 +01:00
sjg bfb09213e0 [fix](trx-frontend-http): improve spectrum hover feedback
Show snapped peak frequencies in the spectrum hover tooltip\nand move the bandwidth label to the bottom of the tuned\nfrequency marker.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 09:03:44 +01:00
sjg 3ab8ca8c1e [fix](trx-frontend-http): snap tuning clicks to peaks
Improve spectrum click-to-tune by snapping the selected\nfrequency to a nearby dominant local peak, making signals\neasier to select.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:59:35 +01:00
sjg 3f29ba3db8 [fix](trx-server): inherit global [audio].listen for per-rig audio listeners
In multi-rig mode, each RigInstanceConfig.audio.listen defaulted to
127.0.0.1 independently of the global [audio] listen setting, causing
per-rig audio ports to bind to localhost only and refuse connections
from remote clients.

Fix by passing cli.listen.or(Some(cfg.audio.listen)) as the listen
override, so the global address is always the fallback when --listen
is not supplied on the CLI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:59:15 +01:00
sjg c7b99f6fa9 [fix](trx-frontend-http): hide rig selector when logged out
Keep the top bar visible for unauthenticated users, but\nhide the rig selector until a session is established.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:57:02 +01:00
sjg b27c2f8d73 [feat](trx-frontend-http): adjust auth header and style ids
Keep the top bar visible while logged out, limit access to\nthe Main tab, and leave theme controls available while the\nrig selector stays disabled.\n\nRename the internal style ids from nord/arctic and\nmonokai/lime, including a compatibility remap for saved\nsettings.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:53:51 +01:00
sjg 4b93e8ff97 [feat](trx-frontend-http): rename theme labels
Rename the Nord and Monokai theme labels in the web UI\nto Arctic and Brownie, and update the matching CSS\nsection comments.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:46:10 +01:00
sjg 2f2a74b810 [chore](trx-app): drop per-binary config file support
Only trx-rs.toml with [trx-server] / [trx-client] section headers is
now supported. Simplify ConfigFile trait to a single required method
section_key(); remove config_filename(), combined_key(), and
default_search_paths(). load_from_file() now errors when the expected
section is absent rather than falling back to flat parsing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:45:32 +01:00
sjg 1ee0389de8 [docs](trx-rs): add libsoapysdr dependency note
Update the README system libraries section to list\nlibsoapysdr as a build-time requirement for SoapySDR\nSDR backends.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:44:17 +01:00
sjg b5a1b4af33 [feat](trx-frontend-rigctl): per-rig rigctl listeners for multi-rig setups
Add rig_ports map to RigctlFrontendConfig. When non-empty, one rigctl
TCP listener is spawned per entry instead of the single shared listener,
each routing commands to its assigned rig via rig_id_override on RigRequest.

Add rig_id_override: Option<String> to RigRequest so the remote client
can route individual requests to a specific rig without changing the
globally selected rig. build_envelope prefers the override when set.

Example config:
  [frontends.rigctl]
  enabled = true
  listen = "127.0.0.1"
  port = 4532
  rig_ports.ft817 = 4532
  rig_ports.airspyhf = 4533

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:41:39 +01:00
sjg 2c2a0951a5 [docs](trx-rs): update README config file docs
Document the combined trx-rs.toml search order and clarify\nthe HTTP auth example for combined vs legacy config files.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:39:55 +01:00
sjg 7a4c2d52b1 [chore](trx-rs): drop legacy ~/.trx-{server,client}.toml search paths
Remove the home-directory dotfile paths that predate the XDG layout.
Search order is now: CWD → ~/.config/trx-rs/ → /etc/trx-rs/, checked
for both the combined trx-rs.toml and the per-binary flat file at each
tier.

Update doc comments and tests accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:31:21 +01:00
sjg 5d43578e03 [chore](trx-rs): replace per-binary example configs with trx-rs.toml.example
Remove trx-server.toml.example and trx-client.toml.example in favour of
a single trx-rs.toml.example using [trx-server] and [trx-client] section
headers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-02-28 08:18:09 +01:00