fix: SteppIR flaky status pinned FlexRadio TX interlock — operator couldn't transmit

The motorized-antenna follow loop keyed its deadband off the antenna's reported
frequency. A SteppIR reports an intermittent/stale status frequency (flips
between the commanded freq and its home/6 m value), so the deadband tripped on
almost every 1.5 s poll and re-issued a tune command. Each command refreshed
noteMotorMoveCommanded(), keeping motorTXInhibitLoop's recentCmd window alive, so
the Flex transmit-inhibit ("Interlock is preventing transmission") never
released — confirmed in a real log (moving=0 throughout, recentCmd was the
driver).

Follow loop now keys the deadband off the LAST COMMANDED rig frequency, only
re-tuning when the radio actually QSYs beyond the step — immune to a flaky
antenna status. Falls back to the antenna's freq only until the first command.

Also dropped SetTXInhibit's `interlock set reason=` sends: `reason` is a
read-only field on the Flex interlock object, so writing it is rejected
(cmd error 5000002D on V1.4.0.0) and did nothing; `transmit set inhibit=` is the
real mechanism and is unchanged.
This commit is contained in:
2026-07-24 15:53:40 +02:00
parent 76e4288b9e
commit b83d55cc32
3 changed files with 21 additions and 13 deletions
+15 -5
View File
@@ -12454,6 +12454,7 @@ func (a *App) ultrabeamFollowLoop(c motorAntenna, stepKHz int, stop <-chan struc
ticker := time.NewTicker(1500 * time.Millisecond)
defer ticker.Stop()
lastRigKHz := 0 // only log when the followed rig frequency actually changes
lastCmdKHz := 0 // rig freq we last issued a move for — the deadband reference
for {
select {
case <-stop:
@@ -12487,12 +12488,20 @@ func (a *App) ultrabeamFollowLoop(c motorAntenna, stepKHz int, stop <-chan struc
continue
}
}
// Deadband reference = the antenna's reported freq, or (when it hasn't
// reported one yet) the last freq we commanded — so a 0/blank status
// doesn't bypass the deadband and re-tune on every small QSY.
ref := st.Frequency
// Deadband reference = the rig freq we LAST commanded a move for, not the
// antenna's reported freq. A SteppIR reports a flaky/stale status
// frequency (it flips between the commanded freq and its home/6 m value),
// which would trip the deadband and re-issue a SET on almost every poll —
// and each SET refreshes the "recently commanded" window that inhibits TX,
// leaving the operator permanently unable to transmit. Following the rig
// (only re-tune when the RIG actually QSYs beyond the step) is immune to
// that. Falls back to the antenna's own freq only until we've commanded once.
ref := lastCmdKHz
if ref <= 0 {
ref = c.LastSetKHz()
ref = st.Frequency
if ref <= 0 {
ref = c.LastSetKHz()
}
}
diff := rigKHz - ref
if diff < 0 {
@@ -12505,6 +12514,7 @@ func (a *App) ultrabeamFollowLoop(c motorAntenna, stepKHz int, stop <-chan struc
if err := c.SetFrequency(rigKHz, st.Direction); err != nil {
applog.Printf("ultrabeam: follow re-tune to %d kHz failed: %v", rigKHz, err)
} else {
lastCmdKHz = rigKHz
applog.Printf("ultrabeam: followed rig → %d kHz (dir %d, was ref %d kHz, step %d)", rigKHz, st.Direction, ref, stepKHz)
}
}