Mercury client: bandwidth toggle and Send CQ Frame - #183
Conversation
|
Both builds clean ( Three issues in the CQ gating, one of which I think matters on air. 1.
|
|
Correction to my finding #1 above: we're staying with VARA semantics, so scrap the The good news is the fix is smaller than either option I gave, and needs no engine change at all. The unambiguous signal already exists and is already VARA-shaped: // data_interfaces/tcp_interfaces.c:1297,1307
(void)tnc_queue_line_critical("PTT ON\r");
(void)tnc_queue_line_critical("PTT OFF\r");Note
That is precisely the failure this gating is meant to prevent, and the engine already guarantees delivery of the signal for it. Ordering is exactly what we need. // modem/modem.c:1288-1305
if (is_cq_frame) arq_notify_cq_tx_started(); // -> PENDING
int rc = send_modulated_data(...); // PTT ON ... frame ... PTT OFF
if (is_cq_frame) arq_notify_cq_tx_complete(); // -> CANCELPENDINGso a CQ produces What's needed: Worth considering the slightly larger version: a (Incidentally, the Findings #2 (unguarded |
CANCELPENDING is emitted both when an incoming connect is cancelled and when our own CQ transmission finishes, so it cannot reliably tell the client that a CQ is off the air. A stray CANCELPENDING from a peer's abandoned connect could re-enable Broadcast and ARQ Connect while the CQ is still keyed. The unambiguous, VARA-shaped signal already exists: PTT ON / PTT OFF. A CQ produces PENDING -> PTT ON -> PTT OFF -> CANCELPENDING, and the incoming-connect path never keys the radio, so PTT OFF is the true end of transmission. Parse PTT ON / PTT OFF in the modem client and clear the CQ busy state on PTT OFF instead of CANCELPENDING.
setCQBusy(false) re-enabled ARQ Connect unconditionally, so if an ARQ session came up while a CQ frame was on the air (setARQ(true) disables arqConnect), the subsequent completion would re-enable Connect mid-session. Apply the same IsConnected/IsARQConnected guard already used for Broadcast.
cqSending was written on the UI goroutine (onSendCQ/onConnect/onDisconnect) and read and written directly from the forwardStatus goroutine, a plain data race. Let setCQBusy own the flag: it now sets and clears cqSending inside its fyne.Do closure (which marshals onto the UI thread) and only clears it when one is actually in flight. forwardStatus now just calls setCQBusy(false) on PTT OFF instead of testing and assigning the flag directly, and onSendCQ uses a synchronous sendCQ.Disable() as the double-tap guard rather than mutating the flag outside the closure.
ecafc06 to
0bbb58c
Compare
|
Re-checked at 0bbb58c. All three findings are properly fixed, and the rebase onto #1 PTT gating (9dc6912) — #2 ARQ Connect guard (a0cf81b) — #3 the race (0bbb58c) — better than what I suggested. Two things the fix surfaces that weren't visible before. Both are about the same gap, and neither is a regression from your changes — the CQ button is simply new surface.
|
setARQ() disabled ARQ Connect and Broadcast for the duration of a session but left Send CQ Frame clickable, so a CQ could be put on the air in the middle of a session, on top of it. The engine does not stop us: ARQ_CMD_SEND_CQ (datalink_arq/arq.c:517) builds the frame and hands it to cb_send_tx_frame with no conn_state guard at all, and onSendCQ only tests IsConnected() -- the modem/TCP link -- plus cqSending. Neither reflects an active session. So the block belongs in setARQ, next to the two it already does. setCQBusy(false) needs the same session test for the same reason: a session can come up while our own CQ is still on the air, and its unconditional sendCQ.Enable() on PTT OFF would have undone the block a moment after setARQ applied it. State paths checked for stuck buttons: a CQ still in flight when a session starts or ends leaves sendCQ disabled until the PTT OFF that clears cqSending, which then re-enables it under the session test; setTCP(false) and onDisconnect both reset the flag. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
@pedromessetti I've pushed the What I changed, so nothing is a surprise:
I walked the state paths looking for a button that could get stuck off:
Your three fixes are all good — and the Still open, and deliberately not in this PR: Thanks for the fast turnarounds on all three rounds. |
|
@pedromessetti — one ask before this lands: please re-review ca6d307. I pushed it directly to your branch, so it's the one commit here that hasn't had a second pair of eyes. Reviewing your own PR after someone else has written into it is easy to skip, and that's exactly the commit where a mistake would be least likely to get caught. Two specific things worth your judgement rather than just a glance:
If it looks right to you, merge away — CI is still running as I write this, so just let it go green first. |
|
Reviewed ca6d307. Both calls are correct — agree with the implementation as-is. On the guard: I can't find a path where a CQ finishes and should return while the session test fails. On blocking CQ mid-session: yes, that's the behaviour I want. The button sends a single solicitation frame, not a beacon, so it only makes sense while idle; transmitting on top of a live session is the key-over-our-own-tail class we've been eliminating, and since Verified |
Summary
Adds two features to the Mercury Client (chat) window and its client library:
500 Hz/2300 Hzselector (default2300 Hz) that sendsBW500/BW2300to the engine. Replaces the previous hard-codedBW2750sent on connect.CQFRAME <callsign> <bw>via the control port using the local callsign and current bandwidth. While a CQ frame is transmitting, broadcast and ARQ connect are disabled; they re-enable on the engine'sCANCELPENDING.Changes
gui_interface/mercury-client/client/client.goConfig.BandwidthHz(default 2300), sendBW<BandwidthHz>on connect.Client.SetBandwidth()andClient.SendCQFrame().gui_interface/mercury-client/modem/modem.goModemClient.SendCQFrame(src, bwHz).gui_interface/fyne-ui/mercury_chat_window.goSend CQ Framebutton, and CQ-in-progress gating of broadcast/ARQ connect.Test plan
go build ./...ingui_interface/mercury-clientandgui_interface/fyne-ui.