Commit Graph
1258 Commits
Author SHA1 Message Date
rouggy da8f60a7b3 fix(icom): the SUB dial is always shown, and split aligns the TX mode
The unselected VFO was read only when split was on, so a dual-receiver rig's
second dial sat blank on the console. It is now read on the same slow beat
regardless. And engaging split copies the main's mode (and data flag) onto
the TX VFO with 0x26 01 — a split whose TX VFO still speaks yesterday's mode
transmits FM into a CW pileup; rigs that predate 0x26 NAK it harmlessly.
2026-08-29 21:53:16 +02:00
rouggy e8b5444fc2 feat(icom): live microphone over the network — the last remote brick
The talk button learns the network road the voice keyer already took: when
To-radio is the radio itself, the microphone is captured and re-framed into
the rig's 320-sample packets, the capture callback serving as the clock — the
mic delivers in real time, so no ring and no pacer. Counters and the frame
remainder live on the audio stream, so a talk session spans calls. PTT keys
before and releases after, through the same code as the USB path.

With this, a network Icom is a complete remote station over three UDP ports:
RX audio to the headset, live voice and recorded messages back, CW through
the rig's keyer, CAT for everything else.
2026-08-29 21:51:37 +02:00
rouggy 08bc401681 fix(audio): the network monitor needs no From-radio device
AudioStartMonitor refused before reaching the network branch when From-radio
was empty — which is the NORMAL network setup, so the new speakers checkbox
un-ticked itself the instant it was ticked. The capture-device requirement now
applies only to the USB path that actually captures.
2026-08-29 21:45:18 +02:00
rouggy 7ac342e2d4 feat(icom): the speaker choice appears beside the RX-audio option too
Same remembered preference as the console's speaker button, surfaced where
the stream itself is enabled — tick RX audio and decide in the same breath
whether it reaches the speakers. Applied immediately, no save needed.
2026-08-29 20:02:28 +02:00
rouggy b244575937 feat(icom): a speaker toggle on the console itself
Muting the network RX audio took a trip through Settings → Audio → Stop
listening — two panels away from the console the operator is actually using.
A speaker button now sits beside ON/OFF (network only, like them): one click
to listen or mute, the recorder and the voice keyer unaffected, the choice
remembered across reconnects and launches.
2026-08-29 19:49:09 +02:00
rouggy c878742e50 feat(icom): listening to the network audio is a remembered choice
The RX stream and the speakers were welded together: every reconnect and
every launch restarted the monitor, so an operator sitting in the room with
the radio could not have the stream (which the recorder and the voice keyer
need) without also hearing it twice. Stop listening now persists, the Listen
button turns it back on, and reconnects respect the choice.
2026-08-29 19:42:18 +02:00
rouggy 13434ca36c feat(icom): phase 5 — the voice keyer plays to the radio over the LAN
The audio session opens its TX side alongside RX (txenable in the conninfo,
16 kHz both ways), the stream gains a paced sender — 320 samples every 20 ms,
the frame mirroring what the rig itself sends on this socket, IDs swapped —
and the network Icom takes the same NetworkPlayer slot a TCI radio does: pick
'Radio (network audio)' as the To-radio device and the voice keyer needs no
cable and no virtual sound card. PTT brackets the message through the same
code as every other audio path.
2026-08-29 19:34:05 +02:00
rouggy 6345710de5 fix(icom): wait out the rig's session cleanup before redialling
The capture shows the spiral: a session goes deaf on CI-V (28 unanswered
commands, transport alive), the fast-fail rebuilds it, the new session answers
for one second — one state read got through — and is then strangled when the
rig purges the half-open old one. Twenty seconds a lap, no audio throughout,
and only the third or fourth session survives. When the previous session died
less than 90 s after connecting, the redial now pauses 20 s so the purge
happens BEFORE the new session, not on top of it. A long-lived session still
reconnects immediately.
2026-08-29 19:21:55 +02:00
rouggy 0cab1c1e6b debug(icom): count the questions asked during a CI-V silence
The operator's counter-hypothesis deserves an answer: RS-BA1 shows no such
dropouts, so are we sure the rig stops answering — or do we stop asking? The
quiet log now carries the number of CI-V commands sent since the last answer.
Zero would convict our own poll loop; a healthy count convicts the rig.
2026-08-29 18:43:46 +02:00
rouggy 1c71495446 fix(icom): give up on the quiet CI-V stream after 15 s, not 30
The capture settled it: the 7760 keeps the transport chatting (pings answered,
no socket error, no loss) while CI-V data simply stops, the in-place reopen is
ignored, and only a fresh session brings it back. So: one reopen attempt at
10 s — kept, it is free and the log will say if a firmware ever honours it —
and at 15 s the link is failed deliberately so the manager rebuilds it,
halving the outage. Also: the recovered-acknowledgement now sits on the DATA
packet, not on any packet — pings were toggling the detector, 160 reopens in
thirty seconds all logged as recoveries that never happened.
2026-08-29 18:35:41 +02:00
rouggy 2c0158b75c fix(icom): re-open the CI-V flow when the rig goes quiet mid-session
The IC-7760 recurrently stops answering CI-V a few minutes into a network
session while the transport keeps chatting — pings answered, session alive,
commands unanswered — and the only recovery was the 30 s watchdog's full
teardown. At 10 s of CI-V silence the pump now says 'open' again on the
existing stream, which is all it should take if the rig quietly closed the
data flow; the watchdog remains as the backstop. The send counters gain a
mutex since the pump now transmits too.
2026-08-29 16:56:06 +02:00
rouggy a2b019b280 debug(icom): the quiet detector watches CI-V DATA, not transport chatter
The first detector counted any packet and never fired: pings and idles keep
flowing while the rig stops answering CI-V commands — which is what the 7760's
recurring silence turns out to be. Now it fires on 10 s without a CI-V payload
and reports the ages of the transport, the last scope frame and the last
socket error, so the next occurrence says exactly what the rig was still
sending.
2026-08-29 16:54:37 +02:00
rouggy 1fba7d2d57 fix(icom): create the audio manager before the CAT link comes up
reloadCAT builds the network audio sink gated on audioMgr, and startup created
the manager AFTER the first reloadCAT: every fresh launch connected with audio
silently off however the option was set, and the operator had to
untick/save/retick it to hear anything. The manager is idle-until-used, so
creating it earlier costs nothing.
2026-08-29 16:47:42 +02:00
rouggy 490941f506 fix(icom): only forward-moving audio packets reach the sink
Every audio packet was delivered as if it were the next 20 ms, duplicates and
late retransmits included. The monitor's capped ring quietly threw the surplus
away, so the speakers sounded fine — but the recorder keeps every sample it is
given, and the file came out longer than the QSO, slowed and stuttering, each
lost-then-resent packet heard twice. trackRxSeq now says whether a packet
advances the stream, and only those are handed on.
2026-08-29 16:43:41 +02:00
rouggy 6bf759b6ae fix(cw): Icom CI-V CW works over the network backend too
The CI-V keyer is the same 0x17 command on the same IcomController whatever
carries the link; only the warnings and enable checks insisted on the USB
backend, telling a network operator their working keyer would fail.
2026-08-29 16:39:43 +02:00
rouggy 43e5088e96 fix(icom): the live radio names MY_RIG, and a manual take records it too
Two halves of the same station confusion. The entry form pre-filled MY_RIG
from the per-band default on every band change, so the log-time priority (the
radio that is keying beats the radio that was planned) never ran — the field
was no longer empty by the time the backend looked. The form now asks the
active radio first, through a new ActiveRadioMyRig binding.

