diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/framework/Ic705Controller.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/framework/Ic705Controller.kt index 010c115e..c02d37f3 100644 --- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/framework/Ic705Controller.kt +++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/framework/Ic705Controller.kt @@ -151,37 +151,18 @@ class Ic705Controller( } override suspend fun pttOn(): Boolean = withContext(Dispatchers.IO) { - Log.w(tag, "pttOn: PTT control not used for IC-705 (radio is master)") + Log.w(tag, "pttOn: not used for IC-705") true } override suspend fun pttOff(): Boolean = withContext(Dispatchers.IO) { - Log.w(tag, "pttOff: PTT control not used for IC-705 (radio is master)") + Log.w(tag, "pttOff: not used for IC-705") true } // ── IRadioController – IC-705 extended operations ─────────────────────── - /** - * Read the current PTT (TX/RX) status from the radio. - * Returns **true** if the radio is currently transmitting, **false** if - * receiving, **null** on error. - */ - override suspend fun readPttStatus(): Boolean? = withContext(Dispatchers.IO) { - ioMutex.withLock { - val cmd = IcomCivProtocol.buildReadTxStatusCommand() - Log.d(tag, "CMD readPTT → ${IcomCivProtocol.toHex(cmd)}") - val payload = sendAndReadResponse(cmd, IcomCivProtocol.CMD_TX_STATUS) ?: return@withContext null - IcomCivProtocol.parseTxStatus(payload).also { - Log.d(tag, "PTT status: ${if (it == true) "TX" else if (it == false) "RX" else "unknown"}") - } - } - } - - /** - * Select VFO-A (main) or VFO-B (sub). - * @param vfoA true → VFO-A, false → VFO-B - */ + /** Select VFO-A (main/RX) or VFO-B (sub/TX). */ override suspend fun setVfo(vfoA: Boolean): Boolean = withContext(Dispatchers.IO) { val cmd = if (vfoA) IcomCivProtocol.buildSelectVfoACommand() else IcomCivProtocol.buildSelectVfoBCommand() @@ -212,7 +193,7 @@ class Ic705Controller( /** * Set TX VFO frequency via CMD 0x25 sub 0x01 (unselected VFO). - * Used in split mode while PTT is pressed. + * Sent every tracking cycle in split mode alongside [setWorkingFrequency]. */ override suspend fun setTxVfoFrequency(frequencyHz: Long): Boolean = withContext(Dispatchers.IO) { Log.d(tag, "setTxVfoFrequency (0x25/01): ${frequencyHz}Hz") diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/framework/IcomCivProtocol.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/framework/IcomCivProtocol.kt index 0f400c1b..1b8b807e 100644 --- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/framework/IcomCivProtocol.kt +++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/framework/IcomCivProtocol.kt @@ -57,9 +57,7 @@ object IcomCivProtocol { const val CMD_CTCSS_TONE: Byte = 0x1B /** Read/write misc settings (used for enabling CTCSS encode). */ const val CMD_MISC_SETTING: Byte = 0x16 - /** Read/write TX-inhibit / transmit status. */ - const val CMD_TX_STATUS: Byte = 0x1C - /** Read/write selected-VFO frequency (cmd 0x25, sub 0x00). */ + /** Read/write selected-VFO frequency (cmd 0x25). */ const val CMD_SELECTED_VFO_FREQ: Byte = 0x25 // ── Sub-command bytes ────────────────────────────────────────────────── @@ -71,8 +69,6 @@ object IcomCivProtocol { const val SUB_SPLIT_OFF: Byte = 0x00 /** Sub for CMD_DUPLEX_SPLIT: SPLIT ON. */ const val SUB_SPLIT_ON: Byte = 0x01 - /** Sub for CMD_TX_STATUS: query TX/RX state. */ - const val SUB_TX_STATE: Byte = 0x00 /** Sub for CMD_SELECTED_VFO_FREQ: selected (active) VFO frequency. */ const val SUB_SELECTED_VFO: Byte = 0x00 /** Sub for CMD_SELECTED_VFO_FREQ: unselected (inactive / TX in split) VFO frequency. */ @@ -200,9 +196,6 @@ object IcomCivProtocol { return frame(CMD_DUPLEX_SPLIT, sub) } - /** Query TX/RX status (CMD 0x1C sub 0x00). Radio replies with 0x00=RX, 0x01=TX. */ - fun buildReadTxStatusCommand(): ByteArray = frame(CMD_TX_STATUS, SUB_TX_STATE) - /** * Enable/disable CTCSS encode (CMD 0x16 sub 0x42). * 0x01 = CTCSS encoder ON, 0x00 = OFF. @@ -293,26 +286,6 @@ object IcomCivProtocol { return freqHz to mode } - /** - * 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 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.size < 2) return null - return when (payload[1]) { - 0x00.toByte() -> false // RX - 0x01.toByte() -> true // TX - else -> null - } - } - /** Hex dump of bytes, useful for debug logging. */ fun toHex(bytes: ByteArray): String = bytes.joinToString(" ") { String.format(Locale.US, "%02X", it.toInt() and 0xFF) } diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/framework/RadioTrackingService.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/framework/RadioTrackingService.kt index 67f8e770..fa43c7dd 100644 --- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/framework/RadioTrackingService.kt +++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/framework/RadioTrackingService.kt @@ -380,33 +380,17 @@ class RadioTrackingService( val rxRadioFreq = rxBaseCalc?.let { pos.getDownlinkFreq(it) } if (radio.isConnected) { - // Query PTT state — don't assume silence; filter broadcast noise - val isPtt = radio.readPttStatus() - Log.d(tag, "Split loop: isPTT=$isPtt txFreq=$txRadioFreq rxFreq=$rxRadioFreq") - - when (isPtt) { - true -> { - // PTT ON → radio's active VFO is VFO-B (TX) - // Use 0x25/01 (unselected VFO) to target VFO-B directly - if (txRadioFreq != null) { - Log.d(tag, "Split loop TX update (0x25/01): ${txRadioFreq}Hz") - radio.setTxVfoFrequency(txRadioFreq) - } + // Update both VFOs every cycle — no PTT polling needed. + // 0x25/00 = active (RX) VFO, 0x25/01 = inactive (TX) VFO. + if (rxRadioFreq != null) { + Log.d(tag, "Split loop RX (0x25/00): ${rxRadioFreq}Hz") + radio.setWorkingFrequency(rxRadioFreq) } - false -> { - // PTT OFF → radio's active VFO is VFO-A (RX) - // Use 0x25/00 (selected/active VFO) to update RX - if (rxRadioFreq != null) { - Log.d(tag, "Split loop RX update (0x25/00): ${rxRadioFreq}Hz") - radio.setWorkingFrequency(rxRadioFreq) - } - } - null -> { - // Could not read PTT (broadcast noise race) — skip this tick - Log.d(tag, "Split loop: PTT read failed, skipping tick") + if (txRadioFreq != null) { + Log.d(tag, "Split loop TX (0x25/01): ${txRadioFreq}Hz") + radio.setTxVfoFrequency(txRadioFreq) } } - } _state.update { it.copy( diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/IRadioController.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/IRadioController.kt index 89d2c83f..cd198f4b 100644 --- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/IRadioController.kt +++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/IRadioController.kt @@ -41,13 +41,6 @@ interface IRadioController { // ── Extended operations (IC-705 / CI-V) ────────────────────────────── - /** - * Read the current PTT status from the radio. - * Returns true if transmitting, false if receiving, null on error. - * Default: not supported. - */ - suspend fun readPttStatus(): Boolean? = null - /** * Select the active VFO. * @param vfoA true → VFO-A (main/RX), false → VFO-B (sub/TX in split). @@ -62,15 +55,14 @@ interface IRadioController { suspend fun setSplitMode(enabled: Boolean): Boolean = false /** - * Set the frequency of the currently active VFO (CMD 0x25 sub 0x00). + * Set the frequency of the currently active VFO (IC-705: CMD 0x25 sub 0x00). * Default: delegates to [setFrequency]. */ suspend fun setWorkingFrequency(frequencyHz: Long): Boolean = setFrequency(frequencyHz) /** - * Set the frequency of the inactive (TX) VFO via CMD 0x25 sub 0x01. - * Used in split mode when PTT is pressed: the radio has made VFO-B - * the active VFO, so sub 0x01 targets it directly. + * Set the frequency of the inactive/TX VFO (IC-705: CMD 0x25 sub 0x01). + * Sent every tracking cycle alongside [setWorkingFrequency] in split mode. * Default: delegates to [setWorkingFrequency]. */ suspend fun setTxVfoFrequency(frequencyHz: Long): Boolean = setWorkingFrequency(frequencyHz)