revert(icom): keep 0x27 0x11 as the scope data switch, log what the retry got
Hamlib documents the spectrum scope on the IC-785x, so a rejected 0x27 0x11 is not proof the command is missing — and taking 0x27 0x10 for the data switch would have blanked that operator's own scope screen when OpsLog disabled it. Both shapes were refused within 96 ms, so neither was a timeout, and guessing the next subcommand is how the last two rounds went. The retry now logs the second attempt's own error and the failure points at the CI-V trace.
This commit is contained in:
@@ -94,9 +94,6 @@ type IcomSerial struct {
|
|||||||
// reassembled sweep; scopeMu guards it (written by the scope goroutine, read
|
// reassembled sweep; scopeMu guards it (written by the scope goroutine, read
|
||||||
// via ScopeData from the binding goroutine).
|
// via ScopeData from the binding goroutine).
|
||||||
dualScope bool
|
dualScope bool
|
||||||
// Which 0x27 subcommand switches the waveform stream on this rig: 0x11 where
|
|
||||||
// it exists, 0x10 on the ones that answer 0x11 with a rejection.
|
|
||||||
scopeOutSub byte
|
|
||||||
scopeMu sync.Mutex
|
scopeMu sync.Mutex
|
||||||
scopeAmp []byte
|
scopeAmp []byte
|
||||||
scopeLow int64 // spectrum left-edge frequency (from the sweep's header frame)
|
scopeLow int64 // spectrum left-edge frequency (from the sweep's header frame)
|
||||||
@@ -1023,7 +1020,10 @@ func (b *IcomSerial) execScope(what string, sub byte, args ...byte) error {
|
|||||||
if err == nil || !strings.Contains(err.Error(), "rejected") {
|
if err == nil || !strings.Contains(err.Error(), "rejected") {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err2 := try(!b.dualScope); err2 == nil {
|
err2 := try(!b.dualScope)
|
||||||
|
applog.Printf("icom scope: %s rejected in the %s form — the other form gave: %v",
|
||||||
|
what, map[bool]string{true: "27 xx 00 …", false: "27 xx …"}[b.dualScope], err2)
|
||||||
|
if err2 == nil {
|
||||||
b.dualScope = !b.dualScope
|
b.dualScope = !b.dualScope
|
||||||
applog.Printf("icom scope: %s rejected — this rig wants the %s form (selector=%v)",
|
applog.Printf("icom scope: %s rejected — this rig wants the %s form (selector=%v)",
|
||||||
what, map[bool]string{true: "27 xx 00 …", false: "27 xx …"}[b.dualScope], b.dualScope)
|
what, map[bool]string{true: "27 xx 00 …", false: "27 xx …"}[b.dualScope], b.dualScope)
|
||||||
@@ -1050,32 +1050,15 @@ func (b *IcomSerial) SetScope(on bool) error {
|
|||||||
// radio, and closing OpsLog (SetScope(false)) blanking a local IC-7300's
|
// radio, and closing OpsLog (SetScope(false)) blanking a local IC-7300's
|
||||||
// screen is exactly the regression this avoids. Some firmwares don't ack a
|
// screen is exactly the regression this avoids. Some firmwares don't ack a
|
||||||
// 0x27 set; a timeout isn't fatal, so log and continue.
|
// 0x27 set; a timeout isn't fatal, so log and continue.
|
||||||
if b.scopeOutSub != civ.SubScopeOnOff {
|
|
||||||
if err := b.execScope("display on", civ.SubScopeOnOff, 0x01); err != nil {
|
if err := b.execScope("display on", civ.SubScopeOnOff, 0x01); err != nil {
|
||||||
applog.Printf("icom scope: display on ack: %v", err)
|
applog.Printf("icom scope: display on ack: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Waveform data OUTPUT over CI-V: enabled with the scope, and — crucially —
|
// Waveform data OUTPUT over CI-V: enabled with the scope, and — crucially —
|
||||||
// the ONLY thing we switch off on disable, so the radio's own scope display is
|
// the ONLY thing we switch off on disable, so the radio's own scope display is
|
||||||
// left exactly as the operator had it.
|
// left exactly as the operator had it.
|
||||||
//
|
if err := b.execScope("data output", civ.SubScopeOn, boolByte(on)); err != nil {
|
||||||
// scopeOutSub is 0x11 on the radios that have it. The IC-7851 does not: it
|
applog.Printf("icom scope: output on=%v ack: %v — turn the CI-V trace on (Settings → CAT) and send the log", on, err)
|
||||||
// rejects 0x11 in both shapes, because on that radio 0x27 0x10 is itself the
|
|
||||||
// waveform-output switch rather than a display switch. Fall back to it, and
|
|
||||||
// from then on switch it off on disable too — on THAT radio doing so stops a
|
|
||||||
// data stream, not the operator's own scope screen.
|
|
||||||
if b.scopeOutSub == 0 {
|
|
||||||
b.scopeOutSub = civ.SubScopeOn
|
|
||||||
}
|
|
||||||
err := b.execScope("data output", b.scopeOutSub, boolByte(on))
|
|
||||||
if err != nil && b.scopeOutSub == civ.SubScopeOn && strings.Contains(err.Error(), "rejected") {
|
|
||||||
applog.Printf("icom scope: no 0x27 0x11 on this rig — 0x27 0x10 is its data-output switch")
|
|
||||||
b.scopeOutSub = civ.SubScopeOnOff
|
|
||||||
err = b.execScope("data output", b.scopeOutSub, boolByte(on))
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
applog.Printf("icom scope: output on=%v ack: %v", on, err)
|
|
||||||
}
|
}
|
||||||
b.scopeMu.Lock()
|
b.scopeMu.Lock()
|
||||||
b.scopeOn = on
|
b.scopeOn = on
|
||||||
|
|||||||
Reference in New Issue
Block a user