From 90871401300233f33defda06bf3f386093f791c8 Mon Sep 17 00:00:00 2001 From: Nonoo Date: Tue, 3 Nov 2020 20:55:27 +0100 Subject: [PATCH] Add periodic S meter readout and display --- README.md | 1 + civcontrol.go | 50 ++++++++++++++++++++++++++++++++++++++++++------- serialstream.go | 5 ++++- statuslog.go | 30 ++++++++++++++++++++++++++++- 4 files changed, 77 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index fe2412b..665be78 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,7 @@ is up) with the following info: - `txpwr`: current transmit power setting in percent - `audio`: current status of the audio monitor (see the *Hotkeys* section in this README for more information about this feature) + - `S meter`: periodically refreshed S meter value - Second status bar line: - `up`: how long the audio/serial connection is active diff --git a/civcontrol.go b/civcontrol.go index abdcf4f..e727bff 100644 --- a/civcontrol.go +++ b/civcontrol.go @@ -6,6 +6,7 @@ import ( ) const civAddress = 0xa4 +const sReadInterval = time.Second type civOperatingMode struct { name string @@ -61,7 +62,10 @@ var civBands = []civBand{ } type civControlStruct struct { - st *serialStream + st *serialStream + deinitNeeded chan bool + deinitFinished chan bool + resetSReadTimer chan bool state struct { freq uint @@ -102,7 +106,7 @@ func (s *civControlStruct) decode(d []byte) { case 0x1c: s.decodeTransmitStatus(payload) case 0x15: - s.decodeVd(payload) + s.decodeVdAndS(payload) case 0x16: s.decodePreamp(payload) } @@ -232,16 +236,15 @@ func (s *civControlStruct) decodeTransmitStatus(d []byte) { statusLog.reportPTT(s.state.ptt, s.state.tune) } -func (s *civControlStruct) decodeVd(d []byte) { - if len(d) < 2 { +func (s *civControlStruct) decodeVdAndS(d []byte) { + if len(d) < 3 { return } switch d[0] { + case 0x02: + statusLog.reportS(int(math.Round(((float64(int(d[1])<<8) + float64(d[2])) / 0x0241) * 18))) case 0x15: - if len(d) < 3 { - return - } statusLog.reportVd(((float64(int(d[1])<<8) + float64(d[2])) / 0x0241) * 16) } } @@ -453,6 +456,23 @@ func (s *civControlStruct) getVd() error { return s.st.send([]byte{254, 254, civAddress, 224, 0x15, 0x15, 253}) } +func (s *civControlStruct) getS() error { + return s.st.send([]byte{254, 254, civAddress, 224, 0x15, 0x02, 253}) +} + +func (s *civControlStruct) loop() { + for { + select { + case <-s.deinitNeeded: + s.deinitFinished <- true + return + case <-time.After(sReadInterval): + _ = s.getS() + case <-s.resetSReadTimer: + } + } +} + func (s *civControlStruct) init(st *serialStream) error { s.st = st @@ -479,5 +499,21 @@ func (s *civControlStruct) init(st *serialStream) error { if err := s.getVd(); err != nil { return err } + if err := s.getS(); err != nil { + return err + } + + s.deinitNeeded = make(chan bool) + s.deinitFinished = make(chan bool) + s.resetSReadTimer = make(chan bool) + go s.loop() return nil } + +func (s *civControlStruct) deinit() { + if s.deinitNeeded != nil { + s.deinitNeeded <- true + <-s.deinitFinished + } + s.deinitNeeded = nil +} diff --git a/serialstream.go b/serialstream.go index 5ce4806..f287e57 100644 --- a/serialstream.go +++ b/serialstream.go @@ -270,7 +270,10 @@ func (s *serialStream) deinit() { s.deinitNeededChan <- true <-s.deinitFinishedChan } - civControl = nil + if civControl != nil { + civControl.deinit() + civControl = nil + } s.common.deinit() s.rxSeqBuf.deinit() } diff --git a/statuslog.go b/statuslog.go index adefbc2..c624041 100644 --- a/statuslog.go +++ b/statuslog.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "math" "os" "sync" "time" @@ -22,6 +23,7 @@ type statusLogData struct { preamp string vd string txPowerStr string + s string startTime time.Time rttStr string @@ -155,6 +157,28 @@ func (s *statusLogStruct) reportVd(voltage float64) { s.data.vd = fmt.Sprintf("%.1fV", voltage) } +func (s *statusLogStruct) reportS(sValue int) { + s.mutex.Lock() + defer s.mutex.Unlock() + + if s.data == nil { + return + } + s.data.s = "S" + if sValue <= 9 { + s.data.s += fmt.Sprint(sValue) + } else { + s.data.s += "9+" + + if sValue > 18 { + s.data.s += "60" + } else { + dB := (float64((sValue - 9)) / 9) * 60 + s.data.s += fmt.Sprint(int(math.Round(dB/10) * 10)) + } + } +} + func (s *statusLogStruct) reportPTT(ptt, tune bool) { s.mutex.Lock() defer s.mutex.Unlock() @@ -233,8 +257,12 @@ func (s *statusLogStruct) update() { if s.data.txPowerStr != "" { txPowerStr = " txpwr " + s.data.txPowerStr } + var sStr string + if s.data.s != "" { + sStr = " " + s.data.s + } s.data.line1 = fmt.Sprint(s.data.stateStr, " ", fmt.Sprintf("%.6f", float64(s.data.frequency)/1000000), - modeStr, filterStr, preampStr, vdStr, txPowerStr, " audio ", s.data.audioStateStr) + modeStr, filterStr, preampStr, vdStr, txPowerStr, " audio ", s.data.audioStateStr, sStr) up, down, lost, retransmits := netstat.get() lostStr := "0"