Commit Graph

621 Commits

Author SHA1 Message Date
sjg 2188d62069 [feat](trx-frontend): rich popup for receiver/owner marker on map
Replace plain-text receiver marker popup with a styled info card
matching the APRS popup layout.  Shows:
- Station callsign (serverCallsign / ownerCallsign)
- trx-server version and build date
- Owner callsign (when different from station callsign)
- QTH coordinates
- All configured rigs with manufacturer/model; active rig badged

Rig data (manufacturer, model, display_name, active state) is
stored in serverRigs/serverActiveRigId on each /rigs refresh.
Popup content is rebuilt live on popupopen so it always reflects
the current state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 17:58:48 +01:00
sjg c2add05a7c [fix](trx-frontend): use server decode history only
Remove APRS client-side persistence, reset decode views before replay,
and clear decode panes only after the server clears its history.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 17:58:16 +01:00
sjg 0e6d2c0c47 [style](trx-frontend): theme radio path line via CSS var
Remove hardcoded #3388ff colour from L.polyline options; use
stroke: var(--accent-green) and stroke-opacity in the CSS class
so the path follows the active colour scheme automatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 17:53:52 +01:00
sjg 1ef1da7c0d [feat](trx-frontend): show animated radio path on APRS station click
Draw a blue dashed polyline from the receiver to the clicked APRS
station on popup open; remove it on popup close.  CSS stroke-dashoffset
animation creates a traveling-dash effect suggesting signal propagation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 17:50:39 +01:00
sjg 6e9d0040bb [fix](trx-frontend): preserve APRS reception timestamp across page refresh
Previously aprsMapAddStation forced Leaflet map init on a hidden element
during history restore.  When live packets later arrived they stamped a
fresh _tsMs, resetting the displayed age to "0s ago".

Decouple data storage from Leaflet rendering:
- aprsMapAddStation now stores station data in stationMarkers immediately
  (with the original _tsMs from localStorage) without touching the map
- _aprsAddMarkerToMap creates Leaflet markers only when the map is ready
- initAprsMap materialises all buffered APRS entries on first open

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 17:47:43 +01:00
sjg 42e73f5eeb [fix](trx-frontend): fix APRS map popup age, distance, and dark theme
- Rebuild popup content on popupopen event so age and distance
  are always computed fresh at the moment of opening; store
  _aprsCall on each marker for O(1) lookup
- Extend map to fill viewport down to the footer instead of 60%
- Override Leaflet popup background/color to use CSS theme vars,
  fixing invisible text in dark theme

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 17:27:38 +01:00
sjg db425156a4 [feat](trx-frontend-http): rich APRS map tooltips with distance and age
Each station popup now shows:
- Callsign/SSID header
- Age (s/min/h ago, from _tsMs stamped on receive)
- Distance from receiver (Haversine, km or m)
- Packet type and via path
- Full info/comment string

