From a1794b44eddbc5387bb1dd5495be5ff2a4aaa3c4 Mon Sep 17 00:00:00 2001 From: Clint Chance Date: Sun, 12 Jul 2026 16:42:47 -0500 Subject: [PATCH 1/5] Fix RX interrupt flag being cleared on the wrong USART in STMUART. handleIRQ() hardcoded USART1 when clearing the RXNE pending bit, so on boards where the repeater/display UART is not USART1 (Nucleo, Discovery, F767, UART5-based boards) the flag was cleared on the wrong peripheral. Use the m_usart member, matching the TXE handling below. Also fix flush(): it passed a flag constant to USART_GetITStatus and span while TXE was set, which returns immediately since TXE indicates the data register is already empty. Wait for the software TX FIFO to drain and then for the TC flag, which indicates the shift register has actually emptied. --- STMUART.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/STMUART.cpp b/STMUART.cpp index c2e779d..8742dc5 100644 --- a/STMUART.cpp +++ b/STMUART.cpp @@ -61,7 +61,7 @@ void CSTMUART::handleIRQ() if (USART_GetITStatus(m_usart, USART_IT_RXNE)) { if(!m_rxFifo.isFull()) m_rxFifo.put((uint8_t) USART_ReceiveData(m_usart)); - USART_ClearITPendingBit(USART1, USART_IT_RXNE); + USART_ClearITPendingBit(m_usart, USART_IT_RXNE); } if (USART_GetITStatus(m_usart, USART_IT_TXE)) { @@ -82,8 +82,12 @@ void CSTMUART::flush() if(m_usart == NULL) return; - // wait until the TXE shows the shift register is empty - while (USART_GetITStatus(m_usart, USART_FLAG_TXE)) + // wait until the TX FIFO has drained + while (!m_txFifo.isEmpty()) + ; + + // wait until the TC flag shows the shift register is empty + while (USART_GetFlagStatus(m_usart, USART_FLAG_TC) == RESET) ; } From 2eb6f7fd06c4f952ff906cbabae8e07e7b098737 Mon Sep 17 00:00:00 2001 From: Clint Chance Date: Sun, 12 Jul 2026 16:42:58 -0500 Subject: [PATCH 2/5] Initialise and reset the FM noise squelch invalid counter. m_invalidCount was missing from the constructor initialiser list and was read uninitialised in process(), making the squelch behaviour after power-up indeterminate. reset() also cleared neither hysteresis counter, so state leaked across squelch resets. --- FMNoiseSquelch.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/FMNoiseSquelch.cpp b/FMNoiseSquelch.cpp index bd01fe9..dd99cf5 100644 --- a/FMNoiseSquelch.cpp +++ b/FMNoiseSquelch.cpp @@ -36,7 +36,8 @@ m_count(0U), m_q0(0), m_q1(0), m_state(false), -m_validCount(0U) +m_validCount(0U), +m_invalidCount(0U) { } @@ -127,6 +128,8 @@ void CFMNoiseSquelch::reset() m_q1 = 0; m_state = false; m_count = 0U; + m_validCount = 0U; + m_invalidCount = 0U; } #endif From 90220cbb9d282fb716188a58ecd0645de88f6c82 Mon Sep 17 00:00:00 2001 From: Clint Chance Date: Sun, 12 Jul 2026 16:42:58 -0500 Subject: [PATCH 3/5] Fix the FM mode LED pin guard on the Arduino Due. The pinMode() call for PIN_FM was guarded by USE_ALTERNATE_POCSAG_LEDS instead of USE_ALTERNATE_FM_LEDS, a copy and paste error. The Teensy version and the setFMInt() implementation in this file both use the FM macro. --- IODue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IODue.cpp b/IODue.cpp index e77c388..8b5655f 100644 --- a/IODue.cpp +++ b/IODue.cpp @@ -110,7 +110,7 @@ void CIO::initInt() #if !defined(USE_ALTERNATE_POCSAG_LEDS) pinMode(PIN_POCSAG, OUTPUT); #endif -#if !defined(USE_ALTERNATE_POCSAG_LEDS) +#if !defined(USE_ALTERNATE_FM_LEDS) pinMode(PIN_FM, OUTPUT); #endif #endif From 96061a60131298516335372c2bce02201cef46a2 Mon Sep 17 00:00:00 2001 From: Clint Chance Date: Sun, 12 Jul 2026 16:45:24 -0500 Subject: [PATCH 4/5] Make DMR trunking state handling order-independent. The CSBK slot type was only encoded into the ALOHA frame inside setColorCode(), so it took effect only if a reconfigure happened after an ALOHA frame had already been received; on the usual command ordering (SET_CONFIG then ALOHA) the transmitted slot type depended entirely on the host-supplied bytes. Remember the colour code and stamp the slot type in writeAloha() as well. Also clear m_controlChannel when trunking is disabled, so the host has a way to stop control channel transmission other than rebooting, and fix a stray tab introduced in createCACH(). --- DMRTX.cpp | 16 ++++++++++++++-- DMRTX.h | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/DMRTX.cpp b/DMRTX.cpp index af634ea..fbc23ff 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -84,7 +84,8 @@ m_frameCount(0U), m_abortCount(), m_abort(), m_controlChannel(false), -m_trunking(false) +m_trunking(false), +m_colorCode(0U) { ::memset(m_modState, 0x00U, 16U * sizeof(q15_t)); @@ -227,6 +228,12 @@ uint8_t CDMRTX::writeAloha(const uint8_t* data, uint16_t length) return 4U; ::memcpy(m_aloha, data, length); + + // Stamp the slot type with the current colour code so that the result + // doesn't depend on the ordering of the ALOHA and SET_CONFIG commands. + CDMRSlotType slotType; + slotType.encode(m_colorCode, DT_CSBK, m_aloha); + m_controlChannel = true; return 0U; @@ -386,7 +393,7 @@ void CDMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex) ::memcpy(m_shortLC, EMPTY_SHORT_LC, 12U); } else { ::memcpy(m_shortLC, m_newShortLC, 12U); - } + } } ::memcpy(m_poBuffer, m_shortLC + m_cachPtr, 3U); @@ -426,6 +433,8 @@ void CDMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex) void CDMRTX::setColorCode(uint8_t colorCode) { + m_colorCode = colorCode; + if (m_trunking) ::memcpy(m_idle, TERMINATOR_DATA, DMR_FRAME_LENGTH_BYTES); else @@ -458,6 +467,9 @@ uint32_t CDMRTX::getFrameCount() void CDMRTX::setTrunking(bool trunking) { m_trunking = trunking; + + if (!trunking) + m_controlChannel = false; } #endif diff --git a/DMRTX.h b/DMRTX.h index b58b87c..ba2ef65 100644 --- a/DMRTX.h +++ b/DMRTX.h @@ -83,6 +83,7 @@ private: bool m_abort[2U]; bool m_controlChannel; bool m_trunking; + uint8_t m_colorCode; void createData(uint8_t slotIndex); void createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex); From 68252f15f545787f91f389ecf7372d0a587db516 Mon Sep 17 00:00:00 2001 From: Clint Chance Date: Sun, 12 Jul 2026 16:45:24 -0500 Subject: [PATCH 5/5] Fix the FM 25kHz calibration debug message. It said 10kHz, a copy and paste from the case above. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 7c6eb0c..220af49 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -745,7 +745,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState) DEBUG1("Mode set to FM 20Khz Calibrate"); break; case STATE_FMCAL25K: - DEBUG1("Mode set to FM 10Khz Calibrate"); + DEBUG1("Mode set to FM 25Khz Calibrate"); break; case STATE_FMCAL30K: DEBUG1("Mode set to FM 30Khz Calibrate");