Add pending cmd retry handling

This commit is contained in:
Nonoo 2020-11-09 09:40:18 +01:00
parent c56ade853f
commit 01a6142232

View file

@ -8,7 +8,8 @@ import (
)
const civAddress = 0xa4
const sReadInterval = time.Second
const statusPollInterval = time.Second
const commandRetryTimeout = 500 * time.Millisecond
// Commands reference: https://www.icomeurope.com/wp-content/uploads/2020/08/IC-705_ENG_CI-V_1_20200721.pdf
@ -74,43 +75,62 @@ const (
splitModeDUPPlus
)
type civCmd struct {
pending bool
sentAt time.Time
name string
cmd []byte
}
type civControlStruct struct {
st *serialStream
deinitNeeded chan bool
deinitFinished chan bool
resetSReadTimer chan bool
st *serialStream
deinitNeeded chan bool
deinitFinished chan bool
resetSReadTimer chan bool
newPendingCmdAdded chan bool
state struct {
getFreqSent bool
getModeSent bool
getDataModeSent bool
getSSent bool
getOVFSent bool
getSWRSent bool
getTransmitStatusSent bool
getVdSent bool
mutex sync.Mutex
pendingCmds []*civCmd
getFreq civCmd
getMode civCmd
getDataMode civCmd
getPwr civCmd
getS civCmd
getOVF civCmd
getSWR civCmd
getTransmitStatus civCmd
getPreamp civCmd
getAGC civCmd
getTuneStatus civCmd
getVd civCmd
getTS civCmd
getRFGain civCmd
getSQL civCmd
getNR civCmd
getNREnabled civCmd
getSplit civCmd
lastSReceivedAt time.Time
lastOVFReceivedAt time.Time
lastSWRReceivedAt time.Time
setPwrSent bool
setRFGainSent bool
setSQLSent bool
setNRSent bool
setFreqSent bool
setModeSent bool
setPTTSent bool
setTuneSent bool
setDataModeSent bool
setPreampSent bool
setAGCSent bool
setNREnabledSent bool
setTSSent bool
setVFOSent bool
setSplitSent bool
mutex sync.Mutex
setPwr civCmd
setRFGain civCmd
setSQL civCmd
setNR civCmd
setFreq civCmd
setMode civCmd
setPTT civCmd
setTune civCmd
setDataMode civCmd
setPreamp civCmd
setAGC civCmd
setNREnabled civCmd
setTS civCmd
setVFO civCmd
setSplit civCmd
freq uint
ptt bool
@ -169,20 +189,20 @@ func (s *civControlStruct) decode(d []byte) bool {
case 0x1a:
return s.decodeDataModeAndOVF(payload)
case 0x14:
return s.decodePowerRFGainSQLNR(payload)
return s.decodePowerRFGainSQLNRPwr(payload)
case 0x1c:
return s.decodeTransmitStatus(payload)
case 0x15:
return s.decodeVdSWRS(payload)
case 0x16:
return s.decodePreampAGCNR(payload)
return s.decodePreampAGCNREnabled(payload)
}
return true
}
func (s *civControlStruct) decodeFreq(d []byte) bool {
if len(d) < 2 {
return !s.state.getFreqSent && !s.state.setFreqSent
return !s.state.getFreq.pending && !s.state.setFreq.pending
}
var f uint
@ -208,12 +228,12 @@ func (s *civControlStruct) decodeFreq(d []byte) bool {
}
}
if s.state.getFreqSent {
s.state.getFreqSent = false
if s.state.getFreq.pending {
s.removePendingCmd(&s.state.getFreq)
return false
}
if s.state.setFreqSent {
s.state.setFreqSent = false
if s.state.setFreq.pending {
s.removePendingCmd(&s.state.setFreq)
return false
}
return true
@ -230,7 +250,7 @@ func (s *civControlStruct) decodeFilterValueToFilterIdx(v byte) int {
func (s *civControlStruct) decodeMode(d []byte) bool {
if len(d) < 1 {
return !s.state.getModeSent && !s.state.setModeSent
return !s.state.getMode.pending && !s.state.setMode.pending
}
var mode string
@ -249,12 +269,12 @@ func (s *civControlStruct) decodeMode(d []byte) bool {
}
statusLog.reportMode(mode, filter)
if s.state.getModeSent {
s.state.getModeSent = false
if s.state.getMode.pending {
s.removePendingCmd(&s.state.getMode)
return false
}
if s.state.setModeSent {
s.state.setModeSent = false
if s.state.setMode.pending {
s.removePendingCmd(&s.state.setMode)
return false
}
return true
@ -262,7 +282,7 @@ func (s *civControlStruct) decodeMode(d []byte) bool {
func (s *civControlStruct) decodeVFO(d []byte) bool {
if len(d) < 1 {
return !s.state.setVFOSent
return !s.state.setVFO.pending
}
if d[0] == 1 {
@ -273,11 +293,11 @@ func (s *civControlStruct) decodeVFO(d []byte) bool {
log.Print("active vfo: A")
}
if s.state.setVFOSent {
if s.state.setVFO.pending {
// The radio does not send the VFO's frequency automatically.
_ = s.getFreq()
s.state.setVFOSent = false
s.removePendingCmd(&s.state.setVFO)
return false
}
return true
@ -285,7 +305,7 @@ func (s *civControlStruct) decodeVFO(d []byte) bool {
func (s *civControlStruct) decodeSplit(d []byte) bool {
if len(d) < 1 {
return !s.state.setSplitSent
return !s.state.getSplit.pending && !s.state.setSplit.pending
}
var str string
@ -304,8 +324,12 @@ func (s *civControlStruct) decodeSplit(d []byte) bool {
}
statusLog.reportSplit(str)
if s.state.setSplitSent {
s.state.setSplitSent = false
if s.state.getSplit.pending {
s.removePendingCmd(&s.state.getSplit)
return false
}
if s.state.setSplit.pending {
s.removePendingCmd(&s.state.setSplit)
return false
}
return true
@ -313,7 +337,7 @@ func (s *civControlStruct) decodeSplit(d []byte) bool {
func (s *civControlStruct) decodeTS(d []byte) bool {
if len(d) < 1 {
return !s.state.setTSSent
return !s.state.getTS.pending && !s.state.setTS.pending
}
s.state.tsValue = d[0]
@ -350,8 +374,12 @@ func (s *civControlStruct) decodeTS(d []byte) bool {
}
statusLog.reportTS(s.state.ts)
if s.state.setTSSent {
s.state.setTSSent = false
if s.state.getTS.pending {
s.removePendingCmd(&s.state.getTS)
return false
}
if s.state.setTS.pending {
s.removePendingCmd(&s.state.setTS)
return false
}
return true
@ -361,7 +389,7 @@ func (s *civControlStruct) decodeDataModeAndOVF(d []byte) bool {
switch d[0] {
case 0x06:
if len(d) < 3 {
return !s.state.getDataModeSent && !s.state.setDataModeSent
return !s.state.getDataMode.pending && !s.state.setDataMode.pending
}
var dataMode string
var filter string
@ -376,17 +404,17 @@ func (s *civControlStruct) decodeDataModeAndOVF(d []byte) bool {
statusLog.reportDataMode(dataMode, filter)
if s.state.getDataModeSent {
s.state.getDataModeSent = false
if s.state.getDataMode.pending {
s.removePendingCmd(&s.state.getDataMode)
return false
}
if s.state.setDataModeSent {
s.state.setDataModeSent = false
if s.state.setDataMode.pending {
s.removePendingCmd(&s.state.setDataMode)
return false
}
case 0x09:
if len(d) < 2 {
return !s.state.getOVFSent
return !s.state.getOVF.pending
}
if d[1] != 0 {
statusLog.reportOVF(true)
@ -394,58 +422,74 @@ func (s *civControlStruct) decodeDataModeAndOVF(d []byte) bool {
statusLog.reportOVF(false)
}
s.state.lastOVFReceivedAt = time.Now()
if s.state.getOVFSent {
s.state.getOVFSent = false
if s.state.getOVF.pending {
s.removePendingCmd(&s.state.getOVF)
return false
}
}
return true
}
func (s *civControlStruct) decodePowerRFGainSQLNR(d []byte) bool {
func (s *civControlStruct) decodePowerRFGainSQLNRPwr(d []byte) bool {
switch d[0] {
case 0x02:
if len(d) < 3 {
return !s.state.setRFGainSent
return !s.state.getRFGain.pending && !s.state.setRFGain.pending
}
hex := uint16(d[1])<<8 | uint16(d[2])
s.state.rfGainPercent = int(math.Round((float64(hex) / 0x0255) * 100))
statusLog.reportRFGain(s.state.rfGainPercent)
if s.state.setRFGainSent {
s.state.setRFGainSent = false
if s.state.getRFGain.pending {
s.removePendingCmd(&s.state.getRFGain)
return false
}
if s.state.setRFGain.pending {
s.removePendingCmd(&s.state.setRFGain)
return false
}
case 0x03:
if len(d) < 3 {
return !s.state.setSQLSent
return !s.state.getSQL.pending && !s.state.setSQL.pending
}
hex := uint16(d[1])<<8 | uint16(d[2])
s.state.sqlPercent = int(math.Round((float64(hex) / 0x0255) * 100))
statusLog.reportSQL(s.state.sqlPercent)
if s.state.setSQLSent {
s.state.setSQLSent = false
if s.state.getSQL.pending {
s.removePendingCmd(&s.state.getSQL)
return false
}
if s.state.setSQL.pending {
s.removePendingCmd(&s.state.setSQL)
return false
}
case 0x06:
if len(d) < 3 {
return !s.state.setNRSent
return !s.state.getNR.pending && !s.state.setNR.pending
}
hex := uint16(d[1])<<8 | uint16(d[2])
s.state.nrPercent = int(math.Round((float64(hex) / 0x0255) * 100))
statusLog.reportNR(s.state.nrPercent)
if s.state.setNRSent {
s.state.setNRSent = false
if s.state.getNR.pending {
s.removePendingCmd(&s.state.getNR)
return false
}
if s.state.setNR.pending {
s.removePendingCmd(&s.state.setNR)
return false
}
case 0x0a:
if len(d) < 3 {
return !s.state.setPwrSent
return !s.state.getPwr.pending && !s.state.setPwr.pending
}
hex := uint16(d[1])<<8 | uint16(d[2])
s.state.pwrPercent = int(math.Round((float64(hex) / 0x0255) * 100))
statusLog.reportTxPower(s.state.pwrPercent)
if s.state.setPwrSent {
s.state.setPwrSent = false
if s.state.getPwr.pending {
s.removePendingCmd(&s.state.getPwr)
return false
}
if s.state.setPwr.pending {
s.removePendingCmd(&s.state.setPwr)
return false
}
}
@ -454,7 +498,7 @@ func (s *civControlStruct) decodePowerRFGainSQLNR(d []byte) bool {
func (s *civControlStruct) decodeTransmitStatus(d []byte) bool {
if len(d) < 2 {
return !s.state.getTransmitStatusSent && !s.state.setPTTSent
return !s.state.getTuneStatus.pending && !s.state.getTransmitStatus.pending && !s.state.setPTT.pending
}
switch d[0] {
@ -468,8 +512,8 @@ func (s *civControlStruct) decodeTransmitStatus(d []byte) bool {
}
}
statusLog.reportPTT(s.state.ptt, s.state.tune)
if s.state.setPTTSent {
s.state.setPTTSent = false
if s.state.setPTT.pending {
s.removePendingCmd(&s.state.setPTT)
return false
}
case 1:
@ -488,13 +532,18 @@ func (s *civControlStruct) decodeTransmitStatus(d []byte) bool {
}
statusLog.reportPTT(s.state.ptt, s.state.tune)
if s.state.setTuneSent {
s.state.setTuneSent = false
if s.state.setTune.pending {
s.removePendingCmd(&s.state.setTune)
return false
}
}
if s.state.getTransmitStatusSent { // TODO
s.state.getTransmitStatusSent = false
if s.state.getTuneStatus.pending {
s.removePendingCmd(&s.state.getTuneStatus)
return false
}
if s.state.getTransmitStatus.pending {
s.removePendingCmd(&s.state.getTransmitStatus)
return false
}
return true
@ -504,7 +553,7 @@ func (s *civControlStruct) decodeVdSWRS(d []byte) bool {
switch d[0] {
case 0x02:
if len(d) < 3 {
return !s.state.getSSent
return !s.state.getS.pending
}
sValue := (int(math.Round(((float64(int(d[1])<<8) + float64(d[2])) / 0x0241) * 18)))
sStr := "S"
@ -538,48 +587,52 @@ func (s *civControlStruct) decodeVdSWRS(d []byte) bool {
}
s.state.lastSReceivedAt = time.Now()
statusLog.reportS(sStr)
if s.state.getSSent {
s.state.getSSent = false
if s.state.getS.pending {
s.removePendingCmd(&s.state.getS)
return false
}
case 0x12:
if len(d) < 3 {
return !s.state.getSWRSent
return !s.state.getSWR.pending
}
s.state.lastSWRReceivedAt = time.Now()
statusLog.reportSWR(((float64(int(d[1])<<8)+float64(d[2]))/0x0120)*2 + 1)
if s.state.getSWRSent {
s.state.getSWRSent = false
if s.state.getSWR.pending {
s.removePendingCmd(&s.state.getSWR)
return false
}
case 0x15:
if len(d) < 3 {
return !s.state.getVdSent
return !s.state.getVd.pending
}
statusLog.reportVd(((float64(int(d[1])<<8) + float64(d[2])) / 0x0241) * 16)
if s.state.getVdSent {
s.state.getVdSent = false
if s.state.getVd.pending {
s.removePendingCmd(&s.state.getVd)
return false
}
}
return true
}
func (s *civControlStruct) decodePreampAGCNR(d []byte) bool {
func (s *civControlStruct) decodePreampAGCNREnabled(d []byte) bool {
switch d[0] {
case 0x02:
if len(d) < 2 {
return !s.state.setPreampSent
return !s.state.getPreamp.pending && !s.state.setPreamp.pending
}
s.state.preamp = int(d[1])
statusLog.reportPreamp(s.state.preamp)
if s.state.setPreampSent {
s.state.setPreampSent = false
if s.state.getPreamp.pending {
s.removePendingCmd(&s.state.getPreamp)
return false
}
if s.state.setPreamp.pending {
s.removePendingCmd(&s.state.setPreamp)
return false
}
case 0x12:
if len(d) < 2 {
return !s.state.setAGCSent
return !s.state.getAGC.pending && !s.state.setAGC.pending
}
s.state.agc = int(d[1])
var agc string
@ -592,13 +645,17 @@ func (s *civControlStruct) decodePreampAGCNR(d []byte) bool {
agc = "S"
}
statusLog.reportAGC(agc)
if s.state.setAGCSent {
s.state.setAGCSent = false
if s.state.getAGC.pending {
s.removePendingCmd(&s.state.getAGC)
return false
}
if s.state.setAGC.pending {
s.removePendingCmd(&s.state.setAGC)
return false
}
case 0x40:
if len(d) < 2 {
return !s.state.setNREnabledSent
return !s.state.getNREnabled.pending && !s.state.setNREnabled.pending
}
if d[1] == 1 {
s.state.nrEnabled = true
@ -606,18 +663,61 @@ func (s *civControlStruct) decodePreampAGCNR(d []byte) bool {
s.state.nrEnabled = false
}
statusLog.reportNREnabled(s.state.nrEnabled)
if s.state.setNREnabledSent {
s.state.setNREnabledSent = false
if s.state.getNREnabled.pending {
s.removePendingCmd(&s.state.getNREnabled)
return false
}
if s.state.setNREnabled.pending {
s.removePendingCmd(&s.state.setNREnabled)
return false
}
}
return true
}
func (s *civControlStruct) initCmd(cmd *civCmd, name string, data []byte) {
*cmd = civCmd{}
cmd.name = name
cmd.cmd = data
}
func (s *civControlStruct) getPendingCmdIndex(cmd *civCmd) int {
for i := range s.state.pendingCmds {
if cmd == s.state.pendingCmds[i] {
return i
}
}
return -1
}
func (s *civControlStruct) removePendingCmd(cmd *civCmd) {
cmd.pending = false
index := s.getPendingCmdIndex(cmd)
if index < 0 {
return
}
s.state.pendingCmds[index] = s.state.pendingCmds[len(s.state.pendingCmds)-1]
s.state.pendingCmds[len(s.state.pendingCmds)-1] = nil
s.state.pendingCmds = s.state.pendingCmds[:len(s.state.pendingCmds)-1]
}
func (s *civControlStruct) sendCmd(cmd *civCmd) error {
cmd.pending = true
cmd.sentAt = time.Now()
if s.getPendingCmdIndex(cmd) < 0 {
s.state.pendingCmds = append(s.state.pendingCmds, cmd)
select {
case s.newPendingCmdAdded <- true:
default:
}
}
return s.st.send(cmd.cmd)
}
func (s *civControlStruct) setPwr(percent int) error {
s.state.setPwrSent = true
v := uint16(0x0255 * (float64(percent) / 100))
return s.st.send([]byte{254, 254, civAddress, 224, 0x14, 0x0a, byte(v >> 8), byte(v & 0xff), 253})
s.initCmd(&s.state.setPwr, "setPwr", []byte{254, 254, civAddress, 224, 0x14, 0x0a, byte(v >> 8), byte(v & 0xff), 253})
return s.sendCmd(&s.state.setPwr)
}
func (s *civControlStruct) incPwr() error {
@ -635,9 +735,9 @@ func (s *civControlStruct) decPwr() error {
}
func (s *civControlStruct) setRFGain(percent int) error {
s.state.setRFGainSent = true
v := uint16(0x0255 * (float64(percent) / 100))
return s.st.send([]byte{254, 254, civAddress, 224, 0x14, 0x02, byte(v >> 8), byte(v & 0xff), 253})
s.initCmd(&s.state.setRFGain, "setRFGain", []byte{254, 254, civAddress, 224, 0x14, 0x02, byte(v >> 8), byte(v & 0xff), 253})
return s.sendCmd(&s.state.setRFGain)
}
func (s *civControlStruct) incRFGain() error {
@ -655,9 +755,9 @@ func (s *civControlStruct) decRFGain() error {
}
func (s *civControlStruct) setSQL(percent int) error {
s.state.setSQLSent = true
v := uint16(0x0255 * (float64(percent) / 100))
return s.st.send([]byte{254, 254, civAddress, 224, 0x14, 0x03, byte(v >> 8), byte(v & 0xff), 253})
s.initCmd(&s.state.setSQL, "setSQL", []byte{254, 254, civAddress, 224, 0x14, 0x03, byte(v >> 8), byte(v & 0xff), 253})
return s.sendCmd(&s.state.setSQL)
}
func (s *civControlStruct) incSQL() error {
@ -680,9 +780,9 @@ func (s *civControlStruct) setNR(percent int) error {
return err
}
}
s.state.setNRSent = true
v := uint16(0x0255 * (float64(percent) / 100))
return s.st.send([]byte{254, 254, civAddress, 224, 0x14, 0x06, byte(v >> 8), byte(v & 0xff), 253})
s.initCmd(&s.state.setNR, "setNR", []byte{254, 254, civAddress, 224, 0x14, 0x06, byte(v >> 8), byte(v & 0xff), 253})
return s.sendCmd(&s.state.setNR)
}
func (s *civControlStruct) incNR() error {
@ -717,7 +817,6 @@ func (s *civControlStruct) decFreq() error {
}
func (s *civControlStruct) setFreq(f uint) error {
s.state.setFreqSent = true
var b [5]byte
v0 := s.getDigit(f, 9)
v1 := s.getDigit(f, 8)
@ -734,7 +833,8 @@ func (s *civControlStruct) setFreq(f uint) error {
v0 = s.getDigit(f, 1)
v1 = s.getDigit(f, 0)
b[0] = v0<<4 | v1
return s.st.send([]byte{254, 254, civAddress, 224, 5, b[0], b[1], b[2], b[3], b[4], 253})
s.initCmd(&s.state.setFreq, "setFreq", []byte{254, 254, civAddress, 224, 5, b[0], b[1], b[2], b[3], b[4], 253})
return s.sendCmd(&s.state.setFreq)
}
func (s *civControlStruct) incOperatingMode() error {
@ -774,20 +874,20 @@ func (s *civControlStruct) decFilter() error {
}
func (s *civControlStruct) setOperatingModeAndFilter(modeCode, filterCode byte) error {
s.state.setModeSent = true
if err := s.st.send([]byte{254, 254, civAddress, 224, 0x06, modeCode, filterCode, 253}); err != nil {
s.initCmd(&s.state.setMode, "setMode", []byte{254, 254, civAddress, 224, 0x06, modeCode, filterCode, 253})
if err := s.sendCmd(&s.state.setMode); err != nil {
return err
}
return s.getMode()
}
func (s *civControlStruct) setPTT(enable bool) error {
s.state.setPTTSent = true
var b byte
if enable {
b = 1
}
return s.st.send([]byte{254, 254, civAddress, 224, 0x1c, 0, b, 253})
s.initCmd(&s.state.setPTT, "setPTT", []byte{254, 254, civAddress, 224, 0x1c, 0, b, 253})
return s.sendCmd(&s.state.setPTT)
}
func (s *civControlStruct) toggleTune() error {
@ -795,14 +895,14 @@ func (s *civControlStruct) toggleTune() error {
return nil
}
s.state.setTuneSent = true
var b byte
if !s.state.tune {
b = 2
} else {
b = 1
}
return s.st.send([]byte{254, 254, civAddress, 224, 0x1c, 1, b, 253})
s.initCmd(&s.state.setTune, "setTune", []byte{254, 254, civAddress, 224, 0x1c, 1, b, 253})
return s.sendCmd(&s.state.setTune)
}
func (s *civControlStruct) setDataMode(enable bool) error {
@ -815,12 +915,11 @@ func (s *civControlStruct) setDataMode(enable bool) error {
b = 0
f = 0
}
return s.st.send([]byte{254, 254, civAddress, 224, 0x1a, 0x06, b, f, 253})
s.initCmd(&s.state.setDataMode, "setDataMode", []byte{254, 254, civAddress, 224, 0x1a, 0x06, b, f, 253})
return s.sendCmd(&s.state.setDataMode)
}
func (s *civControlStruct) toggleDataMode() error {
s.state.setDataModeSent = true
return s.setDataMode(!s.state.dataMode)
}
@ -851,61 +950,63 @@ func (s *civControlStruct) decBand() error {
}
func (s *civControlStruct) togglePreamp() error {
s.state.setPreampSent = true
b := byte(s.state.preamp + 1)
if b > 2 {
b = 0
}
return s.st.send([]byte{254, 254, civAddress, 224, 0x16, 0x02, b, 253})
s.initCmd(&s.state.setPreamp, "setPreamp", []byte{254, 254, civAddress, 224, 0x16, 0x02, b, 253})
return s.sendCmd(&s.state.setPreamp)
}
func (s *civControlStruct) toggleAGC() error {
s.state.setAGCSent = true
b := byte(s.state.agc + 1)
if b > 3 {
b = 1
}
return s.st.send([]byte{254, 254, civAddress, 224, 0x16, 0x12, b, 253})
s.initCmd(&s.state.setAGC, "setAGC", []byte{254, 254, civAddress, 224, 0x16, 0x12, b, 253})
return s.sendCmd(&s.state.setAGC)
}
func (s *civControlStruct) toggleNR() error {
s.state.setNRSent = true
var b byte
if !s.state.nrEnabled {
b = 1
}
return s.st.send([]byte{254, 254, civAddress, 224, 0x16, 0x40, b, 253})
s.initCmd(&s.state.setNREnabled, "setNREnabled", []byte{254, 254, civAddress, 224, 0x16, 0x40, b, 253})
return s.sendCmd(&s.state.setNREnabled)
}
func (s *civControlStruct) setTS(b byte) error {
s.initCmd(&s.state.setTS, "setTS", []byte{254, 254, civAddress, 224, 0x10, b, 253})
return s.sendCmd(&s.state.setTS)
}
func (s *civControlStruct) incTS() error {
s.state.setTSSent = true
var b byte
if s.state.tsValue == 13 {
b = 0
} else {
b = s.state.tsValue + 1
}
return s.st.send([]byte{254, 254, civAddress, 224, 0x10, b, 253})
return s.setTS(b)
}
func (s *civControlStruct) decTS() error {
s.state.setTSSent = true
var b byte
if s.state.tsValue == 0 {
b = 13
} else {
b = s.state.tsValue - 1
}
return s.st.send([]byte{254, 254, civAddress, 224, 0x10, b, 253})
return s.setTS(b)
}
func (s *civControlStruct) setVFO(nr byte) error {
s.state.setVFOSent = true
return s.st.send([]byte{254, 254, civAddress, 224, 0x07, nr, 253})
s.initCmd(&s.state.setVFO, "setVFO", []byte{254, 254, civAddress, 224, 0x07, nr, 253})
return s.sendCmd(&s.state.setVFO)
}
func (s *civControlStruct) toggleVFO() error {
s.state.setVFOSent = true
var b byte
if !s.state.vfoBActive {
b = 1
@ -914,7 +1015,6 @@ func (s *civControlStruct) toggleVFO() error {
}
func (s *civControlStruct) setSplit(mode splitMode) error {
s.state.setSplitSent = true
var b byte
switch mode {
default:
@ -926,11 +1026,11 @@ func (s *civControlStruct) setSplit(mode splitMode) error {
case splitModeDUPPlus:
b = 0x12
}
return s.st.send([]byte{254, 254, civAddress, 224, 0x0f, b, 253})
s.initCmd(&s.state.setSplit, "setSplit", []byte{254, 254, civAddress, 224, 0x0f, b, 253})
return s.sendCmd(&s.state.setSplit)
}
func (s *civControlStruct) toggleSplit() error {
s.state.setSplitSent = true
var mode splitMode
switch s.state.splitMode {
case splitModeOff:
@ -946,85 +1046,136 @@ func (s *civControlStruct) toggleSplit() error {
}
func (s *civControlStruct) getFreq() error {
s.state.getFreqSent = true
return s.st.send([]byte{254, 254, civAddress, 224, 3, 253})
s.initCmd(&s.state.getFreq, "getFreq", []byte{254, 254, civAddress, 224, 3, 253})
return s.sendCmd(&s.state.getFreq)
}
func (s *civControlStruct) getMode() error {
s.state.getModeSent = true
return s.st.send([]byte{254, 254, civAddress, 224, 4, 253})
s.initCmd(&s.state.getMode, "getMode", []byte{254, 254, civAddress, 224, 4, 253})
return s.sendCmd(&s.state.getMode)
}
func (s *civControlStruct) getDataMode() error {
s.state.getDataModeSent = true
return s.st.send([]byte{254, 254, civAddress, 224, 0x1a, 0x06, 253})
s.initCmd(&s.state.getDataMode, "getDataMode", []byte{254, 254, civAddress, 224, 0x1a, 0x06, 253})
return s.sendCmd(&s.state.getDataMode)
}
func (s *civControlStruct) getPwr() error {
s.initCmd(&s.state.getPwr, "getPwr", []byte{254, 254, civAddress, 224, 0x14, 0x0a, 253})
return s.sendCmd(&s.state.getPwr)
}
func (s *civControlStruct) getTransmitStatus() error {
s.state.getTransmitStatusSent = true
if err := s.st.send([]byte{254, 254, civAddress, 224, 0x1c, 0, 253}); err != nil {
s.initCmd(&s.state.getTransmitStatus, "getTransmitStatus", []byte{254, 254, civAddress, 224, 0x1c, 0, 253})
if err := s.sendCmd(&s.state.getTransmitStatus); err != nil {
return err
}
return s.st.send([]byte{254, 254, civAddress, 224, 0x1c, 1, 253})
s.initCmd(&s.state.getTuneStatus, "getTuneStatus", []byte{254, 254, civAddress, 224, 0x1c, 1, 253})
return s.sendCmd(&s.state.getTuneStatus)
}
func (s *civControlStruct) getPreamp() error {
s.initCmd(&s.state.getPreamp, "getPreamp", []byte{254, 254, civAddress, 224, 0x16, 0x02, 253})
return s.sendCmd(&s.state.getPreamp)
}
func (s *civControlStruct) getAGC() error {
s.initCmd(&s.state.getAGC, "getAGC", []byte{254, 254, civAddress, 224, 0x16, 0x12, 253})
return s.sendCmd(&s.state.getAGC)
}
func (s *civControlStruct) getVd() error {
s.state.getVdSent = true
return s.st.send([]byte{254, 254, civAddress, 224, 0x15, 0x15, 253})
s.initCmd(&s.state.getVd, "getVd", []byte{254, 254, civAddress, 224, 0x15, 0x15, 253})
return s.sendCmd(&s.state.getVd)
}
func (s *civControlStruct) getS() error {
s.state.getSSent = true
return s.st.send([]byte{254, 254, civAddress, 224, 0x15, 0x02, 253})
s.initCmd(&s.state.getS, "getS", []byte{254, 254, civAddress, 224, 0x15, 0x02, 253})
return s.sendCmd(&s.state.getS)
}
func (s *civControlStruct) getOVF() error {
s.state.getOVFSent = true
return s.st.send([]byte{254, 254, civAddress, 224, 0x1a, 0x09, 253})
s.initCmd(&s.state.getOVF, "getOVF", []byte{254, 254, civAddress, 224, 0x1a, 0x09, 253})
return s.sendCmd(&s.state.getOVF)
}
func (s *civControlStruct) getSWR() error {
s.state.getSWRSent = true
return s.st.send([]byte{254, 254, civAddress, 224, 0x15, 0x12, 253})
s.initCmd(&s.state.getSWR, "getSWR", []byte{254, 254, civAddress, 224, 0x15, 0x12, 253})
return s.sendCmd(&s.state.getSWR)
}
func (s *civControlStruct) getTS() error {
return s.st.send([]byte{254, 254, civAddress, 224, 0x10, 253})
s.initCmd(&s.state.getTS, "getTS", []byte{254, 254, civAddress, 224, 0x10, 253})
return s.sendCmd(&s.state.getTS)
}
func (s *civControlStruct) getRFGain() error {
return s.st.send([]byte{254, 254, civAddress, 224, 0x14, 0x02, 253})
s.initCmd(&s.state.getRFGain, "getRFGain", []byte{254, 254, civAddress, 224, 0x14, 0x02, 253})
return s.sendCmd(&s.state.getRFGain)
}
func (s *civControlStruct) getSQL() error {
return s.st.send([]byte{254, 254, civAddress, 224, 0x14, 0x03, 253})
s.initCmd(&s.state.getSQL, "getSQL", []byte{254, 254, civAddress, 224, 0x14, 0x03, 253})
return s.sendCmd(&s.state.getSQL)
}
func (s *civControlStruct) getNR() error {
return s.st.send([]byte{254, 254, civAddress, 224, 0x14, 0x06, 253})
s.initCmd(&s.state.getNR, "getNR", []byte{254, 254, civAddress, 224, 0x14, 0x06, 253})
return s.sendCmd(&s.state.getNR)
}
func (s *civControlStruct) getNREnabled() error {
return s.st.send([]byte{254, 254, civAddress, 224, 0x16, 0x40, 253})
s.initCmd(&s.state.getNREnabled, "getNREnabled", []byte{254, 254, civAddress, 224, 0x16, 0x40, 253})
return s.sendCmd(&s.state.getNREnabled)
}
func (s *civControlStruct) getSplit() error {
s.initCmd(&s.state.getSplit, "getSplit", []byte{254, 254, civAddress, 224, 0x0f, 253})
return s.sendCmd(&s.state.getSplit)
}
func (s *civControlStruct) loop() {
for {
s.state.mutex.Lock()
nextPendingCmdTimeout := time.Hour
for i := range s.state.pendingCmds {
diff := time.Since(s.state.pendingCmds[i].sentAt)
if diff >= commandRetryTimeout {
nextPendingCmdTimeout = 0
break
}
if diff < nextPendingCmdTimeout {
nextPendingCmdTimeout = diff
}
}
s.state.mutex.Unlock()
select {
case <-s.deinitNeeded:
s.deinitFinished <- true
return
case <-time.After(sReadInterval):
if time.Since(s.state.lastSReceivedAt) >= sReadInterval {
case <-time.After(statusPollInterval):
if !s.state.getS.pending && time.Since(s.state.lastSReceivedAt) >= statusPollInterval {
_ = s.getS()
}
if time.Since(s.state.lastOVFReceivedAt) >= sReadInterval {
if !s.state.getOVF.pending && time.Since(s.state.lastOVFReceivedAt) >= statusPollInterval {
_ = s.getOVF()
}
if time.Since(s.state.lastSWRReceivedAt) >= sReadInterval && (s.state.ptt || s.state.tune) {
if !s.state.getSWR.pending && time.Since(s.state.lastSWRReceivedAt) >= statusPollInterval &&
(s.state.ptt || s.state.tune) {
_ = s.getSWR()
}
case <-s.resetSReadTimer:
case <-s.newPendingCmdAdded:
case <-time.After(nextPendingCmdTimeout):
s.state.mutex.Lock()
for _, cmd := range s.state.pendingCmds {
if time.Since(cmd.sentAt) >= commandRetryTimeout {
log.Debug("retrying cmd send ", cmd.name)
_ = s.sendCmd(cmd)
}
}
s.state.mutex.Unlock()
}
}
}
@ -1041,19 +1192,16 @@ func (s *civControlStruct) init(st *serialStream) error {
if err := s.getDataMode(); err != nil {
return err
}
// Querying power.
if err := s.st.send([]byte{254, 254, civAddress, 224, 0x14, 0x0a, 253}); err != nil {
if err := s.getPwr(); err != nil {
return err
}
if err := s.getTransmitStatus(); err != nil {
return err
}
// Querying preamp.
if err := s.st.send([]byte{254, 254, civAddress, 224, 0x16, 0x02, 253}); err != nil {
if err := s.getPreamp(); err != nil {
return err
}
// Querying AGC.
if err := s.st.send([]byte{254, 254, civAddress, 224, 0x16, 0x12, 253}); err != nil {
if err := s.getAGC(); err != nil {
return err
}
if err := s.getVd(); err != nil {
@ -1083,14 +1231,14 @@ func (s *civControlStruct) init(st *serialStream) error {
if err := s.getNREnabled(); err != nil {
return err
}
// Querying split.
if err := s.st.send([]byte{254, 254, civAddress, 224, 0x0f, 253}); err != nil {
if err := s.getSplit(); err != nil {
return err
}
s.deinitNeeded = make(chan bool)
s.deinitFinished = make(chan bool)
s.resetSReadTimer = make(chan bool)
s.newPendingCmdAdded = make(chan bool)
go s.loop()
return nil
}