Adds haversineKm(), formatTimeAgo(), buildAprsPopupHtml() helpers in
app.js and .aprs-popup-* CSS. Passes full packet object as 7th arg
to aprsMapAddStation from aprs.js.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 17:19:00 +01:00
sjg dd051beee3 [style](trx-frontend-http): match APRS tab clear button to CW reference
Remove custom #aprs-clear-btn CSS overrides and SVG icon; reduce to a
plain <button>Clear</button> so it inherits the same global button
style as the CW clear button.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 16:37:37 +01:00
sjg f537e1a11b [feat](trx-client): add configurable initial map zoom
Add an HTTP frontend config option for the initial APRS map zoom,
expose it through frontend metadata, and apply it in the web UI.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 16:35:12 +01:00
sjg 8c6c370563 [style](trx-frontend): rebalance aprs overlay title spacing
Tighten the spacing inside the APRS title while adding more room
between the title and the clear action.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:33:32 +01:00
sjg 1ae44a714f [style](trx-frontend): reduce aprs clear text size
Scale the APRS overlay inline clear text down for better balance
with the enlarged APRS title.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:31:28 +01:00
sjg 21a019a0fa [style](trx-frontend): enlarge aprs overlay title
Increase the APRS overlay header base text size so the title reads
larger alongside the clear action.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:28:50 +01:00
sjg 81dca146cf [style](trx-frontend): enlarge aprs clear text
Increase the APRS overlay inline clear text size for stronger
readability.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:25:49 +01:00
sjg 5b3d0c0865 [style](trx-frontend): increase aprs overlay text size
Increase the APRS overlay header text and make the inline clear text
match the row's base text size.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:24:32 +01:00
sjg aa73a4bc00 [style](trx-frontend): simplify aprs overlay clear action
Render the APRS overlay clear action as inline clickable text inside
a span wrapper instead of a button-like control.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:23:08 +01:00
sjg eec147c26f [style](trx-frontend): reduce aprs overlay header height
Cut the APRS overlay header sizing further so the row reads much
smaller and no longer dominates the overlay.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:20:46 +01:00
sjg 579ce31bbd [style](trx-frontend): inset aprs overlay from edges
Offset the APRS overlay slightly from the waterfall edges so it reads
as a hovering strip and leaves the waterfall visible at the sides.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:20:08 +01:00
sjg 69253959c8 [style](trx-frontend): shrink aprs overlay clear control
Reduce the APRS overlay clear control so it no longer sets the
header row height.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:18:42 +01:00
sjg 17a643d070 [style](trx-frontend): polish aprs overlay clear control
Wrap the APRS overlay clear action in a styled span and place it
next to the APRS title for a tighter header layout.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:16:20 +01:00
sjg 26e51447d7 [style](trx-frontend): tighten aprs overlay header
Reduce the APRS overlay header height by trimming spacing and scaling
down the clear control chrome.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:14:39 +01:00
sjg b24d6663a2 [style](trx-frontend-http): align RDS bar border-radius with UI standard
Replace 999px pill on #rds-ps-overlay with 6px to match the rest of
the UI button rounding.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:13:20 +01:00
sjg 436e1d8e23 [style](trx-frontend-http): align APRS bar border-radius with UI standard
Replace 999px pill radii with 6px (overlay), 4px (clear btn, pin),
3px (clear icon) — matching the standard button radius used throughout
the rest of the UI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:12:53 +01:00
sjg b6848c0c8e [style](trx-frontend): refine aprs web controls
Restyle the APRS clear button and tighten the APRS overlay bar to use
more compact, polished chrome while keeping the existing behavior.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:06:36 +01:00
sjg 39c4f1d800 [style](trx-frontend-http): tighten APRS bar entry spacing further
Reduce line-height to 1.05, use 0.1rem vertical padding + hairline
border-bottom to separate entries instead of whitespace.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:01:59 +01:00
sjg c60b764acb [style](trx-frontend-http): restyle APRS bar clear button as slim rect
Smaller font (0.65em), horizontal padding only, line-height-based
height, tighter border-radius — produces a flat wide rectangle tag
rather than a square button.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 15:00:52 +01:00
sjg 1b34d75a31 [style](trx-frontend-http): sticky APRS bar header on scroll
Make the APRS/Clear header row position:sticky so it stays visible
when the frame list is scrolled. Adds a subtle backdrop-blur background
and a divider border so frames slide cleanly beneath it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:59:40 +01:00
sjg 8359beae5c [style](trx-frontend-http): tighten APRS bar entry spacing
Remove inter-frame gap and reduce line-height 1.45→1.2.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:59:09 +01:00
sjg 3e5df90c8f [style](trx-frontend-http): APRS bar clear button rounded rect
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:58:02 +01:00
sjg 8e353620de [style](trx-frontend-http): replace coord sub-line with inline pin button
When a frame carries a position, show a small 📍 button between the
timestamp and callsign on the same line. Title tooltip shows the
coordinates; clicking navigates to the Map tab. Removes the two-line
per-entry layout.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:56:24 +01:00
sjg a7ba1eec5f [style](trx-frontend-http): tighten APRS bar spacing, shrink clear btn, remove cap
- Reduce frame line-height 1.45→1.3 and pos sub-line to 1.1 to close
  the gap between the info and coordinate rows within each entry
- Shrink clear button (smaller padding, 0.78em font)
- Remove 5-entry cap; full history visible via scroll

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:55:37 +01:00
sjg 7c810729ed [fix](trx-frontend-http): fix APRS bar coords visibility, cap at 5 entries
Coordinates were clipped by white-space:nowrap on the frame row.
Split each frame into a .aprs-bar-frame-main line (nowrap+ellipsis)
and a separate .aprs-bar-frame-pos line for the coordinate button,
so coordinates are always visible regardless of info length.
Restore 5-entry cap (slice from history).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:51:02 +01:00
sjg 5987a0b4a8 [feat](trx-frontend-http): add Clear button to APRS bar overlay
Small pill-shaped button in the header row, right-aligned. Clicking
it delegates to the existing aprs-clear-btn, clearing history, the
packet panel, and the bar in one shot.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:49:48 +01:00
sjg 37966ea29a [feat](trx-frontend-http): clicking APRS bar coords navigates to Map
Add window.navigateToAprsMap(lat, lon) which activates the Map tab
and pans to the given position at zoom 13. APRS bar frames that carry
a position render a clickable coordinate button that calls this
function. Button is styled inline with the frame text.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:49:04 +01:00
sjg 8ffe73c539 [fix](trx-server): drop CRC-failed APRS frames before sending to clients
Guard both the live broadcast (decode_tx.send) and the history store
(record_aprs_packet) so CRC-failed packets are never forwarded to
connected clients or replayed on reconnect. The decode logger still
receives all frames for debugging.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:47:54 +01:00
sjg df612aae00 [fix](trx-frontend-http): APRS bar shows full history, no truncation
Drop APRS_BAR_MAX cap and the separate aprsBarFrames ring buffer;
drive the bar directly from aprsPacketHistory (CRC-ok frames only).
Remove the 60-char info truncation. CSS opacity fading still kicks in
after frame 5; older frames are reachable by scrolling.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:46:40 +01:00
sjg b552829c95 [style](trx-frontend-http): APRS bar spans full waterfall width
Stretch overlay edge-to-edge (left/right: 0), drop side borders and
border-radius for a full-width band look. Also enable pointer-events,
user-select, and overflow-y: auto so frames are scrollable and
copy-able.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:44:11 +01:00
sjg 350087855f [fix](trx-frontend-http): gate APRS bar to PKT mode, reject CRC failures
- Hide bar whenever mode != PKT; app.js calls window.updateAprsBar()
  on every server-pushed mode change so the bar disappears immediately
