diff --git a/README.md b/README.md index ea95db1..3fd1f3a 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,8 @@ kappanhang displays a "realtime" status bar (when the audio/serial connection is up) with the following info: - First status bar line: - - `S meter`: periodically refreshed S meter value + - `S meter`: periodically refreshed S meter value, OVF is displayed on + overflow - Second status bar line: - `state`: RX/TX/TUNE depending on the PTT status @@ -108,7 +109,7 @@ is up) with the following info: - `lost`: lost audio/serial packet count from the server Data for the first 2 status bar lines are acquired by monitoring CiV traffic -in the serial stream. S value is queried periodically. +in the serial stream. S value and OVF are queried periodically. `retx` and `lost` are displayed in a 1 minute window, which means they will be reset to 0 if they don't increase for 1 minute. A `retx` value other than 0 diff --git a/civcontrol.go b/civcontrol.go index b88cdf5..7e63e48 100644 --- a/civcontrol.go +++ b/civcontrol.go @@ -105,7 +105,7 @@ func (s *civControlStruct) decode(d []byte) { case 0x10: s.decodeTS(payload) case 0x1a: - s.decodeDataMode(payload) + s.decodeDataModeAndOVF(payload) case 0x14: s.decodePower(payload) case 0x1c: @@ -218,23 +218,35 @@ func (s *civControlStruct) decodeTS(d []byte) { statusLog.reportTS(s.state.ts) } -func (s *civControlStruct) decodeDataMode(d []byte) { - if len(d) < 3 || d[0] != 0x06 { +func (s *civControlStruct) decodeDataModeAndOVF(d []byte) { + if len(d) < 2 { return } - var dataMode string - var filter string - if d[1] == 1 { - dataMode = "-D" - s.state.dataMode = true - s.state.filterIdx = s.decodeFilterValueToFilterIdx(d[2]) - filter = civFilters[s.state.filterIdx].name - } else { - s.state.dataMode = false - } + switch d[0] { + case 0x06: + if len(d) < 3 { + return + } + var dataMode string + var filter string + if d[1] == 1 { + dataMode = "-D" + s.state.dataMode = true + s.state.filterIdx = s.decodeFilterValueToFilterIdx(d[2]) + filter = civFilters[s.state.filterIdx].name + } else { + s.state.dataMode = false + } - statusLog.reportDataMode(dataMode, filter) + statusLog.reportDataMode(dataMode, filter) + case 0x09: + if d[1] != 0 { + statusLog.reportOVF(true) + } else { + statusLog.reportOVF(false) + } + } } func (s *civControlStruct) decodePower(d []byte) { @@ -539,6 +551,10 @@ func (s *civControlStruct) getS() error { return s.st.send([]byte{254, 254, civAddress, 224, 0x15, 0x02, 253}) } +func (s *civControlStruct) getOVF() error { + return s.st.send([]byte{254, 254, civAddress, 224, 0x1a, 0x09, 253}) +} + func (s *civControlStruct) getTS() error { return s.st.send([]byte{254, 254, civAddress, 224, 0x10, 253}) } @@ -551,6 +567,7 @@ func (s *civControlStruct) loop() { return case <-time.After(sReadInterval): _ = s.getS() + _ = s.getOVF() case <-s.resetSReadTimer: } } @@ -585,6 +602,9 @@ func (s *civControlStruct) init(st *serialStream) error { if err := s.getS(); err != nil { return err } + if err := s.getOVF(); err != nil { + return err + } if err := s.getTS(); err != nil { return err } diff --git a/statuslog.go b/statuslog.go index 585eb4e..fc18799 100644 --- a/statuslog.go +++ b/statuslog.go @@ -24,6 +24,7 @@ type statusLogData struct { vd string txPower string s string + ovf bool ts string startTime time.Time @@ -55,6 +56,8 @@ type statusLogStruct struct { monOn string rec string } + + ovf string } data *statusLogData @@ -168,6 +171,16 @@ func (s *statusLogStruct) reportS(sValue string) { s.data.s = sValue } +func (s *statusLogStruct) reportOVF(ovf bool) { + s.mutex.Lock() + defer s.mutex.Unlock() + + if s.data == nil { + return + } + s.data.ovf = ovf +} + func (s *statusLogStruct) reportTS(ts uint) { s.mutex.Lock() defer s.mutex.Unlock() @@ -249,7 +262,11 @@ func (s *statusLogStruct) update() { s.mutex.Lock() defer s.mutex.Unlock() - s.data.line1 = fmt.Sprint(s.data.s) + var ovfStr string + if s.data.ovf { + ovfStr = " " + s.preGenerated.ovf + } + s.data.line1 = fmt.Sprint(s.data.s, ovfStr) var tsStr string if s.data.ts != "" { @@ -396,6 +413,10 @@ func (s *statusLogStruct) initIfNeeded() { s.preGenerated.stateStr.tune = c.Sprint(" TUNE ") s.preGenerated.audioStateStr.rec = c.Sprint(" REC ") + c = color.New(color.FgHiWhite) + c.Add(color.BgRed) + s.preGenerated.ovf = c.Sprint(" OVF ") + s.preGenerated.retransmitsColor = color.New(color.FgHiWhite) s.preGenerated.retransmitsColor.Add(color.BgYellow) s.preGenerated.lostColor = color.New(color.FgHiWhite)