Skip to content

UI themes (10 new) plus a USB sound-card radio backend - #423

Open
madmedicnl wants to merge 14 commits into
dividebysandwich:mainfrom
madmedicnl:main
Open

UI themes (10 new) plus a USB sound-card radio backend#423
madmedicnl wants to merge 14 commits into
dividebysandwich:mainfrom
madmedicnl:main

Conversation

@madmedicnl

Copy link
Copy Markdown

What

Two features on top of d96f39d0:

1. Ten new UI themes

Ten colour themes added to the existing seven, all in the repo's c(0xRRGGBB) palette style:

  • Dark: Nord, Nord dark, Gruvbox, Everforest, Solarized dark, Dracula, Catppuccin mocha
  • Light: Solarized, Catppuccin latte, Modern minimalist (light & restrained, near-monochrome with one blue accent)

Each theme's instrument palettes (S-meter, scope, map) are derived from its hues via new const builders (meter_from, meter_paper, scope_light_from, map_light_from + chan/blend helpers) rather than a second hand-written table, so instruments stay in the theme's own colour family. Default stays at index 0 (boot-up default) and themes are serde-stable (appended last).

Readability is enforced by tests. Three new tests sweep every palette:

  • body text / text_strong ≥ 4.5:1 on every panel
  • every light theme: all ink roles, decode-row tints, chip ink ≥ 4.5:1
  • light-theme instruments: printed meter, dark glass, bright atlas map with ≥ 7:1 station dots

Where a scheme's canonical red was too muted to read as "alert" (Nord, Everforest, Catppuccin mocha), the alert role uses a hotter red of the same family.

Files: crates/sdroxide-types/src/ui.rs, crates/sdroxide-ui/src/theme.rs

2. USB sound-card radio backend

A new interface, "USB audio radio (sound card)", for rigs with no control port — handhelds, walkies, USB dongle rigs.

  • UsbAudioSource (src/usb_audio_source.rs) implementing IqSource:
    • RX: mono 48 kHz demod audio from a chosen sound card (radio headphone socket → PC)
    • TX: real audio to another card (PC → radio mic socket); the rig keys itself via VOX — no PTT to command (center_is_dial() == false, CW on TX as keyed audio/MCW, TX backpressure + drain for VOX tails, drop-frame accounting)
  • Backend::UsbAudio added to sdroxide-types (serde-safe, appended last), wired into open_configured_source with usb_audio_caps(), and exposed in Settings → Radio via settings_usb_audio_tab (receive/transmit device combos + "Apply / reconnect").
  • Reuses the existing radio_audio_in/radio_audio_out config fields and the same sdroxide_audio/sdroxide_dsp machinery as the CAT backend.

Files: src/usb_audio_source.rs (new), src/main.rs, crates/sdroxide-types/src/radio.rs, crates/sdroxide-ui/src/app/settings/mod.rs, crates/sdroxide-ui/src/app/settings/radio.rs

Verification

  • cargo build (full binary, incl. RADE/rtl_433 submodules)
  • Tests: sdroxide-types (427), sdroxide-config (42), sdroxide-ui (576) — all pass, including the new contrast-sweep and picker-completeness tests
  • cargo build -p sdroxide-web passes
  • cargo fmt --check clean; no clippy warnings in touched files

Note: building the full binary requires initializing the vendor/rade_c (etc.) git submodules first — pre-existing requirement.

madmedicnl and others added 14 commits September 11, 2026 13:49
…d, Solarized dark, Dracula, Catppuccin mocha, Catppuccin latte, Modern minimalist

New dark themes get hand-tuned fabrics; the three bright-ground themes
(Solarized, latte, modern minimal) keep a 4.5:1 WCAG promise on every ink,
tint and chip on their own panels. Every theme's instruments are derived
from its hues rather than a second hand-written table: paper meters on
bright grounds, dark-glass scopes, and atlas-shaded maps via const-blended
builders that stay in the theme's own family.

The generalized sweep tests now assert body and instrument contrast for all
light palettes, and every palette keeps its alert a real red.
…gles)

A radio with no control port: demod audio arrives from one sound card,
real TX audio leaves into another, and the rig keys itself off VOX. The
operator picks the two card names in Settings → Radio, the dial becomes
a label rather than a command, and the whole audio half of AudioCat minus
the serial lives here.

Signed-off-by: druid <druid@localhost>
…olerant of their free-text reports (fixes dividebysandwich#396)

The FT8/FT4 engine can now complete a contact on the citizens' band between two
CB stations like 26AT715 and 25TT304, the way WSJT-CB works them:

- mfsk-core is taken from the madmedicnl fork (cb-support, ebd8a88): crates.io
  rejects N{1,3}L{1,2}N{1,4} calls in is_valid_callsign/is_plausible_callsign,
  and that gate silently drops every CB message before it reaches the app.
- Opening, report, R+report, RR73 and 73 pack as the everyday layout with BOTH
  calls hashed (neither fits a 28-bit field), including the empty payload of
  the grid-less opener and the bare sign-offs.
- On RX, WSJT-CB's one-call free-text messages addressed to us ("25TT304 -07",
  "25TT304 RR73") are attributed to the contact in hand and advance it.
- The Maidenhead grid is dropped from TX on 11 m, and the controller switches
  the CB mode on when the dial is in Band::M11.
…ll answer to a CQ (fixes dividebysandwich#396)

Reading WSJT-CB's on-air behaviour rather than its hashed-pair theory: for two
long CB calls it transmits a bare identity call, then one-call messages
(HISCALL +/-NN, HISCALL R+/-NN, HISCALL RR73, HISCALL 73), and calls the
two-call hash pattern unreliable.

- TX on 11 m now follows that sequence: opener is a bare MYCALL, reports and
  sign-offs name the DX alone. All fit the thirteen characters of free text,
  and a new ladder rung packs them that way before the type-4 layout can read
  "73" or "RR73" as a callsign and hash it (they happen to pass WSJT-X's
  shape rules); genuine pairs still take the two-hash ladder.
- RX adopts a station whose answer opens with its bare call, WSJT-CB's
  identity message: free text carries no addressing, so with our CQ
  unanswered an unattributed single CB call is read as the answer and the
  exchange opens. A call is the only thing that is not a status word.
- The two-hash type-1 packer stays for addressed pairs, which still arrive
  on the air from other software.
The message that answers a CQ is WSJT-CB's tx1 verbatim: the DX travels
as an explicit 12-bit hash and our call is spelled out in the clear in
the 58-bit base-38 field (iflip=0, hash first). That is what WSJT-CB
itself transmits, so the DX learns who answered even without holding our
call. The both-hashes pair stays the addressed form: it is what every
other 11m exchange uses once the contact is under way.

Verified bit-identical against the fork's pack77 for <26AT715> 25TT304.
- Add 27.700 MHz (freeband, primary SSTV) to the CB11_DIALS table so
  it appears in the SSTV frequency picker.
- Widen M11 band edges from 26.965-27.405 to 26.965-27.860 so the
  freeband SSTV area and the UK second block are inside the band
  rather than general coverage.
- Update the ADIF gap threshold from 27.5 to 28.0 to match.
- When a decode carries no grid square, fall back to resolve_place()
  to place the far end at its country centre.  This is what makes the
  propagation map work on 11m, where WSJT-CB messages carry no
  locator: the CB country list now feeds the map at the same
  precision as the Reverse Beacon Network.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant