feat: New buttons for Icom Scope

This commit is contained in:
2026-07-07 16:50:26 +02:00
parent 05fbb8a3bc
commit 1cadefd207
8 changed files with 107 additions and 9 deletions
+52
View File
@@ -750,6 +750,58 @@ func (b *IcomSerial) SetScopeMode(fixed bool) error {
return nil
}
// icScopeRanges maps a frequency to the IC-7610's spectrum edge-frequency range
// id (from Hamlib's ic7610 caps). SetScopeEdges needs it to address the right
// fixed-edge memory. Each range spans a chunk of the tuning range.
var icScopeRanges = []struct {
lo, hi int64
id byte
}{
{30_000, 1_600_000, 1}, {1_600_000, 2_000_000, 2}, {2_000_000, 6_000_000, 3},
{6_000_000, 8_000_000, 4}, {8_000_000, 11_000_000, 5}, {11_000_000, 15_000_000, 6},
{15_000_000, 20_000_000, 7}, {20_000_000, 22_000_000, 8}, {22_000_000, 26_000_000, 9},
{26_000_000, 30_000_000, 10}, {30_000_000, 45_000_000, 11}, {45_000_000, 60_000_000, 12},
}
// scopeRangeBCD returns the range id (as a 1-byte BCD) for a frequency, or 0 if
// out of range.
func scopeRangeBCD(freq int64) byte {
for _, r := range icScopeRanges {
if freq >= r.lo && freq < r.hi {
return byte(r.id/10)<<4 | byte(r.id%10) // 1-byte BCD (11 → 0x11)
}
}
return 0
}
// SetScopeEdges points the FIXED-mode scope at [low..high] by writing them into
// the rig's fixed-edge memory (edge set 1) and making that set active. This is
// how the panel's "centre on VFO" and pan ◀/▶ work: they just compute VFO±50 kHz
// (and shift it) and set the edges — no dependence on the waveform decode. CI-V:
// 0x27 0x14 fixed, 0x27 0x16 set 1 active, 0x27 0x1e [range][set][low][high].
func (b *IcomSerial) SetScopeEdges(low, high int64) error {
if low <= 0 || high <= low {
return fmt.Errorf("icom scope: bad edges %d..%d", low, high)
}
rangeID := scopeRangeBCD((low + high) / 2)
if rangeID == 0 {
return fmt.Errorf("icom scope: freq out of range")
}
if b.dualScope {
_ = b.exec(civ.CmdScope, civ.SubScopeMode, 0x00, 0x01) // fixed mode (main)
_ = b.exec(civ.CmdScope, civ.SubScopeEdge, 0x00, 0x01) // activate edge set 1
} else {
_ = b.exec(civ.CmdScope, civ.SubScopeMode, 0x01)
_ = b.exec(civ.CmdScope, civ.SubScopeEdge, 0x01)
}
payload := append([]byte{civ.CmdScope, civ.SubScopeFixEdge, rangeID, 0x01}, civ.FreqToBCD(low)...)
payload = append(payload, civ.FreqToBCD(high)...)
b.scopeMu.Lock()
b.scopeFixed = true
b.scopeMu.Unlock()
return b.exec(payload...)
}
// SetRIT sets the RIT/ΔTX offset (signed Hz, ±9999).
func (b *IcomSerial) SetRIT(hz int) error {
if err := b.exec(append([]byte{civ.CmdRIT, civ.SubRITFreq}, civ.RITToBCD(hz)...)...); err != nil {