This commit is contained in:
2026-06-03 21:53:31 +02:00
parent 2b4326b553
commit 1a425a1b0d
15 changed files with 377 additions and 97 deletions
+80 -24
View File
@@ -160,42 +160,98 @@ func (o *OmniRig) ReadState() (RigState, error) {
func (o *OmniRig) SetFrequency(hz int64) error {
if o.rig == nil {
debugLog.Printf("OmniRig.SetFrequency(%d): NOT CONNECTED", hz)
return fmt.Errorf("not connected")
}
// OmniRig Freq is a Long (int32). Validate to avoid silent truncation.
if hz < 0 || hz > 0x7fffffff {
debugLog.Printf("OmniRig.SetFrequency(%d): out of int32 range", hz)
return fmt.Errorf("frequency out of OmniRig int32 range")
}
hz32 := int32(hz)
// Pick the right OmniRig property. Many rig .ini files only define a
// WRITE command for FreqA/FreqB but not the generic Freq — in which case
// PutProperty(Freq) silently succeeds but the rig never moves. Write to
// the active VFO's specific property when we know it; fall back to Freq.
prop := "FreqA"
if vfoVar, err := oleutil.GetProperty(o.rig, "Vfo"); err == nil {
switch omniRigVfo(vfoVar.Val) {
case "B", "BB", "BA":
prop = "FreqB"
case "A", "AA", "AB":
prop = "FreqA"
}
// Log the rig's writable-params, status and VFO state up front so a
// friend's session shows exactly what OmniRig reports for their rig.
status, statusStr, rigType := int64(-1), "", ""
if v, err := oleutil.GetProperty(o.rig, "Status"); err == nil {
status = v.Val
}
debugLog.Printf("OmniRig.SetFrequency(%d Hz / %.6f MHz) → %s", hz, float64(hz)/1e6, prop)
if _, err := oleutil.PutProperty(o.rig, prop, hz32); err != nil {
debugLog.Printf("OmniRig.SetFrequency(%s) error: %v — falling back to Freq", prop, err)
if _, err2 := oleutil.PutProperty(o.rig, "Freq", hz32); err2 != nil {
debugLog.Printf("OmniRig.SetFrequency(Freq) also failed: %v", err2)
return err2
}
if v, err := oleutil.GetProperty(o.rig, "StatusStr"); err == nil {
statusStr = v.ToString()
}
if v, err := oleutil.GetProperty(o.rig, "RigType"); err == nil {
rigType = v.ToString()
}
rawVfo, vfo := int64(-1), ""
if vfoVar, err := oleutil.GetProperty(o.rig, "Vfo"); err == nil {
rawVfo = vfoVar.Val
vfo = omniRigVfo(vfoVar.Val)
} else {
debugLog.Printf("OmniRig.SetFrequency: Vfo read error: %v", err)
}
split := int64(0)
if v, err := oleutil.GetProperty(o.rig, "Split"); err == nil {
split = v.Val
}
// What can this rig's .ini actually write? OmniRig exposes a WriteableParams
// bitmask — if FreqA/FreqB/Freq bits are missing, the write is a silent no-op.
writeable := int64(-1)
if v, err := oleutil.GetProperty(o.rig, "WriteableParams"); err == nil {
writeable = v.Val
}
debugLog.Printf("OmniRig.SetFrequency(%d Hz / %.6f MHz): rig=%q status=%d(%s) vfo=%q(raw=%d) split=%d writeableParams=0x%X",
hz, float64(hz)/1e6, rigType, status, statusStr, vfo, rawVfo, split, writeable)
// Pick the active VFO's specific property. Many rig .ini files only define
// a WRITE command for FreqA/FreqB but not the generic Freq.
prop := "FreqA"
switch vfo {
case "B", "BB", "BA":
prop = "FreqB"
case "A", "AA", "AB":
prop = "FreqA"
}
// Read back the active VFO freq after a short delay so the log shows
// whether the rig actually moved. Useful when the .ini accepts the write
// silently but the rig doesn't honour it (wrong WRITE command etc.).
if fv, err := oleutil.GetProperty(o.rig, "Freq"); err == nil {
debugLog.Printf("OmniRig.Freq immediately after Put = %d Hz", fv.Val)
wroteOK := false
if _, err := oleutil.PutProperty(o.rig, prop, hz32); err != nil {
debugLog.Printf("OmniRig.SetFrequency: PutProperty(%s) error: %v", prop, err)
} else {
debugLog.Printf("OmniRig.SetFrequency: PutProperty(%s, %d) OK", prop, hz32)
wroteOK = true
}
// Belt-and-suspenders: when NOT in split, also write the generic Freq.
// Icom .ini files commonly honour Freq (CI-V "set operating frequency")
// but ignore FreqA/FreqB, so the rig changed mode but never moved — this
// is exactly the IC-9100 "mode changes, freq doesn't" symptom.
if split == 0 {
if _, err := oleutil.PutProperty(o.rig, "Freq", hz32); err != nil {
debugLog.Printf("OmniRig.SetFrequency: PutProperty(Freq) error: %v", err)
if !wroteOK {
return err
}
} else {
debugLog.Printf("OmniRig.SetFrequency: PutProperty(Freq, %d) OK", hz32)
}
} else if !wroteOK {
return fmt.Errorf("OmniRig: could not write %s and split is on (won't touch generic Freq)", prop)
}
// Read back all three immediately. OmniRig is async (the CAT command is
// queued + sent over serial), so these may still show the OLD value for
// one poll cycle — but if they NEVER change in the next poll, the rig
// isn't honouring the write (wrong .ini WRITE command for this model).
fa, fb, fg := int64(-1), int64(-1), int64(-1)
if v, err := oleutil.GetProperty(o.rig, "FreqA"); err == nil {
fa = v.Val
}
if v, err := oleutil.GetProperty(o.rig, "FreqB"); err == nil {
fb = v.Val
}
if v, err := oleutil.GetProperty(o.rig, "Freq"); err == nil {
fg = v.Val
}
debugLog.Printf("OmniRig.SetFrequency: readback FreqA=%d FreqB=%d Freq=%d (target %d)", fa, fb, fg, hz)
return nil
}