From 2a001f491d8cab387c3b78be1666acd14c1b250c Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 31 Jul 2020 09:20:55 +0100 Subject: [PATCH] Simplify the CTCSS and Noise Squelch decoders and logic. --- FM.cpp | 69 +++++++++++++++++++++------------------------- FMCTCSSRX.cpp | 26 +++++++---------- FMCTCSSRX.h | 13 ++------- FMNoiseSquelch.cpp | 30 ++++++++------------ FMNoiseSquelch.h | 13 ++------- SerialPort.cpp | 2 +- 6 files changed, 58 insertions(+), 95 deletions(-) diff --git a/FM.cpp b/FM.cpp index 52aa742..787206b 100644 --- a/FM.cpp +++ b/FM.cpp @@ -89,10 +89,8 @@ void CFM::samples(bool cos, q15_t* samples, uint8_t length) // ARMv7-M has hardware integer division q15_t currentRFSample = q15_t((q31_t(samples[i]) << 8) / m_rxLevel); - if (m_noiseSquelch) { - uint8_t squelchState = m_squelch.process(currentRFSample); - cos = NSQ_VALID(squelchState); - } + if (m_noiseSquelch) + cos = m_squelch.process(currentRFSample); q15_t currentExtSample; bool inputExt = m_inputExtRB.getSample(currentExtSample);//always consume the external input data so it does not overflow @@ -107,55 +105,50 @@ void CFM::samples(bool cos, q15_t* samples, uint8_t length) break; case 1U: { - uint8_t ctcssState = m_ctcssRX.process(currentRFSample); + bool ctcss = m_ctcssRX.process(currentRFSample); // Delay the audio by 100ms to better match the CTCSS detector output m_inputRFRB.put(currentRFSample); m_inputRFRB.get(currentRFSample); - if (!inputExt && CTCSS_NOT_READY(ctcssState) && m_modemState != STATE_FM) { - // Not enough samples to determine if you have CTCSS, just carry on + if (!inputExt && !ctcss && m_modemState != STATE_FM) { + // No CTCSS detected, just carry on continue; - } else if ((inputExt || CTCSS_READY(ctcssState)) && m_modemState != STATE_FM) { - // We had enough samples for CTCSS and we are in some other mode than FM - bool validCTCSS = CTCSS_VALID(ctcssState); - stateMachine(validCTCSS, inputExt); - if (m_state == FS_LISTENING) - continue; - } else { - bool validCTCSS = CTCSS_VALID(ctcssState); - stateMachine(validCTCSS, inputExt); - } - } - break; - - case 2U: { - uint8_t ctcssState = m_ctcssRX.process(currentRFSample); - if (!inputExt && CTCSS_NOT_READY(ctcssState) && m_modemState != STATE_FM) { - // Not enough samples to determine if you have CTCSS, just carry on - continue; - } else if ((inputExt || CTCSS_READY(ctcssState)) && m_modemState != STATE_FM) { - // We had enough samples for CTCSS and we are in some other mode than FM - bool validCTCSS = CTCSS_VALID(ctcssState); - stateMachine(validCTCSS && cos, inputExt); + } else if ((inputExt || ctcss) && m_modemState != STATE_FM) { + // We had CTCSS or external input + stateMachine(ctcss, inputExt); if (m_state == FS_LISTENING) continue; } else { - bool validCTCSS = CTCSS_VALID(ctcssState); - stateMachine(validCTCSS && cos, inputExt); + stateMachine(ctcss, inputExt); + } + } + break; + + case 2U: { + bool ctcss = m_ctcssRX.process(currentRFSample); + if (!inputExt && !ctcss && m_modemState != STATE_FM) { + // No CTCSS detected, just carry on + continue; + } else if ((inputExt || (ctcss && cos)) && m_modemState != STATE_FM) { + // We had CTCSS or external input + stateMachine(ctcss && cos, inputExt); + if (m_state == FS_LISTENING) + continue; + } else { + stateMachine(ctcss && cos, inputExt); } } break; default: { - uint8_t ctcssState = m_ctcssRX.process(currentRFSample); - if (!inputExt && CTCSS_NOT_READY(ctcssState) && m_modemState != STATE_FM) { - // Not enough samples to determine if you have CTCSS, just carry on + bool ctcss = m_ctcssRX.process(currentRFSample); + if (!inputExt && !ctcss && m_modemState != STATE_FM) { + // No CTCSS detected, just carry on continue; - } else if ((inputExt || CTCSS_READY(ctcssState)) && m_modemState != STATE_FM) { - // We had enough samples for CTCSS and we are in some other mode than FM - bool validCTCSS = CTCSS_VALID(ctcssState); - stateMachine(validCTCSS && cos, inputExt); + } else if ((inputExt || (ctcss && cos)) && m_modemState != STATE_FM) { + // We had CTCSS or external input + stateMachine(ctcss && cos, inputExt); if (m_state == FS_LISTENING) continue; } else { diff --git a/FMCTCSSRX.cpp b/FMCTCSSRX.cpp index e88ff98..b2ecb43 100644 --- a/FMCTCSSRX.cpp +++ b/FMCTCSSRX.cpp @@ -87,7 +87,7 @@ m_lowThreshold(0), m_count(0U), m_q0(0), m_q1(0), -m_result(CTS_NONE) +m_state(false) { } @@ -111,13 +111,11 @@ uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t highThreshold, uint8_t return 0U; } -uint8_t CFMCTCSSRX::process(q15_t sample) +bool CFMCTCSSRX::process(q15_t sample) { //get more dynamic into the decoder by multiplying the sample by 1.5 q31_t sample31 = q31_t(sample) + (q31_t(sample) >> 1); - m_result &= ~CTS_READY; - q31_t q2 = m_q1; m_q1 = m_q0; @@ -149,33 +147,29 @@ uint8_t CFMCTCSSRX::process(q15_t sample) // value = m_q0 * m_q0 + m_q1 * m_q1 - m_q0 * m_q1 * m_coeffDivTwo * 2 q31_t value = t2 + t4 - t9; - bool previousCTCSSValid = CTCSS_VALID(m_result); + bool previousState = m_state; q31_t threshold = m_highThreshold; - if (previousCTCSSValid) + if (previousState) threshold = m_lowThreshold; - m_result |= CTS_READY; - if (value >= threshold) - m_result |= CTS_VALID; - else - m_result &= ~CTS_VALID; + m_state = value >= threshold; - if (previousCTCSSValid != CTCSS_VALID(m_result)) - DEBUG4("CTCSS Value / Threshold / Valid", value, threshold, CTCSS_VALID(m_result)); + if (previousState != m_state) + DEBUG4("CTCSS Value / Threshold / Valid", value, threshold, m_state); m_count = 0U; m_q0 = 0; m_q1 = 0; } - return m_result; + return m_state; } void CFMCTCSSRX::reset() { m_q0 = 0; m_q1 = 0; - m_result = CTS_NONE; - m_count = 0U; + m_state = false; + m_count = 0U; } diff --git a/FMCTCSSRX.h b/FMCTCSSRX.h index eed82de..0980c4c 100644 --- a/FMCTCSSRX.h +++ b/FMCTCSSRX.h @@ -21,22 +21,13 @@ #include "Config.h" -const uint8_t CTS_NONE = 0U; -const uint8_t CTS_READY = 1U; -const uint8_t CTS_VALID = 2U; - -#define CTCSS_READY(a) ((a & CTS_READY) != 0) -#define CTCSS_NOT_READY(a) ((a & CTS_READY) == 0) -#define CTCSS_VALID(a) ((a & CTS_VALID) != 0) -#define CTCSS_NOT_VALID(a) ((a & CTS_VALID) == 0) - class CFMCTCSSRX { public: CFMCTCSSRX(); uint8_t setParams(uint8_t frequency, uint8_t highThreshold, uint8_t lowThreshold); - uint8_t process(q15_t sample); + bool process(q15_t sample); void reset(); @@ -47,7 +38,7 @@ private: uint16_t m_count; q31_t m_q0; q31_t m_q1; - uint8_t m_result; + bool m_state; }; #endif diff --git a/FMNoiseSquelch.cpp b/FMNoiseSquelch.cpp index 06bbccb..3f94cfd 100644 --- a/FMNoiseSquelch.cpp +++ b/FMNoiseSquelch.cpp @@ -32,23 +32,21 @@ m_lowThreshold(0), m_count(0U), m_q0(0), m_q1(0), -m_result(NS_NONE) +m_state(false) { } void CFMNoiseSquelch::setParams(uint8_t highThreshold, uint8_t lowThreshold) { - m_highThreshold = q31_t(highThreshold); - m_lowThreshold = q31_t(lowThreshold); + m_highThreshold = q31_t(highThreshold) * 20; + m_lowThreshold = q31_t(lowThreshold) * 20; } -uint8_t CFMNoiseSquelch::process(q15_t sample) +bool CFMNoiseSquelch::process(q15_t sample) { //get more dynamic into the decoder by multiplying the sample by 1.5 q31_t sample31 = q31_t(sample) + (q31_t(sample) >> 1); - m_result &= ~NS_READY; - q31_t q2 = m_q1; m_q1 = m_q0; @@ -80,33 +78,29 @@ uint8_t CFMNoiseSquelch::process(q15_t sample) // value = m_q0 * m_q0 + m_q1 * m_q1 - m_q0 * m_q1 * m_coeffDivTwo * 2 q31_t value = t2 + t4 - t9; - bool previousNSQValid = NSQ_VALID(m_result); + bool previousState = m_state; q31_t threshold = m_highThreshold; - if (previousNSQValid) + if (previousState) threshold = m_lowThreshold; - m_result |= NS_READY; - if (value < threshold) - m_result |= NS_VALID; - else - m_result &= ~NS_VALID; + m_state = value < threshold; - if (previousNSQValid != NSQ_VALID(m_result)) - DEBUG4("Noise Squelch Value / Threshold / Valid", value, threshold, NSQ_VALID(m_result)); + if (previousState != m_state) + DEBUG4("Noise Squelch Value / Threshold / Valid", value, threshold, m_state); m_count = 0U; m_q0 = 0; m_q1 = 0; } - return m_result; + return m_state; } void CFMNoiseSquelch::reset() { m_q0 = 0; m_q1 = 0; - m_result = NS_NONE; - m_count = 0U; + m_state = false; + m_count = 0U; } diff --git a/FMNoiseSquelch.h b/FMNoiseSquelch.h index a17f7a2..57ee5eb 100644 --- a/FMNoiseSquelch.h +++ b/FMNoiseSquelch.h @@ -21,22 +21,13 @@ #include "Config.h" -const uint8_t NS_NONE = 0U; -const uint8_t NS_READY = 1U; -const uint8_t NS_VALID = 2U; - -#define NSQ_READY(a) ((a & NS_READY) != 0) -#define NSQ_NOT_READY(a) ((a & NS_READY) == 0) -#define NSQ_VALID(a) ((a & NS_VALID) != 0) -#define NSQ_NOT_VALID(a) ((a & NS_VALID) == 0) - class CFMNoiseSquelch { public: CFMNoiseSquelch(); void setParams(uint8_t highThreshold, uint8_t lowThreshold); - uint8_t process(q15_t sample); + bool process(q15_t sample); void reset(); @@ -46,7 +37,7 @@ private: uint16_t m_count; q31_t m_q0; q31_t m_q1; - uint8_t m_result; + bool m_state; }; #endif diff --git a/SerialPort.cpp b/SerialPort.cpp index 0b9111c..1314f56 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -109,7 +109,7 @@ const uint8_t MMDVM_DEBUG5 = 0xF5U; #define HW_TYPE "MMDVM" #endif -#define DESCRIPTION "20200728 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM/AX.25)" +#define DESCRIPTION "20200731 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM/AX.25)" #if defined(GITVERSION) #define concat(h, a, b, c) h " " a " " b " GitID #" c ""