And the manual record button started its capture from the From-radio sound
card unconditionally, where the automatic recorder already knew a network
Icom's audio is pushed from the 50003 stream: a manual take on the IC-7760
was a faithful recording of the Flex's DAX. Same source rule for both, and
the button is offered with no sound card at all when the network stream is
the source.
2026-08-29 16:35:25 +02:00
rouggy 582fa561b2 fix(rec): a fresh take starts its clock at zero, not at the last take's total
Two effects, wrong order: the ticking effect ran before the reset effect on a
new take, so its closure captured the PREVIOUS take's elapsed as its starting
point — the counter showed 0 for one second and then jumped back to thirty
minutes. Effects run in declaration order; the reset now comes first.
2026-08-29 16:31:38 +02:00
rouggy 7f328d4eb5 debug(icom): say what the CI-V stream was doing when it goes quiet
A real IC-7760 keeps going silent on the CI-V stream two-three minutes into a
session while the control link stays alive. At 10 s of silence the pump now
logs the last real socket error and the retransmit backlog, and notes when the
stream resumes — the 30 s watchdog that follows cannot tell a dead socket from
a rig that stopped talking, and the next occurrence should.
2026-08-29 16:07:42 +02:00
rouggy b2eb6a4b1e fix(icom): the 7760 power meter interpolates between MEASURED anchors
A known 50 W read raw ~89 where the two-segment curve said 62: the face is
not linear in watts below half scale. Watts now interpolate through the
measured points (50 W, 100 W, full-scale 250 W); refining the curve is adding
a row to the table.
2026-08-29 16:06:05 +02:00
rouggy c2db4c5f7e chore(icom): stop blaming a hijacker for every silent CI-V stream
The 30 s watchdog message asserted another program had taken the session; a
real IC-7760 went silent once with nothing else on the network, and the
message sent its operator hunting software that was not installed. State both
causes.
2026-08-29 16:04:06 +02:00
rouggy b246c4d10a fix(icom): power in watts on the 7760, and Listening restarts clean
The power meter applies Icom's own meter calibration (raw 143 = half
deflection, 213 = full scale) anchored against the real radio: a measured
100 W sits at half deflection of the 7760's 250 W face — the linear guess
showed it as 140. The RF power slider says watts on a 200 W rig instead of a
percentage the operator has to convert.

