feat(icom): phase 5 — the voice keyer plays to the radio over the LAN
The audio session opens its TX side alongside RX (txenable in the conninfo, 16 kHz both ways), the stream gains a paced sender — 320 samples every 20 ms, the frame mirroring what the rig itself sends on this socket, IDs swapped — and the network Icom takes the same NetworkPlayer slot a TCI radio does: pick 'Radio (network audio)' as the To-radio device and the voice keyer needs no cable and no virtual sound card. PTT brackets the message through the same code as every other audio path.
This commit is contained in:
+17
-2
@@ -940,7 +940,11 @@ func icnConnInfo(seq, innerSeq, tokReq uint16, sentid, rcvdid, token uint32, use
|
||||
copy(b[0x40:0x60], []byte("IC-7610"))
|
||||
copy(b[0x60:0x70], icnPasscode(user))
|
||||
b[0x70] = rxEnable // rxenable: 1 opens the 50003 RX audio stream, 0 = CI-V only
|
||||
b[0x71] = 0x00 // txenable (Phase 5)
|
||||
// TX rides the same audio session: whenever the operator wants RX audio the
|
||||
// TX side is opened with it, so the voice keyer can play to the radio with
|
||||
// no cable. Costs nothing when unused — no packets flow until a message is
|
||||
// actually played.
|
||||
b[0x71] = rxEnable // txenable
|
||||
// rxcodec 0x04 = LPCM, ONE channel, 16-BIT — settled by experiment on a
|
||||
// real IC-7760, one wrong guess at a time: 0x10 produced 1280-byte payloads
|
||||
// of interleaved 16-bit stereo, 0x02 produced 320-byte payloads of 8-bit
|
||||
@@ -949,7 +953,7 @@ func icnConnInfo(seq, innerSeq, tokReq uint16, sentid, rcvdid, token uint32, use
|
||||
b[0x72] = 0x04 // rxcodec
|
||||
b[0x73] = 0x04 // txcodec
|
||||
icnBE.PutUint32(b[0x74:], 16000)
|
||||
icnBE.PutUint32(b[0x78:], 8000)
|
||||
icnBE.PutUint32(b[0x78:], 16000) // TX sample rate — the same 16 kHz everything else here runs at
|
||||
icnBE.PutUint32(b[0x7c:], uint32(civPort))
|
||||
icnBE.PutUint32(b[0x80:], uint32(audioPort))
|
||||
icnBE.PutUint32(b[0x84:], 100)
|
||||
@@ -957,6 +961,17 @@ func icnConnInfo(seq, innerSeq, tokReq uint16, sentid, rcvdid, token uint32, use
|
||||
return b
|
||||
}
|
||||
|
||||
// PlayTXAudio plays one voice-keyer message through the 50003 audio session.
|
||||
// On the transport because the transport owns the session; the IcomSerial
|
||||
// controller forwards here after a type assertion, exactly as the TCI path
|
||||
// reaches its radio.
|
||||
func (n *icomNet) PlayTXAudio(pcm []byte, rate, ch, bits int, stop <-chan struct{}) error {
|
||||
if n.audio == nil {
|
||||
return fmt.Errorf("the radio's audio stream is not open — enable RX audio in Settings → CAT first")
|
||||
}
|
||||
return n.audio.PlayTX(pcm, rate, ch, bits, stop)
|
||||
}
|
||||
|
||||
func icnOpenClose(seq uint16, sentid, rcvdid uint32, civSeq uint16, magic byte) []byte {
|
||||
b := make([]byte, 0x16)
|
||||
icnLE.PutUint32(b[0:], 0x16)
|
||||
|
||||
Reference in New Issue
Block a user