Fix bugs in setting Rx frequency

This commit is contained in:
Rui Oliveira committed 2026-07-24 20:08:46 +01:00
1 parent f9b1a97a37
commit dc596b4348
2 files changed
+41 -4

No files matched your search

@@ -244,7 +244,9 @@ class Ic705Controller(
/**
* Drain whatever bytes the radio has buffered within a [timeoutMs] window.
* Uses non-blocking `available()` polling to avoid blocking indefinitely.
* Exits early as soon as a complete CI-V frame addressed to us is present
* in the buffer (i.e., FE FE E0 A4 … FD), so we don't waste the remaining
* timeout on responses that already arrived.
*/
private suspend fun drainWithTimeout(timeoutMs: Long): ByteArray {
val result = mutableListOf<Byte>()
@@ -256,7 +258,11 @@ class Ic705Controller(
if (available > 0) {
val chunk = ByteArray(available)
val read = stream.read(chunk)
if (read > 0) result.addAll(chunk.take(read))
if (read > 0) {
result.addAll(chunk.take(read))
// Exit early once we have a complete frame for us
if (hasCompleteFrameForUs(result)) break
}
} else {
delay(POLL_INTERVAL_MS)
}
@@ -269,6 +275,30 @@ class Ic705Controller(
return result.toByteArray()
}
/**
* Returns true if [buf] contains a complete CI-V frame addressed to the
* controller (FE FE [ADDR_CTRL] [ADDR_IC705] … FD).
* CI-V data bytes cannot be 0xFD, so the first 0xFD after the header is
* always the frame terminator.
*/
private fun hasCompleteFrameForUs(buf: List<Byte>): Boolean {
var i = 0
while (i < buf.size - 4) {
if (buf[i] == IcomCivProtocol.PREAMBLE &&
buf[i + 1] == IcomCivProtocol.PREAMBLE &&
buf[i + 2] == IcomCivProtocol.ADDR_CTRL &&
buf[i + 3] == IcomCivProtocol.ADDR_IC705
) {
for (k in i + 4 until buf.size) {
if (buf[k] == IcomCivProtocol.END_OF_MSG) return true
}
return false // header found but no FD yet
}
i++
}
return false
}
private fun write(bytes: ByteArray): Boolean {
return try {
outputStream?.write(bytes)
@@ -283,11 +283,18 @@ object IcomCivProtocol {
/**
* Parse TX status from a CMD_TX_STATUS reply payload.
*
* The IC-705 responds to a `1C 00` query with:
* FE FE E0 A4 1C 00 <status> FD
* After [parseResponse] strips the frame header the payload is:
* payload[0] = 0x00 (sub-command echo)
* payload[1] = status byte (0x00 = RX, 0x01 = TX)
*
* Returns true if transmitting, false if receiving, null on error.
*/
fun parseTxStatus(payload: ByteArray): Boolean? {
if (payload.isEmpty()) return null
return when (payload[0]) {
if (payload.size < 2) return null
return when (payload[1]) {
0x00.toByte() -> false // RX
0x01.toByte() -> true // TX
else -> null