diff --git a/FM.cpp b/FM.cpp index de6338c..7f0beb0 100644 --- a/FM.cpp +++ b/FM.cpp @@ -38,14 +38,19 @@ m_ackDelayTimer(), m_hangTimer(), m_filterStage1( 724, 1448, 724, 32768, -37895, 21352), m_filterStage2(32768, 0,-32768, 32768, -50339, 19052), -m_filterStage3(32768, -65536, 32768, 32768, -64075, 31460) +m_filterStage3(32768, -65536, 32768, 32768, -64075, 31460), +m_useCOS(true), +m_rxBoost(1U) { } -void CFM::samples(q15_t* samples, uint8_t length) +void CFM::samples(bool cos, q15_t* samples, uint8_t length) { uint8_t i = 0; for (; i < length; i++) { + if (!m_useCOS) + cos = true; + q15_t currentSample = samples[i];//save to a local variable to avoid indirection on every access CTCSSState ctcssState = m_ctcssRX.process(currentSample); @@ -56,26 +61,28 @@ void CFM::samples(q15_t* samples, uint8_t length) } else if (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, i + 1U); + stateMachine(validCTCSS && cos, i + 1U); if (m_modemState != STATE_FM) continue; } else if (CTCSS_READY(ctcssState) && m_modemState == STATE_FM) { //We had enough samples for CTCSS and we are in FM mode, trigger the state machine bool validCTCSS = CTCSS_VALID(ctcssState); - stateMachine(validCTCSS, i + 1U); + stateMachine(validCTCSS && cos, i + 1U); if (m_modemState != STATE_FM) break; } else if (CTCSS_NOT_READY(ctcssState) && m_modemState == STATE_FM && i == length - 1) { //Not enough samples for CTCSS but we already are in FM, trigger the state machine //but do not trigger the state machine on every single sample, save CPU! bool validCTCSS = CTCSS_VALID(ctcssState); - stateMachine(validCTCSS, i + 1U); + stateMachine(validCTCSS && cos, i + 1U); } // Only let audio through when relaying audio if (m_state != FS_RELAYING && m_state != FS_KERCHUNK) currentSample = 0U; + currentSample *= m_rxBoost; + if (!m_callsign.isRunning()) currentSample += m_rfAck.getHighAudio(); @@ -134,8 +141,11 @@ uint8_t CFM::setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_ return m_rfAck.setParams(rfAck, speed, frequency, level, level); } -uint8_t CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime) +uint8_t CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, uint8_t rxBoost) { + m_useCOS = useCOS; + m_rxBoost = q15_t(rxBoost); + m_timeoutTimer.setTimeout(timeout, 0U); m_kerchunkTimer.setTimeout(kerchunkTime, 0U); m_hangTimer.setTimeout(hangTime, 0U); diff --git a/FM.h b/FM.h index 9bf4997..e451ed6 100644 --- a/FM.h +++ b/FM.h @@ -45,7 +45,7 @@ class CFM { public: CFM(); - void samples(q15_t* samples, uint8_t length); + void samples(bool cos, q15_t* samples, uint8_t length); void process(); @@ -53,7 +53,7 @@ public: uint8_t setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd); uint8_t setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level); - uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime); + uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, uint8_t rxBoost); private: CFMKeyer m_callsign; @@ -74,6 +74,8 @@ private: CFMDirectFormI m_filterStage1; CFMDirectFormI m_filterStage2; CFMDirectFormI m_filterStage3; + bool m_useCOS; + q15_t m_rxBoost; void stateMachine(bool validSignal, uint8_t length); void listeningState(bool validSignal); diff --git a/IO.cpp b/IO.cpp index b0622ba..a737693 100644 --- a/IO.cpp +++ b/IO.cpp @@ -357,10 +357,11 @@ void CIO::process() } if (m_fmEnable) { + bool cos = getCOSInt(); #if defined(USE_DCBLOCKER) - fm.samples(dcSamples, RX_BLOCK_SIZE); + fm.samples(cos, dcSamples, RX_BLOCK_SIZE); #else - fm.samples(samples, RX_BLOCK_SIZE); + fm.samples(cos, samples, RX_BLOCK_SIZE); #endif } } else if (m_modemState == STATE_DSTAR) { @@ -422,10 +423,11 @@ void CIO::process() nxdnRX.samples(NXDNVals, rssi, RX_BLOCK_SIZE); } } else if (m_modemState == STATE_FM) { + bool cos = getCOSInt(); #if defined(USE_DCBLOCKER) - fm.samples(dcSamples, RX_BLOCK_SIZE); + fm.samples(cos, dcSamples, RX_BLOCK_SIZE); #else - fm.samples(samples, RX_BLOCK_SIZE); + fm.samples(cos, samples, RX_BLOCK_SIZE); #endif } else if (m_modemState == STATE_DSTARCAL) { q15_t GMSKVals[RX_BLOCK_SIZE]; diff --git a/SerialPort.cpp b/SerialPort.cpp index c0f44c7..aa71f32 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -101,7 +101,7 @@ const uint8_t MMDVM_DEBUG5 = 0xF5U; #define HW_TYPE "MMDVM" #endif -#define DESCRIPTION "20200424 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM)" +#define DESCRIPTION "20200425 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM)" #if defined(GITVERSION) #define concat(h, a, b, c) h " " a " " b " GitID #" c "" @@ -408,7 +408,7 @@ uint8_t CSerialPort::setFMParams2(const uint8_t* data, uint8_t length) uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint8_t length) { - if (length < 7U) + if (length < 9U) return 4U; uint16_t timeout = data[0U] * 5U; @@ -421,7 +421,11 @@ uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint8_t length) uint8_t kerchunkTime = data[5U]; uint8_t hangTime = data[6U]; - return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssThreshold, ctcssLevel, kerchunkTime, hangTime); + bool useCOS = (data[7U] & 0x01U) == 0x01U; + + uint8_t rxBoost = data[8U]; + + return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssThreshold, ctcssLevel, kerchunkTime, hangTime, useCOS, rxBoost); } uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)