And the Listening button, pressed while a network Icom is connected, restarts
the monitor render-only: it used to open a USB capture from the From-radio
device as well, and that second producer interleaved with the network pushes
chopped the audio to pieces.
2026-08-29 16:02:15 +02:00
rouggy 6d4a110949 fix(cat): the settings panel opens on the radio that is actually active
The loader looked for an 'active' flag the radio list has never carried, so
reopening the panel always landed on the first entry — Radio 1's name over
whichever radio's settings were live, and every field edit (MY_RIG included)
silently rewriting the wrong entry. The backend is the only one who knows
which radio is on the air; ask it.
2026-08-29 15:52:37 +02:00
rouggy ffbbff80d6 feat(icom): a DATA button, native PSK, real watts — and the audio codec
The console gains a DATA mode button (USB-D, what FT8 and friends ride on);
the PSK button now maps to the rigs' native PSK mode (0x12) instead of erroring
as an unknown mode — rigs without one NAK it, exactly as RS-BA1's button does
there. The power meter shows real watts on the IC-7760, whose meter face runs
to 250 W where a 100 W rig's percentage was the watts. The clickable S-meter
gets a pointer cursor so it looks like what it is.

Network audio: rxcodec 0x04 — the experiments on the real 7760 settle the
codec table (0x10 = 16-bit stereo, 0x02 = 8-bit mono, both heard as garble),
and 0x04 is the 16-bit mono the playback path actually plays.
2026-08-29 15:48:26 +02:00
rouggy bd2edf6624 fix(icom): verify the data flag after a mode set, and correct it with 0x26
The IC-7760 acknowledges the 1A 06 data-mode command and stays in USB-D
anyway, which left the operator unable to get back to plain USB from the
console at all. After every mode set the flag is read back; on a mismatch it
is said again with 0x26 — mode, data flag and filter in one frame, the form
the newer rigs actually honour. Only on a mismatch, so rigs that predate 0x26
never see the command.
2026-08-29 15:36:55 +02:00
rouggy 6321948415 fix(icom): fold the 7760's stereo RX stream down to the mono it plays as
The rig keeps sending two-channel LPCM after rxcodec asks for one — 1280-byte
payloads, 320 stereo frames per 20 ms tick, right channel all zeros in the
capture. Played as mono that interleaving is half-speed metallic garble. A
stereo-sized packet is folded to its left channel; a 640-byte mono packet from
a rig that honours the request passes through untouched.
2026-08-29 15:34:18 +02:00
rouggy 89e239d83f fix(icom): decode the network RX audio as what the rig actually sends
The first real radio on the 50003 stream (an IC-7760) settles the two guesses
the experimental audio path shipped with. The payload starts at 0x18 — the
packet carries a big-endian payload length at 0x14 (0x500 on every packet) —
not at 0x16, which swallowed two header bytes into the PCM and laid a 50 Hz
click track under everything. And rxcodec 0x10 asks for TWO-channel LPCM,
which the mono playback path rendered as double-speed garble; 0x02 asks for
the one channel the monitor plays.
2026-08-29 15:32:44 +02:00
rouggy 0e48ad7bb2 fix(icom): the IC-7760's attenuator is the stepped 6/12/18 dB kind
Confirmed on a real one. It was falling into the single-20 dB default, whose
one button the rig NAKs.
2026-08-29 15:29:14 +02:00
rouggy ad82c21dbc debug(icom): log the raw packets seen during a control handshake
A rig that answers something unrecognised (a newer model, another firmware)
and a rig that answers nothing are different faults; a silent timeout hides
which. Capped at a dozen packets so a working handshake cannot flood the log.
Prompted by the first IC-7760 network attempt — which turned out to be aimed
at the console's IP, where nothing listens; the remote server lives on the RF
deck.
2026-08-29 15:12:12 +02:00
rouggy 6f126802cd feat(icom): the IC-7760 joins the model list
CI-V default address B2h, per the radio's own menu. Both places that know a
model: the settings dropdown and civ.ModelName.
2026-08-29 15:02:23 +02:00
rouggy 704b614c38 fix(elecraft): calibrate the S-meter, and stop the SWR spike lingering
The S-unit mapping was provisional, waiting for a real radio. One arrived:
side by side with a K3's own display, raw 5 reads S7 and raw 9 reads S9+20,
so S9 sits near raw 6.5 — not 9 — and each raw step above it is worth ~8 dB.
The old scale showed everything two S-units low.

