Fix bugs in setting the Tx frequency

Uses 0x25 01 command to set the Tx frequency,
which is the correct command when in split mode.
This commit is contained in:
Rui Oliveira committed 2026-07-24 20:09:01 +01:00
1 parent dc596b4348
commit 58fb688593
4 files changed
+39 -10

No files matched your search

@@ -204,12 +204,23 @@ class Ic705Controller(
* always writing to the active VFO is the correct strategy. * always writing to the active VFO is the correct strategy.
*/ */
override suspend fun setWorkingFrequency(frequencyHz: Long): Boolean = withContext(Dispatchers.IO) { override suspend fun setWorkingFrequency(frequencyHz: Long): Boolean = withContext(Dispatchers.IO) {
Log.d(tag, "setWorkingFrequency: ${frequencyHz}Hz") Log.d(tag, "setWorkingFrequency (0x25/00): ${frequencyHz}Hz")
val cmd = IcomCivProtocol.buildSetWorkingFreqCommand(frequencyHz) val cmd = IcomCivProtocol.buildSetWorkingFreqCommand(frequencyHz)
Log.d(tag, "CMD setWorkingFreq → ${IcomCivProtocol.toHex(cmd)}") Log.d(tag, "CMD setWorkingFreq → ${IcomCivProtocol.toHex(cmd)}")
ioMutex.withLock { sendAndWaitAck(cmd) } ioMutex.withLock { sendAndWaitAck(cmd) }
} }
/**
* Set TX VFO frequency via CMD 0x25 sub 0x01 (unselected VFO).
* Used in split mode while PTT is pressed.
*/
override suspend fun setTxVfoFrequency(frequencyHz: Long): Boolean = withContext(Dispatchers.IO) {
Log.d(tag, "setTxVfoFrequency (0x25/01): ${frequencyHz}Hz")
val cmd = IcomCivProtocol.buildSetUnselectedVfoFreqCommand(frequencyHz)
Log.d(tag, "CMD setTxVfoFreq → ${IcomCivProtocol.toHex(cmd)}")
ioMutex.withLock { sendAndWaitAck(cmd) }
}
// ── Internal I/O helpers ──────────────────────────────────────────────── // ── Internal I/O helpers ────────────────────────────────────────────────
/** /**
@@ -73,8 +73,10 @@ object IcomCivProtocol {
const val SUB_SPLIT_ON: Byte = 0x01 const val SUB_SPLIT_ON: Byte = 0x01
/** Sub for CMD_TX_STATUS: query TX/RX state. */ /** Sub for CMD_TX_STATUS: query TX/RX state. */
const val SUB_TX_STATE: Byte = 0x00 const val SUB_TX_STATE: Byte = 0x00
/** Sub for CMD_SELECTED_VFO_FREQ: selected VFO frequency. */ /** Sub for CMD_SELECTED_VFO_FREQ: selected (active) VFO frequency. */
const val SUB_SELECTED_VFO: Byte = 0x00 const val SUB_SELECTED_VFO: Byte = 0x00
/** Sub for CMD_SELECTED_VFO_FREQ: unselected (inactive / TX in split) VFO frequency. */
const val SUB_UNSELECTED_VFO: Byte = 0x01
/** Sub for CMD_MISC_SETTING: CTCSS/DTCS tone squelch. */ /** Sub for CMD_MISC_SETTING: CTCSS/DTCS tone squelch. */
const val SUB_CTCSS_SETTING: Byte = 0x42.toByte() const val SUB_CTCSS_SETTING: Byte = 0x42.toByte()
@@ -167,6 +169,16 @@ object IcomCivProtocol {
return frame(CMD_SELECTED_VFO_FREQ, SUB_SELECTED_VFO, *encodeFrequencyBcd(frequencyHz)) return frame(CMD_SELECTED_VFO_FREQ, SUB_SELECTED_VFO, *encodeFrequencyBcd(frequencyHz))
} }
/**
* Set unselected-VFO frequency via CMD 0x25 sub 0x01.
* In split mode while PTT is pressed the IC-705 makes VFO-B active, so
* this command targets VFO-A (the RX VFO) — and vice-versa when in RX.
* Use this to update the TX VFO when PTT is on.
*/
fun buildSetUnselectedVfoFreqCommand(frequencyHz: Long): ByteArray {
return frame(CMD_SELECTED_VFO_FREQ, SUB_UNSELECTED_VFO, *encodeFrequencyBcd(frequencyHz))
}
/** Read operating frequency (CMD 0x03). */ /** Read operating frequency (CMD 0x03). */
fun buildReadFreqCommand(): ByteArray = frame(CMD_READ_FREQ) fun buildReadFreqCommand(): ByteArray = frame(CMD_READ_FREQ)
@@ -387,17 +387,17 @@ class RadioTrackingService(
when (isPtt) { when (isPtt) {
true -> { true -> {
// PTT ON → radio's active VFO is VFO-B (TX) // PTT ON → radio's active VFO is VFO-B (TX)
// Update TX frequency on active VFO only // Use 0x25/01 (unselected VFO) to target VFO-B directly
if (txRadioFreq != null) { if (txRadioFreq != null) {
Log.d(tag, "Split loop TX update: ${txRadioFreq}Hz") Log.d(tag, "Split loop TX update (0x25/01): ${txRadioFreq}Hz")
radio.setWorkingFrequency(txRadioFreq) radio.setTxVfoFrequency(txRadioFreq)
} }
} }
false -> { false -> {
// PTT OFF → radio's active VFO is VFO-A (RX) // PTT OFF → radio's active VFO is VFO-A (RX)
// Update RX frequency on active VFO only // Use 0x25/00 (selected/active VFO) to update RX
if (rxRadioFreq != null) { if (rxRadioFreq != null) {
Log.d(tag, "Split loop RX update: ${rxRadioFreq}Hz") Log.d(tag, "Split loop RX update (0x25/00): ${rxRadioFreq}Hz")
radio.setWorkingFrequency(rxRadioFreq) radio.setWorkingFrequency(rxRadioFreq)
} }
} }
@@ -62,10 +62,16 @@ interface IRadioController {
suspend fun setSplitMode(enabled: Boolean): Boolean = false suspend fun setSplitMode(enabled: Boolean): Boolean = false
/** /**
* Set the frequency of the currently active VFO. * Set the frequency of the currently active VFO (CMD 0x25 sub 0x00).
* On radios that support it (IC-705: CMD 0x25 sub 0x00) this updates
* the active VFO without switching.
* Default: delegates to [setFrequency]. * Default: delegates to [setFrequency].
*/ */
suspend fun setWorkingFrequency(frequencyHz: Long): Boolean = setFrequency(frequencyHz) 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.
* Default: delegates to [setWorkingFrequency].
*/
suspend fun setTxVfoFrequency(frequencyHz: Long): Boolean = setWorkingFrequency(frequencyHz)
} }