diff --git a/Config.h b/Config.h index 73e716b..da79210 100644 --- a/Config.h +++ b/Config.h @@ -35,9 +35,6 @@ // For 19.2 MHz // #define EXTERNAL_OSC 19200000 -// Allow the use of the COS line to lockout the modem -// #define USE_COS_AS_LOCKOUT - // Use pins to output the current mode via LEDs // #define MODE_LEDS diff --git a/FM.cpp b/FM.cpp index 458fc28..e1d5f76 100644 --- a/FM.cpp +++ b/FM.cpp @@ -20,6 +20,14 @@ #include "Globals.h" #include "FM.h" +/* + * Access Mode values are: + * 0 - Carrier access with COS + * 1 - CTCSS only access without COS + * 2 - CTCSS only access with COS + * 3 - CTCSS only access with COS to start, then carrier access with COS + */ + CFM::CFM() : m_callsign(), m_rfAck(), @@ -41,7 +49,7 @@ m_filterStage1( 724, 1448, 724, 32768, -37895, 21352),//3rd order Cheby Fil m_filterStage2(32768, 0,-32768, 32768, -50339, 19052), m_filterStage3(32768, -65536, 32768, 32768, -64075, 31460), m_blanking(), -m_useCOS(true), +m_accessMode(1U), m_cosInvert(false), m_rfAudioBoost(1U), m_downsampler(128U),//Size might need adjustement @@ -54,12 +62,8 @@ m_outputRB(2400U) // 100ms of audio void CFM::samples(bool cos, const q15_t* samples, uint8_t length) { - if (m_useCOS) { - if (m_cosInvert) - cos = !cos; - } else { - cos = true; - } + if (m_cosInvert) + cos = !cos; clock(length); @@ -70,33 +74,48 @@ void CFM::samples(bool cos, const q15_t* samples, uint8_t length) uint8_t ctcssState = m_ctcssRX.process(currentSample); - if (!m_useCOS) { - // Delay the audio by 100ms to better match the CTCSS detector output - m_inputRB.put(currentSample); - m_inputRB.get(currentSample); + switch (m_accessMode) { + case 0U: + stateMachine(cos); + break; + + case 1U: + // Delay the audio by 100ms to better match the CTCSS detector output + m_inputRB.put(currentSample); + m_inputRB.get(currentSample); + + if (CTCSS_NOT_READY(ctcssState) && m_modemState != STATE_FM) { + // Not enough samples to determine if you have CTCSS, just carry on + } else { + bool validCTCSS = CTCSS_VALID(ctcssState); + stateMachine(validCTCSS); + } + break; + + case 2U: + if (CTCSS_NOT_READY(ctcssState) && m_modemState != STATE_FM) { + // Not enough samples to determine if you have CTCSS, just carry on + } else { + bool validCTCSS = CTCSS_VALID(ctcssState); + stateMachine(validCTCSS && cos); + } + break; + + default: + if (CTCSS_NOT_READY(ctcssState) && m_modemState != STATE_FM) { + // Not enough samples to determine if you have CTCSS, just carry on + } 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 && cos); + } else { + stateMachine(cos); + } + break; } - if (CTCSS_NOT_READY(ctcssState) && m_modemState != STATE_FM) { - //Not enough samples to determine if you have CTCSS, just carry on + 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 some other mode than FM - bool validCTCSS = CTCSS_VALID(ctcssState); - stateMachine(validCTCSS && cos); - 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 && cos); - 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 && cos); - } // Only let audio through when relaying audio if (m_state == FS_RELAYING || m_state == FS_KERCHUNK) { @@ -183,10 +202,10 @@ 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 ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel) +uint8_t CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, uint8_t accessMode, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel) { - m_useCOS = useCOS; - m_cosInvert = cosInvert; + m_accessMode = accessMode; + m_cosInvert = cosInvert; m_rfAudioBoost = q15_t(rfAudioBoost); diff --git a/FM.h b/FM.h index 6411585..3168dc3 100644 --- a/FM.h +++ b/FM.h @@ -56,7 +56,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, bool callsignAtLatch); 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 ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel); + uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, uint8_t accessMode, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel); private: CFMKeyer m_callsign; @@ -79,7 +79,7 @@ private: CFMDirectFormI m_filterStage2; CFMDirectFormI m_filterStage3; CFMBlanking m_blanking; - bool m_useCOS; + uint8_t m_accessMode; bool m_cosInvert; q15_t m_rfAudioBoost; CFMDownsampler m_downsampler; diff --git a/IO.cpp b/IO.cpp index a737693..c36b6a9 100644 --- a/IO.cpp +++ b/IO.cpp @@ -83,6 +83,7 @@ m_pocsagTXLevel(128 * 128), m_fmTXLevel(128 * 128), m_rxDCOffset(DC_OFFSET), m_txDCOffset(DC_OFFSET), +m_useCOSAsLockout(false), m_ledCount(0U), m_ledValue(true), m_detect(false), @@ -256,9 +257,8 @@ void CIO::process() return; } -#if defined(USE_COS_AS_LOCKOUT) - m_lockout = getCOSInt(); -#endif + if (m_useCOSAsLockout) + m_lockout = getCOSInt(); // Switch off the transmitter if needed if (m_txBuffer.getData() == 0U && m_tx) { @@ -529,7 +529,7 @@ void CIO::setMode() #endif } -void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset) +void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout) { m_pttInvert = pttInvert; @@ -545,6 +545,8 @@ void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rx m_rxDCOffset = DC_OFFSET + rxDCOffset; m_txDCOffset = DC_OFFSET + txDCOffset; + + m_useCOSAsLockout = useCOSAsLockout; if (rxInvert) m_rxLevel = -m_rxLevel; diff --git a/IO.h b/IO.h index 07ed700..4a8231f 100644 --- a/IO.h +++ b/IO.h @@ -42,7 +42,7 @@ public: void interrupt(); - void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset); + void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout); void getOverflow(bool& adcOverflow, bool& dacOverflow); @@ -91,6 +91,8 @@ private: uint16_t m_rxDCOffset; uint16_t m_txDCOffset; + bool m_useCOSAsLockout; + uint32_t m_ledCount; bool m_ledValue; diff --git a/SerialPort.cpp b/SerialPort.cpp index 4e22028..171f460 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -103,7 +103,7 @@ const uint8_t MMDVM_DEBUG5 = 0xF5U; #define HW_TYPE "MMDVM" #endif -#define DESCRIPTION "20200712 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM)" +#define DESCRIPTION "20200713 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM)" #if defined(GITVERSION) #define concat(h, a, b, c) h " " a " " b " GitID #" c "" @@ -267,11 +267,12 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) if (length < 21U) return 4U; - bool rxInvert = (data[0U] & 0x01U) == 0x01U; - bool txInvert = (data[0U] & 0x02U) == 0x02U; - bool pttInvert = (data[0U] & 0x04U) == 0x04U; - bool ysfLoDev = (data[0U] & 0x08U) == 0x08U; - bool simplex = (data[0U] & 0x80U) == 0x80U; + bool rxInvert = (data[0U] & 0x01U) == 0x01U; + bool txInvert = (data[0U] & 0x02U) == 0x02U; + bool pttInvert = (data[0U] & 0x04U) == 0x04U; + bool ysfLoDev = (data[0U] & 0x08U) == 0x08U; + bool useCOSAsLockout = (data[0U] & 0x20U) == 0x20U; + bool simplex = (data[0U] & 0x80U) == 0x80U; m_debug = (data[0U] & 0x10U) == 0x10U; @@ -363,7 +364,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) p25TX.setParams(p25TXHang); nxdnTX.setParams(nxdnTXHang); - io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel, fmTXLevel, txDCOffset, rxDCOffset); + io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel, fmTXLevel, txDCOffset, rxDCOffset, useCOSAsLockout); io.start(); @@ -431,14 +432,14 @@ uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint8_t length) uint8_t kerchunkTime = data[6U]; uint8_t hangTime = data[7U]; - bool useCOS = (data[8U] & 0x01U) == 0x01U; - bool cosInvert = (data[8U] & 0x02U) == 0x02U; + uint8_t accessMode = data[8U] & 0x7FU; + bool cosInvert = (data[8U] & 0x80U) == 0x80U; uint8_t rfAudioBoost = data[9U]; uint8_t maxDev = data[10U]; uint8_t rxLevel = data[11U]; - return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold, ctcssLevel, kerchunkTime, hangTime, useCOS, cosInvert, rfAudioBoost, maxDev, rxLevel); + return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold, ctcssLevel, kerchunkTime, hangTime, accessMode, cosInvert, rfAudioBoost, maxDev, rxLevel); } uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)