The SWR meter borrowed the power meter's needle inertia — hold the peak, then
close a quarter of the gap per poll. The K3 throws a brief SWR spike as an FT8
frame ends, and that decay turned one bad sample into twelve seconds of red on
the next transmission. SWR now holds the peak for the same 1.5 s and then
snaps back to the live reading: it is a warning light, not a needle.
2026-08-29 13:52:40 +02:00
rouggy 6eb6f1b339 chore: release v0.27.0 v0.27.0 2026-08-29 02:56:48 +02:00
rouggy dbd2fff121 chore(changelog): the watchlist block becomes 0.27.0
A new tab, a new file format carried over from another program, and a ClubLog
integration are a minor version, not a patch.
2026-08-29 02:56:28 +02:00
rouggy dc6da67cbf chore(changelog): the watchlist headlines 0.26.24
The block's one genuinely new feature opens it — with the ClubLog enrichment,
which had not made it into the entry yet — instead of sitting seventh between
an Elecraft button row and a bulk-edit field.
2026-08-29 02:55:16 +02:00
rouggy ea6fb1c29c fix(flex): send the spot-click zoom after the tune, not alongside it
Double-clicking a cluster spot tuned the slice and zoomed the panadapter in
the same breath. On a cross-band jump SmartSDR moves the panadapter itself to
follow the slice, and that follow lands after — and overrides — a zoom sent in
the same instant, so the width the operator configured never appeared. A spot
clicked ON the panadapter never hit this, because the radio had already tuned
before our zoom arrived; the two paths now behave the same. The Chase new
panel's pick is sequenced identically.
2026-08-29 02:45:07 +02:00
rouggy 29267a865c fix(flex): the Chase new panel's spot click zooms the panadapter too
Every other spot click — cluster grid, band map, watchlist, alert list — goes
through handleSpotClick, which applies the operator's per-mode panadapter
width after the tune. The Chase new panel had its own pick handler that tuned
and stopped there; it now makes the same view change, after the tune for the
same reason.
2026-08-29 02:37:13 +02:00
rouggy e93d2d36a8 feat(watchlist): the ClubLog expedition enrichment — phase 2 lands
clublog.org/watch.php, per entry: the DXpedition flag, OQRS, LiveStream, the
log's QSO total and the last-24h rate — the fields the schema has carried since
phase 1. Refreshed on DXHunter's own cadence (hourly for expeditions,
six-hourly for the rest), two at a time with a breath between requests: the
application API key is shared by every install, so a hundred-entry list must
read as a trickle at ClubLog's end. Nothing to configure — OpsLog's own key,
already used for cty and Most Wanted, serves.

