fix: read the rig's answer to KY — it was killing the CAT link, silently

The log timed it exactly: the CW send at 13:16:17.591, the CAT dropping at
13:16:17.633, forty milliseconds later.

An accepted KY says nothing, but a REJECTED one answers "?;" — and nobody was
reading it. The frame sat in the buffer until the poll loop's next query picked
it up, failed, and the Manager tore the link down. That is the disconnect on
every macro click, and it also explains the silence: the backend was being
rebuilt underneath the send.

Two changes. The KY write is now followed by a short read: silence means
accepted, "?;" means refused — and the operator is told so, naming MENU → CW →
PC KEYING, instead of getting nothing with no reason. And FA; retries once when
it meets a stray rejection, because a "?;" arriving there is almost never about
FA: the rig answers frequency queries perfectly well, it is the previous
command's refusal being attributed to this one.

This does not yet prove the FTDX10 accepts KY at all. It makes the next run say
so plainly either way, which is the point.
This commit is contained in:
2026-07-29 13:18:52 +02:00
parent d114a73729
commit 40df4fe22f
2 changed files with 60 additions and 0 deletions
+9
View File
@@ -184,6 +184,15 @@ func (y *Yaesu) ReadState() (RigState, error) {
s := RigState{Backend: y.Name(), Connected: true, Rig: y.model}
faRaw, err := y.ask("FA;")
if errors.Is(err, errYaesuUnsupported) {
// A "?;" here is almost never about FA — the rig answers frequency queries
// perfectly well. It is a rejection left over from the PREVIOUS command
// that our read then attributed to this one. Retrying once costs a few
// milliseconds; treating it as "lost the rig" tore the CAT link down and
// reconnected it, which is what the operator saw on every CW macro.
debugLog.Printf("yaesu: FA; got a stray rejection — retrying once")
faRaw, err = y.ask("FA;")
}
if err != nil {
return RigState{}, err // the rig stopped answering — let the Manager reconnect
}