diff --git a/IO.cpp b/IO.cpp index bfbb6f4..779dafa 100644 --- a/IO.cpp +++ b/IO.cpp @@ -28,10 +28,18 @@ const uint32_t DC_FILTER_STAGES = 1U; // One Biquad stage // Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB static q15_t RRC_0_2_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}; + 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_2_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, + 10134, 10731, 10935, 10731, 10134, 9184, 7946, 6502, 4946, 3376, 1886, 557, -545, -1375, -1914, -2164, -2150, + -1915, -1516, -1016, -477, 39, 483, 819, 1026, 1097, 1041, 880, 643, 364, 79, -181, -391, -533, -599, -590, + -517, -393, -240, -78, 73, 198, 284, 0}; +const uint16_t NXDN_0_2_FILTER_LEN = 82U; + // Generated using gaussfir(0.5, 4, 5) in MATLAB static q15_t GAUSSIAN_0_5_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0}; const uint16_t GAUSSIAN_0_5_FILTER_LEN = 12U; @@ -49,12 +57,16 @@ m_txBuffer(TX_RINGBUFFER_SIZE), m_rssiBuffer(RX_RINGBUFFER_SIZE), m_dcFilter(), m_dcState(), -m_rrcFilter(), +m_dmrFilter(), m_gaussianFilter(), m_boxcarFilter(), -m_rrcState(), +m_nxdnFilter(), +m_ysfFilter(), +m_dmrState(), m_gaussianState(), m_boxcarState(), +m_nxdnState(), +m_ysfState(), m_pttInvert(false), m_rxLevel(128 * 128), m_cwIdTXLevel(128 * 128), @@ -73,19 +85,21 @@ m_dacOverflow(0U), m_watchdog(0U), m_lockout(false) { - ::memset(m_rrcState, 0x00U, 70U * sizeof(q15_t)); - ::memset(m_gaussianState, 0x00U, 40U * sizeof(q15_t)); - ::memset(m_boxcarState, 0x00U, 30U * sizeof(q15_t)); - ::memset(m_dcState, 0x00U, 4U * sizeof(q31_t)); + ::memset(m_dmrState, 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)); + ::memset(m_ysfState, 0x00U, 70U * sizeof(q15_t)); + ::memset(m_dcState, 0x00U, 4U * sizeof(q31_t)); m_dcFilter.numStages = DC_FILTER_STAGES; m_dcFilter.pState = m_dcState; 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_dmrFilter.numTaps = RRC_0_2_FILTER_LEN; + m_dmrFilter.pState = m_dmrState; + m_dmrFilter.pCoeffs = RRC_0_2_FILTER; m_gaussianFilter.numTaps = GAUSSIAN_0_5_FILTER_LEN; m_gaussianFilter.pState = m_gaussianState; @@ -95,6 +109,14 @@ m_lockout(false) m_boxcarFilter.pState = m_boxcarState; m_boxcarFilter.pCoeffs = BOXCAR_FILTER; + m_nxdnFilter.numTaps = NXDN_0_2_FILTER_LEN; + m_nxdnFilter.pState = m_nxdnState; + m_nxdnFilter.pCoeffs = NXDN_0_2_FILTER; + + m_ysfFilter.numTaps = RRC_0_2_FILTER_LEN; + m_ysfFilter.pState = m_ysfState; + m_ysfFilter.pCoeffs = RRC_0_2_FILTER; + initInt(); selfTest(); @@ -300,31 +322,35 @@ void CIO::process() dstarRX.samples(GMSKVals, rssi, RX_BLOCK_SIZE); } - if (m_p25Enable || m_nxdnEnable) { + if (m_p25Enable) { q15_t C4FSKVals[RX_BLOCK_SIZE]; ::arm_fir_fast_q15(&m_boxcarFilter, dcSamples, C4FSKVals, RX_BLOCK_SIZE); - if (m_p25Enable) - p25RX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE); - - if (m_nxdnEnable) - nxdnRX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE); + p25RX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE); } - // XXX YSF should use dcSamples, but DMR not - if (m_dmrEnable || m_ysfEnable) { - q15_t C4FSKVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_rrcFilter, samples, C4FSKVals, RX_BLOCK_SIZE); + if (m_nxdnEnable) { + q15_t NXDNVals[RX_BLOCK_SIZE]; + ::arm_fir_fast_q15(&m_nxdnFilter, dcSamples, NXDNVals, RX_BLOCK_SIZE); - if (m_dmrEnable) { - if (m_duplex) - dmrIdleRX.samples(C4FSKVals, RX_BLOCK_SIZE); - else - dmrDMORX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE); - } + nxdnRX.samples(NXDNVals, rssi, RX_BLOCK_SIZE); + } - if (m_ysfEnable) - ysfRX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE); + if (m_ysfEnable) { + q15_t YSFVals[RX_BLOCK_SIZE]; + ::arm_fir_fast_q15(&m_ysfFilter, dcSamples, YSFVals, RX_BLOCK_SIZE); + + ysfRX.samples(YSFVals, rssi, RX_BLOCK_SIZE); + } + + if (m_dmrEnable) { + q15_t DMRVals[RX_BLOCK_SIZE]; + ::arm_fir_fast_q15(&m_dmrFilter, samples, DMRVals, RX_BLOCK_SIZE); + + if (m_duplex) + dmrIdleRX.samples(DMRVals, RX_BLOCK_SIZE); + else + dmrDMORX.samples(DMRVals, rssi, RX_BLOCK_SIZE); } } else if (m_modemState == STATE_DSTAR) { if (m_dstarEnable) { @@ -335,25 +361,25 @@ void CIO::process() } } else if (m_modemState == STATE_DMR) { if (m_dmrEnable) { - q15_t C4FSKVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_rrcFilter, samples, C4FSKVals, RX_BLOCK_SIZE); + q15_t DMRVals[RX_BLOCK_SIZE]; + ::arm_fir_fast_q15(&m_dmrFilter, samples, DMRVals, RX_BLOCK_SIZE); if (m_duplex) { // If the transmitter isn't on, use the DMR idle RX to detect the wakeup CSBKs if (m_tx) - dmrRX.samples(C4FSKVals, rssi, control, RX_BLOCK_SIZE); + dmrRX.samples(DMRVals, rssi, control, RX_BLOCK_SIZE); else - dmrIdleRX.samples(C4FSKVals, RX_BLOCK_SIZE); + dmrIdleRX.samples(DMRVals, RX_BLOCK_SIZE); } else { - dmrDMORX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE); + dmrDMORX.samples(DMRVals, rssi, RX_BLOCK_SIZE); } } } else if (m_modemState == STATE_YSF) { if (m_ysfEnable) { - q15_t C4FSKVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_rrcFilter, dcSamples, C4FSKVals, RX_BLOCK_SIZE); + q15_t YSFVals[RX_BLOCK_SIZE]; + ::arm_fir_fast_q15(&m_ysfFilter, dcSamples, YSFVals, RX_BLOCK_SIZE); - ysfRX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE); + ysfRX.samples(YSFVals, rssi, RX_BLOCK_SIZE); } } else if (m_modemState == STATE_P25) { if (m_p25Enable) { @@ -365,7 +391,7 @@ void CIO::process() } else if (m_modemState == STATE_NXDN) { if (m_nxdnEnable) { q15_t NXDNVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_boxcarFilter, dcSamples, NXDNVals, RX_BLOCK_SIZE); + ::arm_fir_fast_q15(&m_nxdnFilter, dcSamples, NXDNVals, RX_BLOCK_SIZE); nxdnRX.samples(NXDNVals, rssi, RX_BLOCK_SIZE); } diff --git a/IO.h b/IO.h index 0f1f62d..511253b 100644 --- a/IO.h +++ b/IO.h @@ -66,12 +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_dmrFilter; arm_fir_instance_q15 m_gaussianFilter; arm_fir_instance_q15 m_boxcarFilter; - q15_t m_rrcState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare + arm_fir_instance_q15 m_nxdnFilter; + arm_fir_instance_q15 m_ysfFilter; + q15_t m_dmrState[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_nxdnState[110U]; // NoTaps + BlockSize - 1, 82 + 20 - 1 plus some spare + q15_t m_ysfState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare bool m_pttInvert; q15_t m_rxLevel; diff --git a/NXDNDefines.h b/NXDNDefines.h index cbb7731..a98166f 100644 --- a/NXDNDefines.h +++ b/NXDNDefines.h @@ -19,7 +19,7 @@ #if !defined(NXDNDEFINES_H) #define NXDNDEFINES_H -const unsigned int NXDN_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate +const unsigned int NXDN_RADIO_SYMBOL_LENGTH = 10U; // At 24 kHz sample rate const unsigned int NXDN_FRAME_LENGTH_BITS = 384U; const unsigned int NXDN_FRAME_LENGTH_BYTES = NXDN_FRAME_LENGTH_BITS / 8U; diff --git a/NXDNTX.cpp b/NXDNTX.cpp index 16e6d55..e655937 100644 --- a/NXDNTX.cpp +++ b/NXDNTX.cpp @@ -23,16 +23,19 @@ #include "NXDNDefines.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, - -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 +// Generated using rcosdesign(0.2, 8, 10, 'sqrt') in MATLAB +static q15_t RRC_0_2_FILTER[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 850, 592, 219, -234, -720, -1179, -1548, -1769, -1795, -1597, -1172, + -544, 237, 1092, 1927, 2637, 3120, 3286, 3073, 2454, 1447, 116, -1431, -3043, -4544, -5739, -6442, + -6483, -5735, -4121, -1633, 1669, 5651, 10118, 14822, 19484, 23810, 27520, 30367, 32156, 32767, + 32156, 30367, 27520, 23810, 19484, 14822, 10118, 5651, 1669, -1633, -4121, -5735, -6483, -6442, + -5739, -4544, -3043, -1431, 116, 1447, 2454, 3073, 3286, 3120, 2637, 1927, 1092, 237, -544, -1172, + -1597, -1795, -1769, -1548, -1179, -720, -234, 219, 592, 850}; // numTaps = 90, L = 10 const uint16_t RRC_0_2_FILTER_PHASE_LEN = 9U; // phaseLength = numTaps/L -const q15_t NXDN_LEVELA = 1680; -const q15_t NXDN_LEVELB = 560; -const q15_t NXDN_LEVELC = -560; -const q15_t NXDN_LEVELD = -1680; +const q15_t NXDN_LEVELA = 840; +const q15_t NXDN_LEVELB = 280; +const q15_t NXDN_LEVELC = -280; +const q15_t NXDN_LEVELD = -840; const uint8_t NXDN_PREAMBLE[] = {0x57U, 0x75U, 0xFDU}; const uint8_t NXDN_SYNC = 0x5FU; @@ -148,6 +151,6 @@ void CNXDNTX::setTXDelay(uint8_t delay) uint8_t CNXDNTX::getSpace() const { - return m_buffer.getSpace() / YSF_FRAME_LENGTH_BYTES; + return m_buffer.getSpace() / NXDN_FRAME_LENGTH_BYTES; }