A starred pattern is asked about by its base (ClubLog has no log for VK9*).
The card gains the 24h rate beside the QSO total and the Live link to the
expedition's stream.
2026-08-29 01:49:13 +02:00
rouggy 107c6fccf6 fix(watchlist): remove on a single click, like the bell and trophy beside it
The two-click arm goes: removing an entry is cheap to undo (type it again), so
it does not earn a confirmation its neighbours do not have. The bin reddens on
hover and the green line confirms the removal.
2026-08-29 01:36:06 +02:00
rouggy 9350af9589 fix(watchlist): remove actually removes on the second click
The two-click arm compared against the STATE variable, which each click's
handler captured at render time — a quick double-click read the pre-arm value
twice, so both clicks merely armed: the bin turned red and nothing was ever
deleted. The arm lives in a ref now, compared synchronously, and the window
grows to three seconds.
2026-08-29 01:34:09 +02:00
rouggy a9a6579a9a feat(watchlist): confirm an add, and both messages clear themselves
A green line under the toolbar says what was added (and as what — the contest
variant names the per-UTC-day rule); the already-exists error keeps its red
line. Both fade after four seconds: a stale 'added' from ten minutes ago reads
as a fresh one.
2026-08-29 01:30:10 +02:00
rouggy 7795e13432 fix(watchlist): open the store before the logbook connect
It was created after the (possibly remote) logbook connect, so a 10-30 s MySQL
dial left the tab saying 'Watchlist: 0' until the next refresh tick — twenty
seconds of an empty list for a JSON file that reads in a millisecond. It now
opens right after the data dir is known; only the auto-contest pattern waits
for the settings store.
2026-08-29 01:28:50 +02:00
rouggy c9e98d5fdd feat(watchlist): exact match by default, * for a family
The prefix matching ported from DXHunter swallowed too much: a three-letter
special-event entry N8W lit up NEEDED for N8WCR, a different station entirely.
The implicit becomes explicit — a bare entry matches exactly that call, a
trailing star makes it a family: VK9* catches every VK9…, RI0SP* the
expedition's portable forms. A star anywhere else (or alone) is refused at Add
rather than silently matching nothing. Same rule in the backend Match and the
tab's own matcher, pinned by test.
2026-08-29 01:25:34 +02:00
rouggy 72253f99fa style(watchlist): the toolbar is two atomic groups — no more orphan chip
Add-controls left, filters right, justify-between: when the pane narrows, the
whole filter group drops below as a block instead of shedding its last chip.
Shorter chip labels (Active / Needed) and a slimmer search keep both groups on
one line at the tab's normal width.
2026-08-29 01:16:53 +02:00
rouggy f0d3bed8a2 style(stats): room for a long entity beside its badges
The F1 panel widens 560 → 600 px, the header row drops its outer padding and
wide gaps, and the country badge tightens — so 'Central African Republic' and
the NEW SLOT chip share one line instead of the chip dropping alone underneath.
2026-08-29 01:11:02 +02:00
rouggy 30c9acf0d2 style(watchlist): counters on their own centred line, sane placeholders
The counters are the tab's headline and now sit alone, centred, above the
toolbar; everything one interacts with lives on the second row. The inputs stop
shouting their placeholders — the uppercase belonged to the VALUE (callsigns),
not the hint text — and the auto-contest field says what it is.
2026-08-29 01:08:39 +02:00
rouggy e3175ef6a3 fix(watchlist): never draw a spot before its verdict
A new spot rendered as Needed the instant it arrived and was withdrawn half a
second later when the worked answer landed — the list twitched on every burst.
Unsettled spots are now invisible everywhere (card lines, counters, the
Active/Needed-only filters) until their verdict is in: nobody needs a spot
150 ms early, they need it settled. The answer map is merged rather than
replaced, so a settled line can never fall back to unknown, and the query
debounce drops to 150 ms since there is nothing on screen waiting for it.
2026-08-29 01:06:01 +02:00
rouggy 441eb295c6 feat(watchlist): header counters, mode filter — and the alert checks worked FIRST
DXHunter's header row, ported: Watchlist / Active / Needed counts up front and
the All-Modes select beside the other filters (DIGI matches the digital class,
SSB folds USB/LSB). Counters, card lists and the Active/Needed-only filters all
read the same mode-filtered view, so the numbers add up to what is on screen.

