mirror of
https://github.com/nonoo/kappanhang.git
synced 2025-12-06 08:02:00 +01:00
Add tune support
This commit is contained in:
parent
3763996cd4
commit
d1511bc15d
|
|
@ -153,10 +153,11 @@ not available.
|
||||||
Note that audio will be played to the previously created virtual sound card
|
Note that audio will be played to the previously created virtual sound card
|
||||||
regardless of this setting.
|
regardless of this setting.
|
||||||
- `space`: toggles PTT and audio stream recording from the default sound
|
- `space`: toggles PTT and audio stream recording from the default sound
|
||||||
device.
|
device
|
||||||
|
|
||||||
You can transmit your own voice using a mic attached to your computer for
|
You can transmit your own voice using a mic attached to your computer for
|
||||||
example.
|
example.
|
||||||
|
- `t`: toggles the tune process
|
||||||
|
|
||||||
## Authors
|
## Authors
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,19 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "math"
|
import (
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
const civAddress = 0xa4
|
const civAddress = 0xa4
|
||||||
|
|
||||||
type civControlStruct struct {
|
type civControlStruct struct {
|
||||||
st *serialStream
|
st *serialStream
|
||||||
|
|
||||||
|
state struct {
|
||||||
|
ptt bool
|
||||||
|
tune bool
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var civControl *civControlStruct
|
var civControl *civControlStruct
|
||||||
|
|
@ -26,6 +34,8 @@ func (s *civControlStruct) decode(d []byte) {
|
||||||
s.decodeFreq(payload)
|
s.decodeFreq(payload)
|
||||||
case 0x04:
|
case 0x04:
|
||||||
s.decodeMode(payload)
|
s.decodeMode(payload)
|
||||||
|
case 0x1a:
|
||||||
|
s.decodeDataMode(payload)
|
||||||
case 0x14:
|
case 0x14:
|
||||||
s.decodePower(payload)
|
s.decodePower(payload)
|
||||||
case 0x1c:
|
case 0x1c:
|
||||||
|
|
@ -47,6 +57,18 @@ func (s *civControlStruct) decodeFreq(d []byte) {
|
||||||
statusLog.reportFrequency(f)
|
statusLog.reportFrequency(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *civControlStruct) decodeFilterValue(v byte) string {
|
||||||
|
switch v {
|
||||||
|
case 0x01:
|
||||||
|
return "FIL1"
|
||||||
|
case 0x02:
|
||||||
|
return "FIL2"
|
||||||
|
case 0x03:
|
||||||
|
return "FIL3"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (s *civControlStruct) decodeMode(d []byte) {
|
func (s *civControlStruct) decodeMode(d []byte) {
|
||||||
if len(d) < 1 {
|
if len(d) < 1 {
|
||||||
return
|
return
|
||||||
|
|
@ -78,16 +100,27 @@ func (s *civControlStruct) decodeMode(d []byte) {
|
||||||
|
|
||||||
var filter string
|
var filter string
|
||||||
if len(d) > 1 {
|
if len(d) > 1 {
|
||||||
switch d[1] {
|
filter = s.decodeFilterValue(d[1])
|
||||||
case 0x01:
|
|
||||||
filter = "FIL1"
|
|
||||||
case 0x02:
|
|
||||||
filter = "FIL2"
|
|
||||||
case 0x03:
|
|
||||||
filter = "FIL3"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
statusLog.reportMode(mode, filter)
|
statusLog.reportMode(mode, filter)
|
||||||
|
|
||||||
|
// The transceiver does not send the data mode setting automatically.
|
||||||
|
_ = s.getDataMode()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *civControlStruct) decodeDataMode(d []byte) {
|
||||||
|
if len(d) < 3 || d[0] != 0x06 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var dataMode string
|
||||||
|
var filter string
|
||||||
|
if d[1] == 1 {
|
||||||
|
dataMode = "-D"
|
||||||
|
filter = s.decodeFilterValue(d[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
statusLog.reportDataMode(dataMode, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *civControlStruct) decodePower(d []byte) {
|
func (s *civControlStruct) decodePower(d []byte) {
|
||||||
|
|
@ -106,19 +139,26 @@ func (s *civControlStruct) decodeTransmitStatus(d []byte) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var ptt bool
|
|
||||||
var tune bool
|
|
||||||
switch d[0] {
|
switch d[0] {
|
||||||
case 0:
|
case 0:
|
||||||
if d[1] == 1 {
|
if d[1] == 1 {
|
||||||
ptt = true
|
s.state.ptt = true
|
||||||
|
} else {
|
||||||
|
s.state.ptt = false
|
||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
if d[1] == 2 {
|
if d[1] == 2 {
|
||||||
tune = true
|
s.state.tune = true
|
||||||
|
|
||||||
|
// The transceiver does not send the tune state after it's finished.
|
||||||
|
time.AfterFunc(time.Second, func() {
|
||||||
|
_ = s.getTransmitStatus()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
s.state.tune = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
statusLog.reportPTT(ptt, tune)
|
statusLog.reportPTT(s.state.ptt, s.state.tune)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *civControlStruct) setPTT(enable bool) error {
|
func (s *civControlStruct) setPTT(enable bool) error {
|
||||||
|
|
@ -129,6 +169,31 @@ func (s *civControlStruct) setPTT(enable bool) error {
|
||||||
return s.st.send([]byte{254, 254, civAddress, 224, 0x1c, 0, b, 253})
|
return s.st.send([]byte{254, 254, civAddress, 224, 0x1c, 0, b, 253})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *civControlStruct) toggleTune() error {
|
||||||
|
if s.state.ptt {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *civControlStruct) getDataMode() error {
|
||||||
|
return s.st.send([]byte{254, 254, civAddress, 224, 0x1a, 0x06, 253})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *civControlStruct) getTransmitStatus() error {
|
||||||
|
if err := s.st.send([]byte{254, 254, civAddress, 224, 0x1c, 0, 253}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return s.st.send([]byte{254, 254, civAddress, 224, 0x1c, 1, 253})
|
||||||
|
}
|
||||||
|
|
||||||
func (s *civControlStruct) init(st *serialStream) error {
|
func (s *civControlStruct) init(st *serialStream) error {
|
||||||
s.st = st
|
s.st = st
|
||||||
|
|
||||||
|
|
@ -140,12 +205,14 @@ func (s *civControlStruct) init(st *serialStream) error {
|
||||||
if err := s.st.send([]byte{254, 254, civAddress, 224, 4, 253}); err != nil {
|
if err := s.st.send([]byte{254, 254, civAddress, 224, 4, 253}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := s.getDataMode(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
// Querying power.
|
// Querying power.
|
||||||
if err := s.st.send([]byte{254, 254, civAddress, 224, 0x14, 0x0a, 253}); err != nil {
|
if err := s.st.send([]byte{254, 254, civAddress, 224, 0x14, 0x0a, 253}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Querying PTT.
|
if err := s.getTransmitStatus(); err != nil {
|
||||||
if err := s.st.send([]byte{254, 254, civAddress, 224, 0x1c, 0, 253}); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,12 @@ func (s *keyboardStruct) handleKey(k byte) {
|
||||||
audio.togglePlaybackToDefaultSoundcard()
|
audio.togglePlaybackToDefaultSoundcard()
|
||||||
case ' ':
|
case ' ':
|
||||||
audio.toggleRecFromDefaultSoundcard()
|
audio.toggleRecFromDefaultSoundcard()
|
||||||
|
case 't':
|
||||||
|
if civControl != nil {
|
||||||
|
if err := civControl.toggleTune(); err != nil {
|
||||||
|
log.Error("can't toggle tune: ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
16
statuslog.go
16
statuslog.go
|
|
@ -17,6 +17,7 @@ type statusLogData struct {
|
||||||
stateStr string
|
stateStr string
|
||||||
frequency float64
|
frequency float64
|
||||||
mode string
|
mode string
|
||||||
|
dataMode string
|
||||||
filter string
|
filter string
|
||||||
txPowerStr string
|
txPowerStr string
|
||||||
|
|
||||||
|
|
@ -119,6 +120,19 @@ func (s *statusLogStruct) reportMode(mode, filter string) {
|
||||||
s.data.filter = filter
|
s.data.filter = filter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *statusLogStruct) reportDataMode(dataMode, filter string) {
|
||||||
|
s.mutex.Lock()
|
||||||
|
defer s.mutex.Unlock()
|
||||||
|
|
||||||
|
if s.data == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.data.dataMode = dataMode
|
||||||
|
if dataMode != "" {
|
||||||
|
s.data.filter = filter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *statusLogStruct) reportPTT(ptt, tune bool) {
|
func (s *statusLogStruct) reportPTT(ptt, tune bool) {
|
||||||
s.mutex.Lock()
|
s.mutex.Lock()
|
||||||
defer s.mutex.Unlock()
|
defer s.mutex.Unlock()
|
||||||
|
|
@ -179,7 +193,7 @@ func (s *statusLogStruct) update() {
|
||||||
|
|
||||||
var modeStr string
|
var modeStr string
|
||||||
if s.data.mode != "" {
|
if s.data.mode != "" {
|
||||||
modeStr = " " + s.data.mode
|
modeStr = " " + s.data.mode + s.data.dataMode
|
||||||
}
|
}
|
||||||
var filterStr string
|
var filterStr string
|
||||||
if s.data.filter != "" {
|
if s.data.filter != "" {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue