diff --git a/FM.cpp b/FM.cpp index ee219ae..466a281 100644 --- a/FM.cpp +++ b/FM.cpp @@ -35,3 +35,15 @@ void CFM::process() void CFM::reset() { } + +void CFM::setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callAtStart, bool callAtEnd) +{ +} + +void CFM::setAck(const char* ack, uint8_t speed, uint16_t frequency, uint16_t delay, uint8_t level) +{ +} + +void CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime) +{ +} diff --git a/FM.h b/FM.h index ca62586..a315869 100644 --- a/FM.h +++ b/FM.h @@ -31,6 +31,10 @@ public: void reset(); + void setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callAtStart, bool callAtEnd); + void setAck(const char* ack, uint8_t speed, uint16_t frequency, uint16_t delay, uint8_t level); + void setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime); + private: }; diff --git a/IO.cpp b/IO.cpp index 8f3e54e..94b0cbb 100644 --- a/IO.cpp +++ b/IO.cpp @@ -80,6 +80,8 @@ m_ysfTXLevel(128 * 128), m_p25TXLevel(128 * 128), m_nxdnTXLevel(128 * 128), m_pocsagTXLevel(128 * 128), +m_fmRXLevel(128 * 128), +m_fmTXLevel(128 * 128), m_rxDCOffset(DC_OFFSET), m_txDCOffset(DC_OFFSET), m_ledCount(0U), @@ -144,6 +146,7 @@ void CIO::selfTest() setP25Int(ledValue); setNXDNInt(ledValue); setPOCSAGInt(ledValue); + setFMInt(ledValue); #endif delayInt(250); } @@ -155,105 +158,46 @@ void CIO::selfTest() setP25Int(false); setNXDNInt(false); setPOCSAGInt(false); + setFMInt(false); delayInt(250); - - setDStarInt(true); setDMRInt(true); - setYSFInt(false); - setP25Int(false); - setNXDNInt(false); - setPOCSAGInt(false); delayInt(250); - - setDStarInt(true); - setDMRInt(true); setYSFInt(true); - setP25Int(false); - setNXDNInt(false); - setPOCSAGInt(false); - - delayInt(250); - setDStarInt(true); - setDMRInt(true); - setYSFInt(true); + delayInt(250); setP25Int(true); - setNXDNInt(false); - setPOCSAGInt(false); - - delayInt(250); - setDStarInt(true); - setDMRInt(true); - setYSFInt(true); - setP25Int(true); + delayInt(250); setNXDNInt(true); - setPOCSAGInt(false); - - delayInt(250); - setDStarInt(true); - setDMRInt(true); - setYSFInt(true); - setP25Int(true); - setNXDNInt(true); + delayInt(250); setPOCSAGInt(true); - - delayInt(250); - setDStarInt(true); - setDMRInt(true); - setYSFInt(true); - setP25Int(true); - setNXDNInt(true); + delayInt(250); + setFMInt(true); + + delayInt(250); + setFMInt(false); + + delayInt(250); setPOCSAGInt(false); - - delayInt(250); - setDStarInt(true); - setDMRInt(true); - setYSFInt(true); - setP25Int(true); + delayInt(250); setNXDNInt(false); - setPOCSAGInt(false); delayInt(250); - - setDStarInt(true); - setDMRInt(true); - setYSFInt(true); setP25Int(false); - setNXDNInt(false); - setPOCSAGInt(false); delayInt(250); - - setDStarInt(true); - setDMRInt(true); setYSFInt(false); - setP25Int(false); - setNXDNInt(false); - setPOCSAGInt(false); delayInt(250); - - setDStarInt(true); setDMRInt(false); - setYSFInt(false); - setP25Int(false); - setNXDNInt(false); - setPOCSAGInt(false); delayInt(250); - setDStarInt(false); - setDMRInt(false); - setYSFInt(false); - setP25Int(false); - setNXDNInt(false); - setPOCSAGInt(false); #endif } @@ -405,11 +349,19 @@ void CIO::process() if (m_fmEnable) { bool cos = getCOSInt(); + q15_t FMVals[RX_BLOCK_SIZE]; #if defined(USE_DCBLOCKER) - fm.samples(cos, dcSamples, RX_BLOCK_SIZE); + for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) { + q31_t res1 = dcSamples[i] * m_fmRXLevel; + FMVals[i] = q15_t(__SSAT((res1 >> 15), 16)); + } #else - fm.samples(cos, samples, RX_BLOCK_SIZE); + for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) { + q31_t res1 = samples[i] * m_fmRXLevel; + FMVals[i] = q15_t(__SSAT((res1 >> 15), 16)); + } #endif + fm.samples(cos, FMVals, RX_BLOCK_SIZE); } } else if (m_modemState == STATE_DSTAR) { if (m_dstarEnable) { @@ -471,11 +423,19 @@ void CIO::process() } } else if (m_modemState == STATE_FM) { bool cos = getCOSInt(); + q15_t FMVals[RX_BLOCK_SIZE]; #if defined(USE_DCBLOCKER) - fm.samples(cos, dcSamples, RX_BLOCK_SIZE); + for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) { + q31_t res1 = dcSamples[i] * m_fmRXLevel; + FMVals[i] = q15_t(__SSAT((res1 >> 15), 16)); + } #else - fm.samples(cos, samples, RX_BLOCK_SIZE); + for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) { + q31_t res1 = samples[i] * m_fmRXLevel; + FMVals[i] = q15_t(__SSAT((res1 >> 15), 16)); + } #endif + fm.samples(cos, FMVals, RX_BLOCK_SIZE); } else if (m_modemState == STATE_DSTARCAL) { q15_t GMSKVals[RX_BLOCK_SIZE]; ::arm_fir_fast_q15(&m_gaussianFilter, samples, GMSKVals, RX_BLOCK_SIZE); @@ -576,7 +536,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 fmRXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset) { m_pttInvert = pttInvert; @@ -588,6 +548,7 @@ void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rx m_p25TXLevel = q15_t(p25TXLevel * 128); m_nxdnTXLevel = q15_t(nxdnTXLevel * 128); m_pocsagTXLevel = q15_t(pocsagTXLevel * 128); + m_fmRXLevel = q15_t(fmRXLevel * 128); m_fmTXLevel = q15_t(fmTXLevel * 128); m_rxDCOffset = DC_OFFSET + rxDCOffset; diff --git a/IO.h b/IO.h index 21eccc0..1fea082 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 fmRXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset); void getOverflow(bool& adcOverflow, bool& dacOverflow); @@ -86,6 +86,7 @@ private: q15_t m_p25TXLevel; q15_t m_nxdnTXLevel; q15_t m_pocsagTXLevel; + q15_t m_fmRXLevel; q15_t m_fmTXLevel; uint16_t m_rxDCOffset; diff --git a/SerialPort.cpp b/SerialPort.cpp index 5a737fc..872657a 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -262,7 +262,7 @@ void CSerialPort::getVersion() uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) { - if (length < 18U) + if (length < 20U) return 4U; bool rxInvert = (data[0U] & 0x01U) == 0x01U; @@ -327,6 +327,9 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) uint8_t pocsagTXLevel = data[17U]; + uint8_t fmTXLevel = data[18U]; + uint8_t fmRXLevel = data[19U]; + m_modemState = modemState; m_dstarEnable = dstarEnable; @@ -353,7 +356,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) ysfTX.setParams(ysfLoDev, ysfTXHang); - io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel, txDCOffset, rxDCOffset); + io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel, fmTXLevel, fmRXLevel, txDCOffset, rxDCOffset); io.start(); @@ -375,12 +378,14 @@ uint8_t CSerialPort::setFMParams1(const uint8_t* data, uint8_t length) bool callAtStart = (data[6U] & 0x01U) == 0x01U; bool callAtEnd = (data[6U] & 0x02U) == 0x02U; - char callsign; + char callsign[50U]; uint8_t n = 0U; for (uint8_t i = 7U; i < length; i++, n++) callsign[n] = data[i]; callsign[n] = '\0'; + fm.setCallsign(callsign, speed, frequency, time, holdoff, highLevel, lowLevel, callAtStart, callAtEnd); + return 0U; } @@ -391,21 +396,23 @@ uint8_t CSerialPort::setFMParams2(const uint8_t* data, uint8_t length) uint8_t speed = data[0U]; uint16_t frequency = data[1U] * 10U; - uint8_t delay = data[2U] * 10U; + uint16_t delay = data[2U] * 10U; uint8_t level = data[3U]; - char ack; + char ack[50U]; uint8_t n = 0U; for (uint8_t i = 4U; i < length; i++, n++) ack[n] = data[i]; ack[n] = '\0'; + fm.setAck(ack, speed, frequency, delay, level); + return 0U; } uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint8_t length) { - if (length < 9U) + if (length < 7U) return 4U; uint16_t timeout = data[0U] * 5U; @@ -415,10 +422,10 @@ uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint8_t length) uint8_t ctcssThreshold = data[3U]; uint8_t ctcssLevel = data[4U]; - uint8_t inputLevel = data[5U]; - uint8_t outputLevel = data[6U]; - uint8_t kerchunkTime = data[7U]; - uint8_t hangTime = data[8U]; + uint8_t kerchunkTime = data[5U]; + uint8_t hangTime = data[6U]; + + fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssThreshold, ctcssLevel, kerchunkTime, hangTime); return 0U; } @@ -529,6 +536,9 @@ void CSerialPort::setMode(MMDVM_STATE modemState) if (modemState != STATE_NXDN) nxdnRX.reset(); + if (modemState != STATE_FM) + fm.reset(); + cwIdTX.reset(); m_modemState = modemState;