And the notify alert now asks the SAME worked-slot question the tab asks —
before making a sound. It used to fire on the raw spot while the tab's verdict
arrived on a debounce, so the bell rang for a slot that showed Worked a moment
later. Judged in the backend at emit time: exact slot for named modes, digital
class for generic DATA, today-only for contest entries.
2026-08-29 01:03:37 +02:00
rouggy cb2f8aba72 fix(watchlist): the auto-contest FIELD — the backend shipped without its UI
The wiring script died on an app.go anchor mid-run: the backend half was
committed, the frontend half (the pattern field, the changed-event refresh, the
i18n keys) never ran. Replayed; the field sits after Add.
2026-08-29 00:58:46 +02:00
rouggy 7b9cda93bc style(watchlist): drop the lone '!' on needed lines
A needed line already says so twice — the amber left border and the Needed!
badge — and the exclamation mark was noise. The green tick stays on worked
lines.
2026-08-29 00:52:38 +02:00
rouggy 8f64e3fee3 feat(watchlist): the auto-contest pattern — DXHunter's contest_prefix
A field in the tab's toolbar (e.g. WWA): while non-empty, any spotted callsign
CONTAINING it joins the watchlist as a contest entry by itself — a
special-event fleet (HB9WWA, DL0WWA, F4WWA/P…) is collected as it appears
instead of typed in one by one, and each is judged per UTC day like any contest
entry. Contains, not prefix, because the event string sits anywhere in those
calls.

Global setting, cached in an atomic so the spot pipeline never touches the
settings store per spot. Emptying the field stops the collecting but keeps what
was collected — DXHunter deletes non-matching contest entries on a pattern
change, and a setting that silently empties an operator's list is the one
behaviour of the original this port refuses.

The tab also refreshes on backend auto-adds (event) and on a slow tick, so
last-seen and the counters stay honest while it sits open.
2026-08-29 00:50:14 +02:00
rouggy c4de5f2ea0 style(watchlist): a wider column, and the country stops truncating first
max-w-4xl left 'Central African R…' cut mid-name: the column grows to 5xl and
the country cell flexes with the row (capped at 14rem) instead of a hard 8rem.
2026-08-29 00:46:34 +02:00