- CRC-failed frames are excluded from the bar (both live and history
  restore); the [CRC] rendering path is removed
- Offset bar 1.2 rem from left edge for visual breathing room

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:41:39 +01:00
sjg cbefdc15c4 [docs](trx-frontend): rename audio control labels
Update the web audio control labels in the markup and initialize the
same labels from JavaScript for consistency.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:41:13 +01:00
sjg aa367239de [fix](trx-rs): update PKT and AM default bandwidths
PKT: default 25 kHz, max 50 kHz (was 3 kHz / 25 kHz).
AM:  default 9 kHz,  max 20 kHz (was 6 kHz / 15 kHz).

Applied consistently across the UI mode-defaults table
(trx-frontend-http), server initial-mode logic (trx-server), and the
SoapySDR DSP channel (trx-backend-soapysdr).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:37:28 +01:00
sjg 62c5889619 [feat](trx-frontend-http): add APRS bar overlay on overview strip
Show the last 5 received APRS frames as a compact overlay in the
bottom-left corner of the waterfall strip, styled similarly to the
RDS PS overlay (backdrop blur, pill border). Frames fade out by
recency via CSS sibling-selector opacity steps. Bar auto-hides when
empty and is cleared by the APRS clear button. Restored from
localStorage on page load.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:37:17 +01:00
sjg fce024b090 [style](trx-frontend): improve mobile web layout
Refine the mobile layout for the web frontend, add a sticky bottom tab bar,
and style the GitHub footer link as a badge.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:32:36 +01:00
sjg 99ff619b9a [docs](trx-rs): add architecture and code design overview
Adds OVERVIEW.md with a comprehensive description of the project
architecture, crate layout, key types, data flow diagrams, DSP
pipeline, plugin system, and configuration reference.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 14:25:17 +01:00
sjg 56d6d12d9e [refactor](trx-backend-soapysdr): extract spectrum snapshot helper
Move the spectrum FFT snapshot logic into a dedicated dsp module so dsp.rs stays focused on pipeline orchestration.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 13:58:30 +01:00
sjg 08b8c80cc3 [refactor](workspace): split soapysdr demod and dsp modules
Split the SoapySDR backend demod and dsp code into focused modules while keeping behavior stable, and include the resulting formatting updates.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 13:55:48 +01:00
sjg 441cdd3adb [style](trx-frontend): use select element for WFM denoise control
Replace the checkbox with an On/Off select dropdown to match the
styling of the other WFM controls (Deemp, Audio) in the controls row.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 13:41:13 +01:00
sjg 64bb9a0d42 [feat](trx-rs): expose WFM stereo denoise toggle in UI
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>
2026-03-01 13:29:02 +01:00
sjg 46bc96ddf2 [fix](workspace): resolve clippy warnings
Clean up the workspace so cargo clippy passes across all targets and features.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 13:22:44 +01:00
sjg 523f3992f5 [feat](trx-backend-soapysdr): add WFM stereo denoise processor
Add frequency-selective attenuation of the L-R difference signal to
reduce stereo hiss on weak FM broadcasts. Uses the quadrature component
(diff_q) as a noise reference per US7292694B2 (Wildhagen/Sony).

The algorithm splits sum, diff_i, and diff_q into 6 overlapping subbands,
estimates per-band SNR from smoothed |diff_q|² noise power, and applies
an energy-weighted broadband gain to the original diff signal. This
preserves clean stereo content (<4 dB loss) while attenuating noise-only
diff channels (>6 dB reduction).

Enabled by default; toggled via set_denoise_enabled() / set_wfm_denoise().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 13:17:30 +01:00
sjg cb5467ba34 [fix](trx-backend-soapysdr): retune wfm stereo gain
Increase the stereo matrix gain to 1.2 and trim the WFM output gain slightly to rebalance the decoded audio path.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 11:28:30 +01:00
sjg d133b9082b [fix](trx-frontend): disable marker overlay for non-sdr
Collapse the shared signal marker overlay when no spectrum data is available so the non-SDR signal graph renders cleanly.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-01 11:22:24 +01:00