Align the CW tone picker to the actual tone window and stop live CW decode events from overriding manual tone selection.
Co-authored-by: Stan Grams <sjg@haxx.space>
Signed-off-by: Stan Grams <sjg@haxx.space>
Send boolean values for the CW auto toggle query and improve the CW tone picker waterfall contrast.
Co-authored-by: Stan Grams <sjg@haxx.space>
Signed-off-by: Stan Grams <sjg@haxx.space>
Add a mini waterfall-based CW tone selector in the plugin tab and make CW auto mode apply only to WPM.
Co-authored-by: Stan Grams <sjg@haxx.space>
Signed-off-by: Stan Grams <sjg@haxx.space>
Publish decoded VDES positions into the map and revert the VDES burst detector to its original gating thresholds.
Co-authored-by: Stan Grams <sjg@haxx.space>
Signed-off-by: Stan Grams <sjg@haxx.space>
Add an FT8 live overlay bar, align APRS top controls with the other decoder tabs, advertise MARINE in the SoapySDR mode list, and make the VDES decoder emit raw unsynced diagnostic frames instead of dropping weak bursts outright.
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
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 first VDES payload parser on top of the decoded bitstream so the server surfaces message labels, source and destination IDs, session IDs, ASM IDs, ack fields, geographic hints, and payload previews. Update the VDES frontend pane to render those parsed fields in the history and live bar.
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Improve the VDES decoder with sync/rotation metadata and a first hard-decision rate-1/2 Viterbi stage after deinterleaving, then surface the extra lock state in the VDES frontend. Also fix the strict clippy findings in AIS, frontend bookmarks, and the server audio stack signature.
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Add a dedicated VDES plugin tab and live bar, stop reusing the AIS vessel UI, and serve a separate VDES frontend script. Rework the SDR backend so VDES receives a single 100 kHz IQ tap, then replace the fake AIS-clone decoder path with an early M.2092-1 oriented complex-baseband scaffold using burst detection, coarse pi/4-QPSK slicing, and TER-MCS-1.100 frame heuristics.
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>
Replace the APRS plugin log with a richer history view that adds summaries, filtering, pause/resume, duplicate collapsing, structured rows, row actions, and expandable details.
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Improve the AIS decoder timing recovery, add AIS vessel linking and map trails, and make the AIS/APRS decoder panels behave like mode-bound views with full-height history panes.
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Refine the AIS plugin tab with summary cards, clearer vessel rows, and better live-bar deduping, and let long side bookmark names wrap cleanly inside their chips.
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>
- Move bookmark frequency markers from drawSpectrum() to drawSignalOverlay()
so dashed lines span both the waterfall and waveform canvases
- Assign distinct palette colors to named categories; uncategorised uses
--accent-yellow resolved from the live theme at runtime
- Compute WCAG-compliant foreground color (dark/light) per category so label
text is always legible against the solid background
- Add text search input to the Bookmarks toolbar; filters by name, category,
and comment client-side without re-fetching from the server
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
let-declared bmList is not a window property, so window.bmList in
app.js always returned undefined. Change to var so it lands on window;
read it via typeof guard in app.js to stay safe if bookmarks.js is absent.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Draw bookmark frequency markers on the spectrum canvas: amber vertical
line + ribbon shape (rectangle with V-notch) at each bookmark in view.
Below the freq axis, show a #spectrum-bookmark-axis row of clickable
amber ribbon labels (clip-path bookmark shape); clicking tunes the rig.
Labels auto-appear / collapse as bookmarks scroll in and out of view.
Server: reject POST/PUT with 409 Conflict when another bookmark already
exists at the requested freq_hz (BookmarkStore::freq_taken helper).
Client: bmFetch() triggers a spectrum redraw so markers appear
immediately on load without requiring a tab visit first.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Replace the free-text decoder input with FT8/WSPR checkboxes so users
cannot enter arbitrary decoder strings. Hide the "+ Add Bookmark" button
by default and show it only when the authenticated role is `control`
(or auth is disabled), matching the server-side write-endpoint guard.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Add a "Bookmarks" tab between Main and Plugins in the tab bar.
HTML: tab panel with toolbar (category filter + Add Bookmark button),
an inline add/edit form (hidden by default, prefills freq/mode/BW from
the current rig state), and a sortable table showing all columns with
Tune / Edit / Del action buttons.
CSS: responsive bm-* classes following existing card/button theming,
works in both dark and light modes and all palette variants.
bookmarks.js: fetches bookmarks on tab activation, renders table with
event delegation, handles create/update/delete via REST, and applies a
bookmark by calling set_freq → set_mode → set_bandwidth, plus toggles
FT8/WSPR decoders when the stored mode is DIG.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Limit the APRS live bar to the last 15 minutes and show that
window in the overlay header.
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
Attach replay timestamps to APRS history and filter the APRS live bar
so it only shows the last hour of valid entries.
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
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>
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>
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>
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>
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>
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>
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>
- 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>
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>
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>
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>
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>
- 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>
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>
Refine map plotting and filter UX in HTTP frontend plugins.\n\n- support plotting multiple locator squares from FT8/WSPR messages\n- show locator lists in popup content as newline-separated entries\n- add WSPR map layer filter toggle and marker typing\n- style filter controls for strong dark/light mode contrast\n- keep themed behavior aligned with map and control updates\n\nCo-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Implement UI refinements for the HTTP frontend main and plugin views.\n\n- add dimmed header signal graph with live rendering and scale\n- make graph responsive, colorized by signal strength, and keep last 10s only\n- add APRS and WSPR text filtering, matching FT8 behavior\n- refine responsive layout for controls/map/header behavior\n- tune jog wheel/button sizing and mode selector height alignment\n\nCo-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Wire the WSPR period label to a live 120-second slot countdown so
it no longer stays at the placeholder value.
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Reorder Plugins subtabs to align with the Overview plugin listing
(APRS, CW, FT8, WSPR), with Map moved to the end.
Also add a live FT8 period countdown indicator in the FT8 panel.
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
Expose a WSPR subtab in the Plugins view with its own controls and
message list, wire a dedicated wspr.js asset endpoint, and route WSPR
decode events to the new panel.
This makes WSPR visible in the HTTP frontend instead of reusing the
FT8 panel for WSPR messages.
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>