diff --git a/IO.cpp b/IO.cpp index 2aebcbb..4e2e86a 100644 --- a/IO.cpp +++ b/IO.cpp @@ -32,6 +32,12 @@ static q15_t RRC_0_2_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 147 -553, -847, -731, -340, 104, 401, 0}; const uint16_t RRC_0_2_FILTER_LEN = 42U; +// Generated using rcosdesign(0.5, 8, 5, 'sqrt') in MATLAB +static q15_t RRC_0_5_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, + 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, + -553, -847, -731, -340, 104, 401, 0}; +const uint16_t RRC_0_5_FILTER_LEN = 42U; + // Generated using rcosdesign(0.2, 8, 10, 'sqrt') in MATLAB static q15_t NXDN_0_2_FILTER[] = {284, 198, 73, -78, -240, -393, -517, -590, -599, -533, -391, -181, 79, 364, 643, 880, 1041, 1097, 1026, 819, 483, 39, -477, -1016, -1516, -1915, -2150, -2164, -1914, -1375, -545, 557, 1886, 3376, 4946, 6502, 7946, 9184, @@ -61,12 +67,14 @@ m_txBuffer(TX_RINGBUFFER_SIZE), m_rssiBuffer(RX_RINGBUFFER_SIZE), m_dcFilter(), m_dcState(), -m_rrcFilter(), +m_rrc02Filter(), +m_rrc05Filter(), m_gaussianFilter(), m_boxcarFilter(), m_nxdnFilter(), m_nxdnISincFilter(), -m_rrcState(), +m_rrc02State(), +m_rrc05State(), m_gaussianState(), m_boxcarState(), m_nxdnState(), @@ -93,7 +101,8 @@ m_dacOverflow(0U), m_watchdog(0U), m_lockout(false) { - ::memset(m_rrcState, 0x00U, 70U * sizeof(q15_t)); + ::memset(m_rrc02State, 0x00U, 70U * sizeof(q15_t)); + ::memset(m_rrc05State, 0x00U, 70U * sizeof(q15_t)); ::memset(m_gaussianState, 0x00U, 40U * sizeof(q15_t)); ::memset(m_boxcarState, 0x00U, 30U * sizeof(q15_t)); ::memset(m_nxdnState, 0x00U, 110U * sizeof(q15_t)); @@ -105,9 +114,13 @@ m_lockout(false) m_dcFilter.pCoeffs = DC_FILTER; m_dcFilter.postShift = 0; - m_rrcFilter.numTaps = RRC_0_2_FILTER_LEN; - m_rrcFilter.pState = m_rrcState; - m_rrcFilter.pCoeffs = RRC_0_2_FILTER; + m_rrc02Filter.numTaps = RRC_0_2_FILTER_LEN; + m_rrc02Filter.pState = m_rrc02State; + m_rrc02Filter.pCoeffs = RRC_0_2_FILTER; + + m_rrc05Filter.numTaps = RRC_0_5_FILTER_LEN; + m_rrc05Filter.pState = m_rrc05State; + m_rrc05Filter.pCoeffs = RRC_0_5_FILTER; m_gaussianFilter.numTaps = GAUSSIAN_0_5_FILTER_LEN; m_gaussianFilter.pState = m_gaussianState; @@ -370,22 +383,34 @@ void CIO::process() nxdnRX.samples(NXDNVals, rssi, RX_BLOCK_SIZE); } - if (m_dmrEnable || m_ysfEnable || m_m17Enable) { + if (m_dmrEnable) { + q15_t DMRVals[RX_BLOCK_SIZE]; + ::arm_fir_fast_q15(&m_rrc02Filter, samples, DMRVals, RX_BLOCK_SIZE); + + if (m_duplex) + dmrIdleRX.samples(DMRVals, RX_BLOCK_SIZE); + else + dmrDMORX.samples(DMRVals, rssi, RX_BLOCK_SIZE); + } + + if (m_ysfEnable) { + q15_t YSFVals[RX_BLOCK_SIZE]; +#if defined(USE_DCBLOCKER) + ::arm_fir_fast_q15(&m_rrc02Filter, dcSamples, YSFVals, RX_BLOCK_SIZE); +#else + ::arm_fir_fast_q15(&m_rrc02Filter, samples, YSFVals, RX_BLOCK_SIZE); +#endif + ysfRX.samples(YSFVals, rssi, RX_BLOCK_SIZE); + } + + if (m_m17Enable) { q15_t RRCVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_rrcFilter, samples, RRCVals, RX_BLOCK_SIZE); - - if (m_ysfEnable) - ysfRX.samples(RRCVals, rssi, RX_BLOCK_SIZE); - - if (m_dmrEnable) { - if (m_duplex) - dmrIdleRX.samples(RRCVals, RX_BLOCK_SIZE); - else - dmrDMORX.samples(RRCVals, rssi, RX_BLOCK_SIZE); - } - - if (m_m17Enable) - m17RX.samples(RRCVals, rssi, RX_BLOCK_SIZE); +#if defined(USE_DCBLOCKER) + ::arm_fir_fast_q15(&m_rrc05Filter, dcSamples, RRCVals, RX_BLOCK_SIZE); +#else + ::arm_fir_fast_q15(&m_rrc05Filter, samples, RRCVals, RX_BLOCK_SIZE); +#endif + m17RX.samples(RRCVals, rssi, RX_BLOCK_SIZE); } if (m_fmEnable) { @@ -409,7 +434,7 @@ void CIO::process() } else if (m_modemState == STATE_DMR) { if (m_dmrEnable) { q15_t DMRVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_rrcFilter, samples, DMRVals, RX_BLOCK_SIZE); + ::arm_fir_fast_q15(&m_rrc02Filter, samples, DMRVals, RX_BLOCK_SIZE); if (m_duplex) { // If the transmitter isn't on, use the DMR idle RX to detect the wakeup CSBKs @@ -425,9 +450,9 @@ void CIO::process() if (m_ysfEnable) { q15_t YSFVals[RX_BLOCK_SIZE]; #if defined(USE_DCBLOCKER) - ::arm_fir_fast_q15(&m_rrcFilter, dcSamples, YSFVals, RX_BLOCK_SIZE); + ::arm_fir_fast_q15(&m_rrc02Filter, dcSamples, YSFVals, RX_BLOCK_SIZE); #else - ::arm_fir_fast_q15(&m_rrcFilter, samples, YSFVals, RX_BLOCK_SIZE); + ::arm_fir_fast_q15(&m_rrc02Filter, samples, YSFVals, RX_BLOCK_SIZE); #endif ysfRX.samples(YSFVals, rssi, RX_BLOCK_SIZE); } @@ -458,9 +483,9 @@ void CIO::process() if (m_m17Enable) { q15_t M17Vals[RX_BLOCK_SIZE]; #if defined(USE_DCBLOCKER) - ::arm_fir_fast_q15(&m_rrcFilter, dcSamples, M17Vals, RX_BLOCK_SIZE); + ::arm_fir_fast_q15(&m_rrc05Filter, dcSamples, M17Vals, RX_BLOCK_SIZE); #else - ::arm_fir_fast_q15(&m_rrcFilter, samples, M17Vals, RX_BLOCK_SIZE); + ::arm_fir_fast_q15(&m_rrc05Filter, samples, M17Vals, RX_BLOCK_SIZE); #endif m17RX.samples(M17Vals, rssi, RX_BLOCK_SIZE); } @@ -573,7 +598,7 @@ void CIO::setMode(MMDVM_STATE state) case STATE_YSF: setYSFInt(false); break; case STATE_P25: setP25Int(false); break; case STATE_NXDN: setNXDNInt(false); break; - case STATE_M17: setM17Int(false); break; + case STATE_M17: setM17Int(false); break; case STATE_POCSAG: setPOCSAGInt(false); break; case STATE_FM: setFMInt(false); break; } diff --git a/IO.h b/IO.h index 4364a63..842de1e 100644 --- a/IO.h +++ b/IO.h @@ -66,14 +66,16 @@ private: arm_biquad_casd_df1_inst_q31 m_dcFilter; q31_t m_dcState[4]; - arm_fir_instance_q15 m_rrcFilter; + arm_fir_instance_q15 m_rrc02Filter; + arm_fir_instance_q15 m_rrc05Filter; arm_fir_instance_q15 m_gaussianFilter; arm_fir_instance_q15 m_boxcarFilter; arm_fir_instance_q15 m_nxdnFilter; arm_fir_instance_q15 m_nxdnISincFilter; - q15_t m_rrcState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare + q15_t m_rrc02State[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare + q15_t m_rrc05State[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare q15_t m_gaussianState[40U]; // NoTaps + BlockSize - 1, 12 + 20 - 1 plus some spare - q15_t m_boxcarState[30U]; // NoTaps + BlockSize - 1, 6 + 20 - 1 plus some spare + q15_t m_boxcarState[30U]; // NoTaps + BlockSize - 1, 6 + 20 - 1 plus some spare q15_t m_nxdnState[110U]; // NoTaps + BlockSize - 1, 82 + 20 - 1 plus some spare q15_t m_nxdnISincState[60U]; // NoTaps + BlockSize - 1, 32 + 20 - 1 plus some spare diff --git a/IODue.cpp b/IODue.cpp index b2aec0a..6dd01f3 100644 --- a/IODue.cpp +++ b/IODue.cpp @@ -107,6 +107,9 @@ void CIO::initInt() #if !defined(USE_ALTERNATE_NXDN_LEDS) pinMode(PIN_NXDN, OUTPUT); #endif +#if !defined(USE_ALTERNATE_M17_LEDS) + pinMode(PIN_M17, OUTPUT); +#endif #if !defined(USE_ALTERNATE_POCSAG_LEDS) pinMode(PIN_POCSAG, OUTPUT); #endif @@ -254,6 +257,16 @@ void CIO::setNXDNInt(bool on) #endif } +void CIO::setM17Int(bool on) +{ +#if defined(USE_ALTERNATE_M17_LEDS) + digitalWrite(PIN_DSTAR, on ? HIGH : LOW); + digitalWrite(PIN_P25, on ? HIGH : LOW); +#else + digitalWrite(PIN_M17, on ? HIGH : LOW); +#endif +} + void CIO::setPOCSAGInt(bool on) { #if defined(USE_ALTERNATE_POCSAG_LEDS) diff --git a/IOSTM.cpp b/IOSTM.cpp index 3abe89b..2e8f635 100644 --- a/IOSTM.cpp +++ b/IOSTM.cpp @@ -106,6 +106,14 @@ void CIO::initInt() GPIO_Init(PORT_NXDN, &GPIO_InitStruct); #endif +#if !defined(USE_ALTERNATE_M17_LEDS) + // M17 pin + RCC_AHB1PeriphClockCmd(RCC_Per_M17, ENABLE); + GPIO_InitStruct.GPIO_Pin = PIN_M17; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; + GPIO_Init(PORT_M17, &GPIO_InitStruct); +#endif + #if !defined(USE_ALTERNATE_POCSAG_LEDS) // POCSAG pin RCC_AHB1PeriphClockCmd(RCC_Per_POCSAG, ENABLE); @@ -157,6 +165,14 @@ void CIO::initInt() GPIO_Init(PORT_MNXDN, &GPIO_InitStruct); #endif +#if !defined(USE_ALTERNATE_M17_LEDS) + // M17 mode pin + RCC_AHB1PeriphClockCmd(RCC_Per_MM17, ENABLE); + GPIO_InitStruct.GPIO_Pin = PIN_MM17; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; + GPIO_Init(PORT_MM17, &GPIO_InitStruct); +#endif + #if !defined(USE_ALTERNATE_POCSAG_LEDS) // POCSAG mode pin RCC_AHB1PeriphClockCmd(RCC_Per_MPOCSAG, ENABLE); @@ -441,6 +457,27 @@ void CIO::setNXDNInt(bool on) #endif } +void CIO::setM17Int(bool on) +{ +#if defined(MODE_LEDS) +#if defined(USE_ALTERNATE_M17_LEDS) + GPIO_WriteBit(PORT_DSTAR, PIN_DSTAR, on ? Bit_SET : Bit_RESET); + GPIO_WriteBit(PORT_P25, PIN_P25, on ? Bit_SET : Bit_RESET); +#else + GPIO_WriteBit(PORT_M17, PIN_M17, on ? Bit_SET : Bit_RESET); +#endif +#endif + +#if defined(MODE_PINS) && defined(STM32F4_NUCLEO_MORPHO_HEADER) && (defined(STM32F4_NUCLEO) || defined(STM32F722_RPT_HAT)) +#if defined(USE_ALTERNATE_M17_LEDS) + GPIO_WriteBit(PORT_MDSTAR, PIN_MDSTAR, on ? Bit_SET : Bit_RESET); + GPIO_WriteBit(PORT_MP25, PIN_MP25, on ? Bit_SET : Bit_RESET); +#else + GPIO_WriteBit(PORT_MM17, PIN_MM17, on ? Bit_SET : Bit_RESET); +#endif +#endif +} + void CIO::setPOCSAGInt(bool on) { #if defined(MODE_LEDS) diff --git a/IOSTM_CMSIS.cpp b/IOSTM_CMSIS.cpp index 00f9767..8e4b39f 100644 --- a/IOSTM_CMSIS.cpp +++ b/IOSTM_CMSIS.cpp @@ -225,6 +225,9 @@ static inline void GPIOInit() #if !defined(USE_ALTERNATE_NXDN_LEDS) GPIOConfigPin(PORT_NXDN, PIN_NXDN, GPIO_CRL_MODE0_1); #endif +#if !defined(USE_ALTERNATE_M17_LEDS) + GPIOConfigPin(PORT_M17, PIN_M17, GPIO_CRL_MODE0_1); +#endif #if !defined(USE_ALTERNATE_POCSAG_LEDS) GPIOConfigPin(PORT_POCSAG, PIN_POCSAG, GPIO_CRL_MODE0_1); #endif @@ -450,6 +453,16 @@ void CIO::setNXDNInt(bool on) #endif } +void CIO::setM17Int(bool on) +{ +#if defined(USE_ALTERNATE_M17_LEDS) + BB_DSTAR = !!on; + BB_P25 = !!on; +#else + BB_M17 = !!on; +#endif +} + void CIO::setPOCSAGInt(bool on) { #if defined(USE_ALTERNATE_POCSAG_LEDS) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index aaece08..7e1fbaf 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -75,6 +75,9 @@ void CIO::initInt() #if !defined(USE_ALTERNATE_NXDN_LEDS) pinMode(PIN_NXDN, OUTPUT); #endif +#if !defined(USE_ALTERNATE_M17_LEDS) + pinMode(PIN_M17, OUTPUT); +#endif #if !defined(USE_ALTERNATE_POCSAG_LEDS) pinMode(PIN_POCSAG, OUTPUT); #endif @@ -238,6 +241,16 @@ void CIO::setNXDNInt(bool on) #endif } +void CIO::setM17Int(bool on) +{ +#if defined(USE_ALTERNATE_M17_LEDS) + digitalWrite(PIN_DSTAR, on ? HIGH : LOW); + digitalWrite(PIN_P25, on ? HIGH : LOW); +#else + digitalWrite(PIN_M17, on ? HIGH : LOW); +#endif +} + void CIO::setPOCSAGInt(bool on) { #if defined(USE_ALTERNATE_POCSAG_LEDS) diff --git a/M17TX.cpp b/M17TX.cpp index e38a4db..41d8d2b 100644 --- a/M17TX.cpp +++ b/M17TX.cpp @@ -23,16 +23,16 @@ #include "M17Defines.h" -// Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB -static q15_t RRC_0_2_FILTER[] = {0, 0, 0, 0, 850, 219, -720, -1548, -1795, -1172, 237, 1927, 3120, 3073, 1447, -1431, -4544, -6442, +// Generated using rcosdesign(0.5, 8, 5, 'sqrt') in MATLAB +static q15_t RRC_0_5_FILTER[] = {0, 0, 0, 0, 850, 219, -720, -1548, -1795, -1172, 237, 1927, 3120, 3073, 1447, -1431, -4544, -6442, -5735, -1633, 5651, 14822, 23810, 30367, 32767, 30367, 23810, 14822, 5651, -1633, -5735, -6442, -4544, -1431, 1447, 3073, 3120, 1927, 237, -1172, -1795, -1548, -720, 219, 850}; // numTaps = 45, L = 5 -const uint16_t RRC_0_2_FILTER_PHASE_LEN = 9U; // phaseLength = numTaps/L +const uint16_t RRC_0_5_FILTER_PHASE_LEN = 9U; // phaseLength = numTaps/L -const q15_t M17_LEVELA = 948; -const q15_t M17_LEVELB = 316; -const q15_t M17_LEVELC = -316; -const q15_t M17_LEVELD = -948; +const q15_t M17_LEVELA = 1683; +const q15_t M17_LEVELB = 561; +const q15_t M17_LEVELC = -561; +const q15_t M17_LEVELD = -1683; const uint8_t M17_START_SYNC = 0x77U; const uint8_t M17_END_SYNC = 0xFFU; @@ -52,12 +52,11 @@ m_txCount(0U) ::memset(m_modState, 0x00U, 16U * sizeof(q15_t)); m_modFilter.L = M17_RADIO_SYMBOL_LENGTH; - m_modFilter.phaseLength = RRC_0_2_FILTER_PHASE_LEN; - m_modFilter.pCoeffs = RRC_0_2_FILTER; + m_modFilter.phaseLength = RRC_0_5_FILTER_PHASE_LEN; + m_modFilter.pCoeffs = RRC_0_5_FILTER; m_modFilter.pState = m_modState; } - void CM17TX::process() { // If we have M17 data to transmit, do so.