From 316085f2a6bc29dd5d73b7785fe5728f9cdb15c9 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 2 Jul 2017 17:08:45 +0100 Subject: [PATCH 01/13] Try the boxcar filter on all modes. --- IO.cpp | 104 +++++++++++++++------------------------------------------ IO.h | 4 --- 2 files changed, 26 insertions(+), 82 deletions(-) diff --git a/IO.cpp b/IO.cpp index 35d4a7a..f1ad830 100644 --- a/IO.cpp +++ b/IO.cpp @@ -22,16 +22,6 @@ #include "Globals.h" #include "IO.h" -// 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}; -const uint16_t RRC_0_2_FILTER_LEN = 42U; - -// 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; - // One symbol boxcar filter static q15_t BOXCAR_FILTER[] = {3000, 3000, 3000, 3000, 3000, 0}; const uint16_t BOXCAR_FILTER_LEN = 6U; @@ -43,11 +33,7 @@ m_started(false), m_rxBuffer(RX_RINGBUFFER_SIZE), m_txBuffer(TX_RINGBUFFER_SIZE), m_rssiBuffer(RX_RINGBUFFER_SIZE), -m_rrcFilter(), -m_gaussianFilter(), m_boxcarFilter(), -m_rrcState(), -m_gaussianState(), m_boxcarState(), m_pttInvert(false), m_rxLevel(128 * 128), @@ -64,17 +50,7 @@ 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)); - - m_rrcFilter.numTaps = RRC_0_2_FILTER_LEN; - m_rrcFilter.pState = m_rrcState; - m_rrcFilter.pCoeffs = RRC_0_2_FILTER; - - m_gaussianFilter.numTaps = GAUSSIAN_0_5_FILTER_LEN; - m_gaussianFilter.pState = m_gaussianState; - m_gaussianFilter.pCoeffs = GAUSSIAN_0_5_FILTER; + ::memset(m_boxcarState, 0x00U, 30U * sizeof(q15_t)); m_boxcarFilter.numTaps = BOXCAR_FILTER_LEN; m_boxcarFilter.pState = m_boxcarState; @@ -157,76 +133,48 @@ void CIO::process() if (m_lockout) return; + q15_t vals[RX_BLOCK_SIZE]; + ::arm_fir_fast_q15(&m_boxcarFilter, samples, vals, RX_BLOCK_SIZE); + if (m_modemState == STATE_IDLE) { - if (m_dstarEnable) { - q15_t GMSKVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_gaussianFilter, samples, GMSKVals, RX_BLOCK_SIZE); + if (m_dstarEnable) + dstarRX.samples(vals, rssi, RX_BLOCK_SIZE); - dstarRX.samples(GMSKVals, rssi, RX_BLOCK_SIZE); + if (m_p25Enable) + p25RX.samples(vals, rssi, RX_BLOCK_SIZE); + + if (m_dmrEnable) { + if (m_duplex) + dmrIdleRX.samples(vals, RX_BLOCK_SIZE); + else + dmrDMORX.samples(vals, rssi, RX_BLOCK_SIZE); } - if (m_p25Enable) { - q15_t P25Vals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_boxcarFilter, samples, P25Vals, RX_BLOCK_SIZE); - - p25RX.samples(P25Vals, rssi, RX_BLOCK_SIZE); - } - - if (m_dmrEnable || m_ysfEnable) { - q15_t C4FSKVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_rrcFilter, samples, C4FSKVals, RX_BLOCK_SIZE); - - if (m_dmrEnable) { - if (m_duplex) - dmrIdleRX.samples(C4FSKVals, RX_BLOCK_SIZE); - else - dmrDMORX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE); - } - - if (m_ysfEnable) - ysfRX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE); - } + if (m_ysfEnable) + ysfRX.samples(vals, rssi, RX_BLOCK_SIZE); } else if (m_modemState == STATE_DSTAR) { - if (m_dstarEnable) { - q15_t GMSKVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_gaussianFilter, samples, GMSKVals, RX_BLOCK_SIZE); - - dstarRX.samples(GMSKVals, rssi, RX_BLOCK_SIZE); - } + if (m_dstarEnable) + dstarRX.samples(vals, rssi, RX_BLOCK_SIZE); } 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); - 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(vals, rssi, control, RX_BLOCK_SIZE); else - dmrIdleRX.samples(C4FSKVals, RX_BLOCK_SIZE); + dmrIdleRX.samples(vals, RX_BLOCK_SIZE); } else { - dmrDMORX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE); + dmrDMORX.samples(vals, 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, samples, C4FSKVals, RX_BLOCK_SIZE); - - ysfRX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE); - } + if (m_ysfEnable) + ysfRX.samples(vals, rssi, RX_BLOCK_SIZE); } else if (m_modemState == STATE_P25) { - if (m_p25Enable) { - q15_t P25Vals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_boxcarFilter, samples, P25Vals, RX_BLOCK_SIZE); - - p25RX.samples(P25Vals, rssi, RX_BLOCK_SIZE); - } + if (m_p25Enable) + p25RX.samples(vals, rssi, 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); - - calDStarRX.samples(GMSKVals, RX_BLOCK_SIZE); + calDStarRX.samples(vals, RX_BLOCK_SIZE); } else if (m_modemState == STATE_RSSICAL) { calRSSI.samples(rssi, RX_BLOCK_SIZE); } diff --git a/IO.h b/IO.h index 80a6d28..8498b75 100644 --- a/IO.h +++ b/IO.h @@ -60,11 +60,7 @@ private: CSampleRB m_txBuffer; CRSSIRB m_rssiBuffer; - arm_fir_instance_q15 m_rrcFilter; - 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 - 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 bool m_pttInvert; From 5d74c2f7bf5e0b74ba008a0340b98dd847a106d1 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 2 Jul 2017 17:57:17 +0100 Subject: [PATCH 02/13] First changes for correlation of D-Star. --- DStarDefines.h | 13 ++-- DStarRX.cpp | 183 ++++++++++++++++++++++++++++++++----------------- DStarRX.h | 27 +++++--- 3 files changed, 145 insertions(+), 78 deletions(-) diff --git a/DStarDefines.h b/DStarDefines.h index 6255028..995e736 100644 --- a/DStarDefines.h +++ b/DStarDefines.h @@ -21,14 +21,15 @@ const unsigned int DSTAR_RADIO_BIT_LENGTH = 5U; // At 24 kHz sample rate -const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U; -const unsigned int DSTAR_HEADER_LENGTH_BITS = DSTAR_HEADER_LENGTH_BYTES * 8U; +const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U; -const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U; -const unsigned int DSTAR_FEC_SECTION_LENGTH_BITS = 660U; +const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U; +const unsigned int DSTAR_FEC_SECTION_LENGTH_BITS = 660U; +const unsigned int DSTAR_FEC_SECTION_LENGTH_SAMPLES = DSTAR_FEC_SECTION_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH; -const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U; -const unsigned int DSTAR_DATA_LENGTH_BITS = DSTAR_DATA_LENGTH_BYTES * 8U; +const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U; +const unsigned int DSTAR_DATA_LENGTH_BITS = DSTAR_DATA_LENGTH_BYTES * 8U; +const unsigned int DSTAR_DATA_LENGTH_SAMPLES = DSTAR_DATA_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH; const uint8_t DSTAR_EOT_BYTES[] = {0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const unsigned int DSTAR_EOT_LENGTH_BYTES = 6U; diff --git a/DStarRX.cpp b/DStarRX.cpp index 6c4f342..de3bc93 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -22,12 +22,6 @@ #include "DStarRX.h" #include "Utils.h" -const unsigned int BUFFER_LENGTH = 200U; - -const uint32_t PLLMAX = 0x10000U; -const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH; -const uint32_t INC = PLLINC / 32U; - const unsigned int MAX_SYNC_BITS = 50U * DSTAR_DATA_LENGTH_BITS; const unsigned int SYNC_POS = 21U * DSTAR_DATA_LENGTH_BITS; @@ -245,14 +239,22 @@ const uint16_t CCITT_TABLE[] = { 0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U, 0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U}; +const uint16_t NOENDPTR = 9999U; + CDStarRX::CDStarRX() : -m_pll(0U), -m_prev(false), m_rxState(DSRXS_NONE), -m_patternBuffer(0x00U), -m_rxBuffer(), -m_rxBufferBits(0U), -m_dataBits(0U), +m_bitBuffer(), +m_buffer(), +m_bitPtr(0U), +m_dataPtr(0U), +m_startPtr(NOENDPTR), +m_endPtr(NOENDPTR), +m_syncPtr(NOENDPTR), +m_minSyncPtr(NOENDPTR), +m_maxSyncPtr(NOENDPTR), +m_maxCorr(0), +m_lostCount(0U), +m_countdown(0U), m_mar(0U), m_pathMetric(), m_pathMemory0(), @@ -268,21 +270,26 @@ m_dcState() ::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.pState = m_dcState; + m_dcFilter.pCoeffs = DC_FILTER; m_dcFilter.postShift = 0; } void CDStarRX::reset() { - m_pll = 0U; - m_prev = false; - m_rxState = DSRXS_NONE; - m_patternBuffer = 0x00U; - m_rxBufferBits = 0U; - m_dataBits = 0U; - m_rssiAccum = 0U; - m_rssiCount = 0U; + m_rxState = DSRXS_NONE; + m_dataPtr = 0U; + m_bitPtr = 0U; + m_maxCorr = 0; + m_startPtr = NOENDPTR; + m_endPtr = NOENDPTR; + m_syncPtr = NOENDPTR; + m_minSyncPtr = NOENDPTR; + m_maxSyncPtr = NOENDPTR; + m_lostCount = 0U; + m_countdown = 0U; + m_rssiAccum = 0U; + m_rssiCount = 0U; } void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length) @@ -303,45 +310,38 @@ void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t lengt m_rssiAccum += rssi[i]; m_rssiCount++; - bool bit = samples[i] < (q15_t) (dc_level >> 16); + q15_t sample = samples[i] - q15_t(dc_level >> 16); - if (bit != m_prev) { - if (m_pll < (PLLMAX / 2U)) - m_pll += INC; - else - m_pll -= INC; + m_bitBuffer[m_bitPtr] <<= 1; + if (sample < 0) + m_bitBuffer[m_bitPtr] |= 0x01U; + + m_buffer[m_dataPtr] = sample; + + switch (m_rxState) { + case DSRXS_HEADER: + processHeader(sample); + break; + case DSRXS_DATA: + processData(sample); + break; + default: + processNone(sample); + break; } - m_prev = bit; + m_dataPtr++; + if (m_dataPtr >= DSTAR_FRAME_LENGTH_SAMPLES) + m_dataPtr = 0U; - m_pll += PLLINC; - - if (m_pll >= PLLMAX) { - m_pll -= PLLMAX; - - switch (m_rxState) { - case DSRXS_NONE: - processNone(bit); - break; - case DSRXS_HEADER: - processHeader(bit); - break; - case DSRXS_DATA: - processData(bit); - break; - default: - break; - } - } + m_bitPtr++; + if (m_bitPtr >= DSTAR_RADIO_BIT_LENGTH) + m_bitPtr = 0U; } } -void CDStarRX::processNone(bool bit) +void CDStarRX::processNone(q15_t sample) { - m_patternBuffer <<= 1; - if (bit) - m_patternBuffer |= 0x01U; - // Fuzzy matching of the frame sync sequence if (countBits32((m_patternBuffer & FRAME_SYNC_MASK) ^ FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) { DEBUG1("DStarRX: found frame sync in None"); @@ -379,12 +379,8 @@ void CDStarRX::processNone(bool bit) } } -void CDStarRX::processHeader(bool bit) +void CDStarRX::processHeader(q15_t sample) { - m_patternBuffer <<= 1; - if (bit) - m_patternBuffer |= 0x01U; - WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit); m_rxBufferBits++; @@ -411,12 +407,8 @@ void CDStarRX::processHeader(bool bit) } } -void CDStarRX::processData(bool bit) +void CDStarRX::processData(q15_t sample) { - m_patternBuffer <<= 1; - if (bit) - m_patternBuffer |= 0x01U; - WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit); m_rxBufferBits++; @@ -536,6 +528,71 @@ void CDStarRX::writeRSSIData(unsigned char* data) m_rssiCount = 0U; } +bool CDStarRX::correlateDataSync() +{ + if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_SYNC_SYMBOLS_MASK) ^ DSTAR_SYNC_SYMBOLS) <= MAX_SYNC_SYMBOLS_ERRS) { + uint16_t ptr = m_dataPtr + DSTAR_FRAME_LENGTH_SAMPLES - DSTAR_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH; + if (ptr >= DSTAR_FRAME_LENGTH_SAMPLES) + ptr -= DSTAR_FRAME_LENGTH_SAMPLES; + + q31_t corr = 0; + + for (uint8_t i = 0U; i < YSF_SYNC_LENGTH_SYMBOLS; i++) { + q15_t val = m_buffer[ptr]; + + switch (DSTAR_SYNC_SYMBOLS_VALUES[i]) { + case +1: + corr -= val; + break; + default: + corr += val; + break; + } + + ptr += DSTAR_RADIO_SYMBOL_LENGTH; + if (ptr >= DSTAR_FRAME_LENGTH_SAMPLES) + ptr -= DSTAR_FRAME_LENGTH_SAMPLES; + } + + if (corr > m_maxCorr) { + uint16_t startPtr = m_dataPtr + DSTAR_FRAME_LENGTH_SAMPLES - DSTAR_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH; + if (startPtr >= DSTAR_FRAME_LENGTH_SAMPLES) + startPtr -= DSTAR_FRAME_LENGTH_SAMPLES; + + m_maxCorr = corr; + m_lostCount = MAX_SYNC_FRAMES; + m_syncPtr = m_dataPtr; + + m_startPtr = startPtr; + + m_endPtr = m_dataPtr + DSTAR_FRAME_LENGTH_SAMPLES - DSTAR_SYNC_LENGTH_SAMPLES - 1U; + if (m_endPtr >= DSTAR_FRAME_LENGTH_SAMPLES) + m_endPtr -= DSTAR_FRAME_LENGTH_SAMPLES; + + return true; + } + } + } + + return false; +} + +void CDStarRX::samplesToBits(uint16_t start, uint16_t count, uint8_t* buffer, uint16_t offset) +{ + for (uint16_t i = 0U; i < count; i++, offset++) { + q15_t sample = m_buffer[start]; + + if (sample < 0) + WRITE_BIT2(buffer, offset, true); + else + WRITE_BIT2(buffer, offset, false); + + start += DSTAR_RADIO_SYMBOL_LENGTH; + if (start >= DSTAR_FRAME_LENGTH_SAMPLES) + start -= DSTAR_FRAME_LENGTH_SAMPLES; + } +} + bool CDStarRX::rxHeader(uint8_t* in, uint8_t* out) { int i; diff --git a/DStarRX.h b/DStarRX.h index 157fb41..1fedd3a 100644 --- a/DStarRX.h +++ b/DStarRX.h @@ -37,13 +37,19 @@ public: void reset(); private: - uint32_t m_pll; - bool m_prev; DSRX_STATE m_rxState; - uint32_t m_patternBuffer; - uint8_t m_rxBuffer[100U]; - unsigned int m_rxBufferBits; - unsigned int m_dataBits; + uint32_t m_bitBuffer[DSTAR_RADIO_BIT_LENGTH]; + q15_t m_buffer[DSTAR_FEC_SECTION_LENGTH_SAMPLES]; + uint16_t m_bitPtr; + uint16_t m_dataPtr; + uint16_t m_startPtr; + uint16_t m_endPtr; + uint16_t m_minSyncPtr; + uint16_t m_maxSyncPtr; + uint16_t m_syncPtr; + q31_t m_maxCorr; + uint16_t m_lostCount; + uint8_t m_countdown; unsigned int m_mar; int m_pathMetric[4U]; unsigned int m_pathMemory0[42U]; @@ -56,9 +62,12 @@ private: arm_biquad_casd_df1_inst_q31 m_dcFilter; q31_t m_dcState[4]; - void processNone(bool bit); - void processHeader(bool bit); - void processData(bool bit); + void processNone(q15_t sample); + void processHeader(q15_t sample); + void processData(q15_t sample); + bool correlateFrameSync(); + bool correlateDataSync(); + void samplesToBits(uint16_t start, uint16_t count, uint8_t* buffer, uint16_t offset); void writeRSSIHeader(unsigned char* header); void writeRSSIData(unsigned char* data); bool rxHeader(uint8_t* in, uint8_t* out); From c22f360ed1d3ee3e2f45c6cf27fb328f4d01d8f4 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 3 Jul 2017 20:26:24 +0100 Subject: [PATCH 03/13] More changes to the D-Star RX. --- CalDStarRX.cpp | 2 +- DStarDefines.h | 39 +++++--- DStarRX.cpp | 235 ++++++++++++++++++++++++++----------------------- DStarRX.h | 13 +-- 4 files changed, 160 insertions(+), 129 deletions(-) diff --git a/CalDStarRX.cpp b/CalDStarRX.cpp index 32b6345..0336938 100644 --- a/CalDStarRX.cpp +++ b/CalDStarRX.cpp @@ -24,7 +24,7 @@ const unsigned int BUFFER_LENGTH = 200U; const uint32_t PLLMAX = 0x10000U; -const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH; +const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_SYMBOL_LENGTH; const uint32_t INC = PLLINC / 32U; // D-Star bit order version of 0x55 0x2D 0x16 diff --git a/DStarDefines.h b/DStarDefines.h index 995e736..970fe5a 100644 --- a/DStarDefines.h +++ b/DStarDefines.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2015 by Jonathan Naylor G4KLX + * Copyright (C) 2009-2015,2017 by Jonathan Naylor G4KLX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,31 +19,48 @@ #if !defined(DSTARDEFINES_H) #define DSTARDEFINES_H -const unsigned int DSTAR_RADIO_BIT_LENGTH = 5U; // At 24 kHz sample rate +const unsigned int DSTAR_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U; const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U; const unsigned int DSTAR_FEC_SECTION_LENGTH_BITS = 660U; -const unsigned int DSTAR_FEC_SECTION_LENGTH_SAMPLES = DSTAR_FEC_SECTION_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH; +const unsigned int DSTAR_FEC_SECTION_LENGTH_SAMPLES = DSTAR_FEC_SECTION_LENGTH_BITS * DSTAR_RADIO_SYMBOL_LENGTH; const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U; const unsigned int DSTAR_DATA_LENGTH_BITS = DSTAR_DATA_LENGTH_BYTES * 8U; -const unsigned int DSTAR_DATA_LENGTH_SAMPLES = DSTAR_DATA_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH; +const unsigned int DSTAR_DATA_LENGTH_SAMPLES = DSTAR_DATA_LENGTH_BITS * DSTAR_RADIO_SYMBOL_LENGTH; -const uint8_t DSTAR_EOT_BYTES[] = {0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const unsigned int DSTAR_EOT_LENGTH_BYTES = 6U; const unsigned int DSTAR_EOT_LENGTH_BITS = DSTAR_EOT_LENGTH_BYTES * 8U; -const uint8_t DSTAR_DATA_SYNC_LENGTH_BYTES = 3U; -const uint8_t DSTAR_DATA_SYNC_LENGTH_BITS = DSTAR_DATA_SYNC_LENGTH_BYTES * 8U; +const unsigned int DSTAR_FRAME_SYNC_LENGTH_BYTES = 3U; +const unsigned int DSTAR_FRAME_SYNC_LENGTH_SYMBOLS = DSTAR_FRAME_SYNC_LENGTH_BYTES * 8U; -const uint8_t DSTAR_DATA_SYNC_BYTES[] = {0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16}; +const unsigned int DSTAR_DATA_SYNC_LENGTH_BYTES = 3U; +const unsigned int DSTAR_DATA_SYNC_LENGTH_SYMBOLS = DSTAR_DATA_SYNC_LENGTH_BYTES * 8U; -const uint8_t DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U; -const uint8_t DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U; +const uint8_t DSTAR_DATA_SYNC_BYTES[] = {0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16}; -const uint8_t DSTAR_SCRAMBLER_BYTES[] = {0x70U, 0x4FU, 0x93U}; +// D-Star bit order version of 0x55 0x6E 0x0A +const uint32_t DSTAR_FRAME_SYNC_DATA = 0x00557650U; +const uint32_t DSTAR_FRAME_SYNC_MASK = 0x00FFFFFFU; +const bool DSTAR_FRAME_SYNC_SYMBOLS[] = {false, true, false, true, false, true, false, true, false, true, true, true, false, true, true, false, false, true, false, true, false, false, false, false}; + +// D-Star bit order version of 0x55 0x2D 0x16 +const uint32_t DSTAR_DATA_SYNC_DATA = 0x00AAB468U; +const uint32_t DSTAR_DATA_SYNC_MASK = 0x00FFFFFFU; +const bool DSTAR_DATA_SYNC_SYMBOLS[] = {true, false, true, false, true, false, true, false, true, false, true, true, false, true, false, false, false, true, true, false, true, false, false, false}; + +// D-Star bit order version of 0x55 0x55 0xC8 0x7A +const uint32_t DSTAR_END_SYNC_DATA = 0xAAAA135EU; +const uint32_t DSTAR_END_SYNC_MASK = 0xFFFFFFFFU; +const uint8_t DSTAR_END_SYNC_BYTES[] = {0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +const uint8_t DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U; +const uint8_t DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U; + +const uint8_t DSTAR_SCRAMBLER_BYTES[] = {0x70U, 0x4FU, 0x93U}; #endif diff --git a/DStarRX.cpp b/DStarRX.cpp index de3bc93..cec0dc4 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -25,27 +25,16 @@ const unsigned int MAX_SYNC_BITS = 50U * DSTAR_DATA_LENGTH_BITS; const unsigned int SYNC_POS = 21U * DSTAR_DATA_LENGTH_BITS; -const unsigned int SYNC_SCAN_START = SYNC_POS - 3U; -const unsigned int SYNC_SCAN_END = SYNC_POS + 3U; +const unsigned int SYNC_SCAN_START = SYNC_POS - 2U; +const unsigned int SYNC_SCAN_END = SYNC_POS + 2U; // Generated using [b, a] = butter(1, 0.001) in MATLAB static q31_t DC_FILTER[] = {3367972, 0, 3367972, 0, 2140747704, 0}; // {b0, 0, b1, b2, -a1, -a2} const uint32_t DC_FILTER_STAGES = 1U; // One Biquad stage -// D-Star bit order version of 0x55 0x55 0x6E 0x0A -const uint32_t FRAME_SYNC_DATA = 0x00557650U; -const uint32_t FRAME_SYNC_MASK = 0x00FFFFFFU; -const uint8_t FRAME_SYNC_ERRS = 2U; - -// D-Star bit order version of 0x55 0x2D 0x16 -const uint32_t DATA_SYNC_DATA = 0x00AAB468U; -const uint32_t DATA_SYNC_MASK = 0x00FFFFFFU; -const uint8_t DATA_SYNC_ERRS = 2U; - -// D-Star bit order version of 0x55 0x55 0xC8 0x7A -const uint32_t END_SYNC_DATA = 0xAAAA135EU; -const uint32_t END_SYNC_MASK = 0xFFFFFFFFU; -const uint8_t END_SYNC_ERRS = 3U; +const uint8_t MAX_FRAME_SYNC_SYMBOL_ERRS = 2U; +const uint8_t MAX_DATA_SYNC_SYMBOL_ERRS = 2U; +const uint8_t MAX_END_SYNC_SYMBOL_ERRS = 3U; const uint8_t BIT_MASK_TABLE0[] = {0x7FU, 0xBFU, 0xDFU, 0xEFU, 0xF7U, 0xFBU, 0xFDU, 0xFEU}; const uint8_t BIT_MASK_TABLE1[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; @@ -244,15 +233,18 @@ const uint16_t NOENDPTR = 9999U; CDStarRX::CDStarRX() : m_rxState(DSRXS_NONE), m_bitBuffer(), -m_buffer(), +m_headerBuffer(), +m_dataBuffer(), m_bitPtr(0U), +m_headerPtr(0U), m_dataPtr(0U), m_startPtr(NOENDPTR), m_endPtr(NOENDPTR), m_syncPtr(NOENDPTR), m_minSyncPtr(NOENDPTR), m_maxSyncPtr(NOENDPTR), -m_maxCorr(0), +m_maxFrameCorr(0), +m_maxDataCorr(0), m_lostCount(0U), m_countdown(0U), m_mar(0U), @@ -278,9 +270,11 @@ m_dcState() void CDStarRX::reset() { m_rxState = DSRXS_NONE; + m_headerPtr = 0U; m_dataPtr = 0U; m_bitPtr = 0U; - m_maxCorr = 0; + m_maxFrameCorr = 0; + m_maxDataCorr = 0; m_startPtr = NOENDPTR; m_endPtr = NOENDPTR; m_syncPtr = NOENDPTR; @@ -316,14 +310,14 @@ void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t lengt if (sample < 0) m_bitBuffer[m_bitPtr] |= 0x01U; - m_buffer[m_dataPtr] = sample; + m_dataBuffer[m_dataPtr] = sample; switch (m_rxState) { case DSRXS_HEADER: processHeader(sample); break; case DSRXS_DATA: - processData(sample); + processData(); break; default: processNone(sample); @@ -331,11 +325,11 @@ void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t lengt } m_dataPtr++; - if (m_dataPtr >= DSTAR_FRAME_LENGTH_SAMPLES) + if (m_dataPtr >= DSTAR_DATA_LENGTH_SAMPLES) m_dataPtr = 0U; m_bitPtr++; - if (m_bitPtr >= DSTAR_RADIO_BIT_LENGTH) + if (m_bitPtr >= DSTAR_RADIO_SYMBOL_LENGTH) m_bitPtr = 0U; } } @@ -343,21 +337,26 @@ void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t lengt void CDStarRX::processNone(q15_t sample) { // Fuzzy matching of the frame sync sequence - if (countBits32((m_patternBuffer & FRAME_SYNC_MASK) ^ FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) { + bool ret = correlateFrameSync(); + if (ret) { DEBUG1("DStarRX: found frame sync in None"); - ::memset(m_rxBuffer, 0x00U, DSTAR_FEC_SECTION_LENGTH_BYTES); - m_rxBufferBits = 0U; + m_countdown = 5U; + + m_headerBuffer[0U] = sample; + m_headerPtr = 1U; m_rssiAccum = 0U; m_rssiCount = 0U; m_rxState = DSRXS_HEADER; + return; } - // Exact matching of the data sync bit sequence - if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) == 0U) { + // Fuzzy matching of the data sync bit sequence + ret = correlateDataSync(); + if (ret) { DEBUG1("DStarRX: found data sync in None"); io.setDecode(true); @@ -375,29 +374,33 @@ void CDStarRX::processNone(q15_t sample) m_dataBits = 0U; m_rxState = DSRXS_DATA; - return; } } void CDStarRX::processHeader(q15_t sample) { - WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit); - m_rxBufferBits++; + if (m_countdown > 0U) { + correlateFrameSync(); + m_countdown--; + } + + m_headerBuffer[m_headerPtr] = sample; + m_headerPtr++; // A full FEC header - if (m_rxBufferBits == DSTAR_FEC_SECTION_LENGTH_BITS) { + if (m_headerPtr == DSTAR_FEC_SECTION_LENGTH_SAMPLES) { // Process the scrambling, interleaving and FEC, then return if the chcksum was correct - unsigned char header[DSTAR_HEADER_LENGTH_BYTES]; - bool ok = rxHeader(m_rxBuffer, header); + uint8_t buffer[DSTAR_FEC_SECTION_LENGTH_BYTES]; + samplesToBits(m_headerBuffer, m_startPtr, DSTAR_FEC_SECTION_LENGTH_SYMBOLS, buffer, DSTAR_FEC_SECTION_LENGTH_SAMPLES); + + uint8_t header[DSTAR_HEADER_LENGTH_BYTES]; + bool ok = rxHeader(buffer, header); if (ok) { io.setDecode(true); io.setADCDetection(true); writeRSSIHeader(header); - ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U); - m_rxBufferBits = 0U; - m_rxState = DSRXS_DATA; m_dataBits = SYNC_POS - DSTAR_DATA_LENGTH_BITS + 1U; } else { @@ -407,13 +410,10 @@ void CDStarRX::processHeader(q15_t sample) } } -void CDStarRX::processData(q15_t sample) +void CDStarRX::processData() { - WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit); - m_rxBufferBits++; - // Fuzzy matching of the end frame sequences - if (countBits32((m_patternBuffer & END_SYNC_MASK) ^ END_SYNC_DATA) <= END_SYNC_ERRS) { + if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_END_SYNC_MASK) ^ DSTAR_END_SYNC_DATA) <= MAX_END_SYNC_SYMBOL_ERRS) { DEBUG1("DStarRX: Found end sync in Data"); io.setDecode(false); @@ -426,35 +426,8 @@ void CDStarRX::processData(q15_t sample) } // Fuzzy matching of the data sync bit sequence - bool syncSeen = false; - if (m_dataBits >= SYNC_SCAN_START && m_dataBits <= (SYNC_POS + 1U)) { - if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) <= DATA_SYNC_ERRS) { - if (m_dataBits < SYNC_POS) - DEBUG2("DStarRX: found data sync in Data, early", SYNC_POS - m_dataBits); - else - DEBUG1("DStarRX: found data sync in Data"); - - m_rxBufferBits = DSTAR_DATA_LENGTH_BITS; - m_dataBits = 0U; - syncSeen = true; - } - } // Check to see if the sync is arriving late - if (m_dataBits == SYNC_POS) { - for (uint8_t i = 1U; i <= 3U; i++) { - uint32_t syncMask = DATA_SYNC_MASK >> i; - uint32_t syncData = DATA_SYNC_DATA >> i; - if (countBits32((m_patternBuffer & syncMask) ^ syncData) <= DATA_SYNC_ERRS) { - DEBUG2("DStarRX: found data sync in Data, late", i); - m_rxBufferBits -= i; - m_dataBits -= i; - break; - } - } - } - - m_dataBits++; // We've not seen a data sync for too long, signal RXLOST and change to RX_NONE if (m_dataBits >= MAX_SYNC_BITS) { @@ -469,20 +442,18 @@ void CDStarRX::processData(q15_t sample) return; } - // Send a data frame to the host if the required number of bits have been received, or if a data sync has been seen - if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS) { + // Send a data frame to the host if the required number of bits have been received + if (m_dataPtr == m_endPtr) { + uint8_t buffer[DSTAR_DATA_LENGTH_BYTES + 2U]; + samplesToBits(m_dataBuffer, m_startPtr, DSTAR_DATA_LENGTH_SYMBOLS, buffer, DSTAR_DATA_LENGTH_SAMPLES); if (syncSeen) { - m_rxBuffer[9U] = DSTAR_DATA_SYNC_BYTES[9U]; - m_rxBuffer[10U] = DSTAR_DATA_SYNC_BYTES[10U]; - m_rxBuffer[11U] = DSTAR_DATA_SYNC_BYTES[11U]; - writeRSSIData(m_rxBuffer); + buffer[9U] = DSTAR_DATA_SYNC_BYTES[9U]; + buffer[10U] = DSTAR_DATA_SYNC_BYTES[10U]; + buffer[11U] = DSTAR_DATA_SYNC_BYTES[11U]; + writeRSSIData(buffer); } else { - serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES); - } - - // Start the next frame - ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U); - m_rxBufferBits = 0U; + serial.writeDStarData(buffer, DSTAR_DATA_LENGTH_BYTES); + } } } @@ -528,68 +499,108 @@ void CDStarRX::writeRSSIData(unsigned char* data) m_rssiCount = 0U; } -bool CDStarRX::correlateDataSync() +bool CDStarRX::correlateFrameSync() { - if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_SYNC_SYMBOLS_MASK) ^ DSTAR_SYNC_SYMBOLS) <= MAX_SYNC_SYMBOLS_ERRS) { + if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_FRAME_SYNC_MASK) ^ DSTAR_FRAME_SYNC_DATA) <= MAX_FRAME_SYNC_SYMBOLS_ERRS) { uint16_t ptr = m_dataPtr + DSTAR_FRAME_LENGTH_SAMPLES - DSTAR_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH; - if (ptr >= DSTAR_FRAME_LENGTH_SAMPLES) - ptr -= DSTAR_FRAME_LENGTH_SAMPLES; + if (ptr >= DSTAR_DATA_LENGTH_SAMPLES) + ptr -= DSTAR_DATA_LENGTH_SAMPLES; q31_t corr = 0; - for (uint8_t i = 0U; i < YSF_SYNC_LENGTH_SYMBOLS; i++) { - q15_t val = m_buffer[ptr]; + for (uint8_t i = 0U; i < DSTAR_FRAME_SYNC_LENGTH_SYMBOLS; i++) { + q15_t val = m_dataBuffer[ptr]; - switch (DSTAR_SYNC_SYMBOLS_VALUES[i]) { - case +1: + if (DSTAR_FRAME_SYNC_SYMBOLS[i]) corr -= val; - break; - default: + else corr += val; - break; - } ptr += DSTAR_RADIO_SYMBOL_LENGTH; - if (ptr >= DSTAR_FRAME_LENGTH_SAMPLES) - ptr -= DSTAR_FRAME_LENGTH_SAMPLES; + if (ptr >= DSTAR_DATA_LENGTH_SAMPLES) + ptr -= DSTAR_DATA_LENGTH_SAMPLES; } - if (corr > m_maxCorr) { + if (corr > m_maxFrameCorr) { uint16_t startPtr = m_dataPtr + DSTAR_FRAME_LENGTH_SAMPLES - DSTAR_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH; if (startPtr >= DSTAR_FRAME_LENGTH_SAMPLES) startPtr -= DSTAR_FRAME_LENGTH_SAMPLES; - m_maxCorr = corr; - m_lostCount = MAX_SYNC_FRAMES; - m_syncPtr = m_dataPtr; + m_maxFrameCorr = corr; + m_lostCount = MAX_SYNC_FRAMES; + m_syncPtr = m_dataPtr; + m_headerPtr = 0U; - m_startPtr = startPtr; + m_startPtr = startPtr; - m_endPtr = m_dataPtr + DSTAR_FRAME_LENGTH_SAMPLES - DSTAR_SYNC_LENGTH_SAMPLES - 1U; - if (m_endPtr >= DSTAR_FRAME_LENGTH_SAMPLES) - m_endPtr -= DSTAR_FRAME_LENGTH_SAMPLES; + m_endPtr = m_dataPtr + DSTAR_FRAME_LENGTH_SAMPLES - DSTAR_SYNC_LENGTH_SAMPLES - 1U; + if (m_endPtr >= DSTAR_FRAME_LENGTH_SAMPLES) + m_endPtr -= DSTAR_FRAME_LENGTH_SAMPLES; - return true; - } + return true; } } return false; } -void CDStarRX::samplesToBits(uint16_t start, uint16_t count, uint8_t* buffer, uint16_t offset) +bool CDStarRX::correlateDataSync() { - for (uint16_t i = 0U; i < count; i++, offset++) { - q15_t sample = m_buffer[start]; + if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_DATA_SYNC_MASK) ^ DSTAR_DATA_SYNC_DATA) <= MAX_DATA_SYNC_SYMBOLS_ERRS) { + uint16_t ptr = m_dataPtr + DSTAR_FRAME_LENGTH_SAMPLES - DSTAR_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH; + if (ptr >= DSTAR_DATA_LENGTH_SAMPLES) + ptr -= DSTAR_DATA_LENGTH_SAMPLES; + + q31_t corr = 0; + + for (uint8_t i = 0U; i < DSTAR_DATA_SYNC_LENGTH_SYMBOLS; i++) { + q15_t val = m_dataBuffer[ptr]; + + if (DSTAR_DATA_SYNC_SYMBOLS[i]) + corr -= val; + else + corr += val; + + ptr += DSTAR_RADIO_SYMBOL_LENGTH; + if (ptr >= DSTAR_DATA_LENGTH_SAMPLES) + ptr -= DSTAR_DATA_LENGTH_SAMPLES; + } + + if (corr > m_maxDataCorr) { + uint16_t startPtr = m_dataPtr + DSTAR_FRAME_LENGTH_SAMPLES - DSTAR_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH; + if (startPtr >= DSTAR_DATA_LENGTH_SAMPLES) + startPtr -= DSTAR_DATA_LENGTH_SAMPLES; + + m_maxDataCorr = corr; + m_lostCount = MAX_SYNC_FRAMES; + m_syncPtr = m_dataPtr; + + m_startPtr = startPtr; + + m_endPtr = m_dataPtr + 2U; + if (m_endPtr >= DSTAR_DATA_LENGTH_SAMPLES) + m_endPtr -= DSTAR_DATA_LENGTH_SAMPLES; + + return true; + } + } + + return false; +} + +void CDStarRX::samplesToBits(const uint8_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit) +{ + for (uint16_t i = 0U; i < count; i++) { + q15_t sample = inBuffer[start]; if (sample < 0) - WRITE_BIT2(buffer, offset, true); + WRITE_BIT2(outBuffer, i, true); else - WRITE_BIT2(buffer, offset, false); + WRITE_BIT2(outBuffer, i, false); start += DSTAR_RADIO_SYMBOL_LENGTH; - if (start >= DSTAR_FRAME_LENGTH_SAMPLES) - start -= DSTAR_FRAME_LENGTH_SAMPLES; + if (start >= limit) + start -= limit; } } diff --git a/DStarRX.h b/DStarRX.h index 1fedd3a..5c76890 100644 --- a/DStarRX.h +++ b/DStarRX.h @@ -38,16 +38,19 @@ public: private: DSRX_STATE m_rxState; - uint32_t m_bitBuffer[DSTAR_RADIO_BIT_LENGTH]; - q15_t m_buffer[DSTAR_FEC_SECTION_LENGTH_SAMPLES]; + uint32_t m_bitBuffer[DSTAR_RADIO_SYMBOL_LENGTH]; + q15_t m_headerBuffer[DSTAR_FEC_SECTION_LENGTH_SAMPLES]; + q15_t m_dataBuffer[DSTAR_DATA_LENGTH_SAMPLES]; uint16_t m_bitPtr; + uint16_t m_headerPtr; uint16_t m_dataPtr; uint16_t m_startPtr; uint16_t m_endPtr; uint16_t m_minSyncPtr; uint16_t m_maxSyncPtr; uint16_t m_syncPtr; - q31_t m_maxCorr; + q31_t m_maxFrameCorr; + q31_t m_maxDataCorr; uint16_t m_lostCount; uint8_t m_countdown; unsigned int m_mar; @@ -64,10 +67,10 @@ private: void processNone(q15_t sample); void processHeader(q15_t sample); - void processData(q15_t sample); + void processData(); bool correlateFrameSync(); bool correlateDataSync(); - void samplesToBits(uint16_t start, uint16_t count, uint8_t* buffer, uint16_t offset); + void samplesToBits(const uint8_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit); void writeRSSIHeader(unsigned char* header); void writeRSSIData(unsigned char* data); bool rxHeader(uint8_t* in, uint8_t* out); From 4b253f888de0105ffa840a45cff363218d10e4ef Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 3 Jul 2017 20:29:52 +0100 Subject: [PATCH 04/13] Increase the boxcar level. --- IO.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IO.cpp b/IO.cpp index f1ad830..38e45a0 100644 --- a/IO.cpp +++ b/IO.cpp @@ -23,7 +23,7 @@ #include "IO.h" // One symbol boxcar filter -static q15_t BOXCAR_FILTER[] = {3000, 3000, 3000, 3000, 3000, 0}; +static q15_t BOXCAR_FILTER[] = {6000, 6000, 6000, 6000, 6000, 0}; const uint16_t BOXCAR_FILTER_LEN = 6U; const uint16_t DC_OFFSET = 2048U; From de0aed2d2b410027b84a2e17ae2b8a93aa52cec3 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 6 Jul 2017 20:09:57 +0100 Subject: [PATCH 05/13] Increase amplitude of the boxcar filter. --- IO.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IO.cpp b/IO.cpp index 38e45a0..7072980 100644 --- a/IO.cpp +++ b/IO.cpp @@ -23,7 +23,7 @@ #include "IO.h" // One symbol boxcar filter -static q15_t BOXCAR_FILTER[] = {6000, 6000, 6000, 6000, 6000, 0}; +static q15_t BOXCAR_FILTER[] = {12000, 12000, 12000, 12000, 12000, 0}; const uint16_t BOXCAR_FILTER_LEN = 6U; const uint16_t DC_OFFSET = 2048U; From 90797696dd45e16be7f3f5f9800c7c0c1b51c772 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 6 Jul 2017 20:28:20 +0100 Subject: [PATCH 06/13] First compileable version, but untested. --- DStarDefines.h | 14 +++-- DStarRX.cpp | 150 +++++++++++++++++++++++++------------------------ DStarRX.h | 8 +-- DStarTX.cpp | 14 ++--- 4 files changed, 95 insertions(+), 91 deletions(-) diff --git a/DStarDefines.h b/DStarDefines.h index 970fe5a..2983c9e 100644 --- a/DStarDefines.h +++ b/DStarDefines.h @@ -24,21 +24,23 @@ const unsigned int DSTAR_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U; const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U; -const unsigned int DSTAR_FEC_SECTION_LENGTH_BITS = 660U; -const unsigned int DSTAR_FEC_SECTION_LENGTH_SAMPLES = DSTAR_FEC_SECTION_LENGTH_BITS * DSTAR_RADIO_SYMBOL_LENGTH; +const unsigned int DSTAR_FEC_SECTION_LENGTH_SYMBOLS = 660U; +const unsigned int DSTAR_FEC_SECTION_LENGTH_SAMPLES = DSTAR_FEC_SECTION_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH; const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U; -const unsigned int DSTAR_DATA_LENGTH_BITS = DSTAR_DATA_LENGTH_BYTES * 8U; -const unsigned int DSTAR_DATA_LENGTH_SAMPLES = DSTAR_DATA_LENGTH_BITS * DSTAR_RADIO_SYMBOL_LENGTH; +const unsigned int DSTAR_DATA_LENGTH_SYMBOLS = DSTAR_DATA_LENGTH_BYTES * 8U; +const unsigned int DSTAR_DATA_LENGTH_SAMPLES = DSTAR_DATA_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH; -const unsigned int DSTAR_EOT_LENGTH_BYTES = 6U; -const unsigned int DSTAR_EOT_LENGTH_BITS = DSTAR_EOT_LENGTH_BYTES * 8U; +const unsigned int DSTAR_END_SYNC_LENGTH_BYTES = 6U; +const unsigned int DSTAR_END_SYNC_LENGTH_BITS = DSTAR_END_SYNC_LENGTH_BYTES * 8U; const unsigned int DSTAR_FRAME_SYNC_LENGTH_BYTES = 3U; const unsigned int DSTAR_FRAME_SYNC_LENGTH_SYMBOLS = DSTAR_FRAME_SYNC_LENGTH_BYTES * 8U; +const unsigned int DSTAR_FRAME_SYNC_LENGTH_SAMPLES = DSTAR_FRAME_SYNC_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH; const unsigned int DSTAR_DATA_SYNC_LENGTH_BYTES = 3U; const unsigned int DSTAR_DATA_SYNC_LENGTH_SYMBOLS = DSTAR_DATA_SYNC_LENGTH_BYTES * 8U; +const unsigned int DSTAR_DATA_SYNC_LENGTH_SAMPLES = DSTAR_DATA_SYNC_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH; const uint8_t DSTAR_DATA_SYNC_BYTES[] = {0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16}; diff --git a/DStarRX.cpp b/DStarRX.cpp index cec0dc4..3d10ddc 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -22,19 +22,15 @@ #include "DStarRX.h" #include "Utils.h" -const unsigned int MAX_SYNC_BITS = 50U * DSTAR_DATA_LENGTH_BITS; - -const unsigned int SYNC_POS = 21U * DSTAR_DATA_LENGTH_BITS; -const unsigned int SYNC_SCAN_START = SYNC_POS - 2U; -const unsigned int SYNC_SCAN_END = SYNC_POS + 2U; +const unsigned int MAX_FRAMES = 75U; // Generated using [b, a] = butter(1, 0.001) in MATLAB static q31_t DC_FILTER[] = {3367972, 0, 3367972, 0, 2140747704, 0}; // {b0, 0, b1, b2, -a1, -a2} const uint32_t DC_FILTER_STAGES = 1U; // One Biquad stage -const uint8_t MAX_FRAME_SYNC_SYMBOL_ERRS = 2U; -const uint8_t MAX_DATA_SYNC_SYMBOL_ERRS = 2U; -const uint8_t MAX_END_SYNC_SYMBOL_ERRS = 3U; +const uint8_t MAX_FRAME_SYNC_BIT_ERRS = 2U; +const uint8_t MAX_DATA_SYNC_BIT_ERRS = 2U; +const uint8_t MAX_END_SYNC_BIT_ERRS = 3U; const uint8_t BIT_MASK_TABLE0[] = {0x7FU, 0xBFU, 0xDFU, 0xEFU, 0xF7U, 0xFBU, 0xFDU, 0xFEU}; const uint8_t BIT_MASK_TABLE1[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; @@ -239,13 +235,11 @@ m_bitPtr(0U), m_headerPtr(0U), m_dataPtr(0U), m_startPtr(NOENDPTR), -m_endPtr(NOENDPTR), -m_syncPtr(NOENDPTR), m_minSyncPtr(NOENDPTR), m_maxSyncPtr(NOENDPTR), m_maxFrameCorr(0), m_maxDataCorr(0), -m_lostCount(0U), +m_frameCount(0U), m_countdown(0U), m_mar(0U), m_pathMetric(), @@ -276,11 +270,9 @@ void CDStarRX::reset() m_maxFrameCorr = 0; m_maxDataCorr = 0; m_startPtr = NOENDPTR; - m_endPtr = NOENDPTR; - m_syncPtr = NOENDPTR; m_minSyncPtr = NOENDPTR; m_maxSyncPtr = NOENDPTR; - m_lostCount = 0U; + m_frameCount = 0U; m_countdown = 0U; m_rssiAccum = 0U; m_rssiCount = 0U; @@ -343,8 +335,8 @@ void CDStarRX::processNone(q15_t sample) m_countdown = 5U; - m_headerBuffer[0U] = sample; - m_headerPtr = 1U; + m_headerBuffer[m_headerPtr] = sample; + m_headerPtr++; m_rssiAccum = 0U; m_rssiCount = 0U; @@ -362,18 +354,7 @@ void CDStarRX::processNone(q15_t sample) io.setDecode(true); io.setADCDetection(true); - // Suppress RSSI on the dummy sync message - m_rssiAccum = 0U; - m_rssiCount = 0U; - - ::memcpy(m_rxBuffer, DSTAR_DATA_SYNC_BYTES, DSTAR_DATA_LENGTH_BYTES); - writeRSSIData(m_rxBuffer); - - ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U); - m_rxBufferBits = 0U; - - m_dataBits = 0U; - m_rxState = DSRXS_DATA; + m_rxState = DSRXS_DATA; } } @@ -389,31 +370,47 @@ void CDStarRX::processHeader(q15_t sample) // A full FEC header if (m_headerPtr == DSTAR_FEC_SECTION_LENGTH_SAMPLES) { - // Process the scrambling, interleaving and FEC, then return if the chcksum was correct uint8_t buffer[DSTAR_FEC_SECTION_LENGTH_BYTES]; - samplesToBits(m_headerBuffer, m_startPtr, DSTAR_FEC_SECTION_LENGTH_SYMBOLS, buffer, DSTAR_FEC_SECTION_LENGTH_SAMPLES); + samplesToBits(m_headerBuffer, 0U, DSTAR_FEC_SECTION_LENGTH_SYMBOLS, buffer, DSTAR_FEC_SECTION_LENGTH_SAMPLES); + // Process the scrambling, interleaving and FEC, then return true if the chcksum was correct uint8_t header[DSTAR_HEADER_LENGTH_BYTES]; bool ok = rxHeader(buffer, header); - if (ok) { - io.setDecode(true); - io.setADCDetection(true); - - writeRSSIHeader(header); - - m_rxState = DSRXS_DATA; - m_dataBits = SYNC_POS - DSTAR_DATA_LENGTH_BITS + 1U; - } else { + if (!ok) { // The checksum failed, return to looking for syncs m_rxState = DSRXS_NONE; + m_maxFrameCorr = 0; + m_maxDataCorr = 0; } } + + // Reday to start the first data section + if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH)) { + m_frameCount = 0U; + + m_startPtr = m_dataPtr; + + m_maxSyncPtr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_DATA_SYNC_LENGTH_SAMPLES + 2U; + if (m_maxSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES) + m_maxSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES; + + m_minSyncPtr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_DATA_SYNC_LENGTH_SAMPLES - 2U; + if (m_minSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES) + m_minSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES; + } + + // Reday to start the first data section + if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH + DSTAR_RADIO_SYMBOL_LENGTH)) { + m_rxState = DSRXS_DATA; + m_maxFrameCorr = 0; + m_maxDataCorr = 0; + } } void CDStarRX::processData() { // Fuzzy matching of the end frame sequences - if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_END_SYNC_MASK) ^ DSTAR_END_SYNC_DATA) <= MAX_END_SYNC_SYMBOL_ERRS) { + if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_END_SYNC_MASK) ^ DSTAR_END_SYNC_DATA) <= MAX_END_SYNC_BIT_ERRS) { DEBUG1("DStarRX: Found end sync in Data"); io.setDecode(false); @@ -421,16 +418,26 @@ void CDStarRX::processData() serial.writeDStarEOT(); + m_maxFrameCorr = 0; + m_maxDataCorr = 0; + m_rxState = DSRXS_NONE; return; } // Fuzzy matching of the data sync bit sequence - - // Check to see if the sync is arriving late + if ((m_frameCount % 21U) == 0U) { + if (m_minSyncPtr < m_maxSyncPtr) { + if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr) + correlateDataSync(); + } else { + if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr) + correlateDataSync(); + } + } // We've not seen a data sync for too long, signal RXLOST and change to RX_NONE - if (m_dataBits >= MAX_SYNC_BITS) { + if (m_frameCount >= MAX_FRAMES) { DEBUG1("DStarRX: data sync timed out, lost lock"); io.setDecode(false); @@ -438,15 +445,19 @@ void CDStarRX::processData() serial.writeDStarLost(); + m_maxFrameCorr = 0; + m_maxDataCorr = 0; + m_rxState = DSRXS_NONE; return; } // Send a data frame to the host if the required number of bits have been received - if (m_dataPtr == m_endPtr) { + if (m_dataPtr == m_maxSyncPtr) { uint8_t buffer[DSTAR_DATA_LENGTH_BYTES + 2U]; samplesToBits(m_dataBuffer, m_startPtr, DSTAR_DATA_LENGTH_SYMBOLS, buffer, DSTAR_DATA_LENGTH_SAMPLES); - if (syncSeen) { + + if (m_frameCount == 0U) { buffer[9U] = DSTAR_DATA_SYNC_BYTES[9U]; buffer[10U] = DSTAR_DATA_SYNC_BYTES[10U]; buffer[11U] = DSTAR_DATA_SYNC_BYTES[11U]; @@ -454,6 +465,11 @@ void CDStarRX::processData() } else { serial.writeDStarData(buffer, DSTAR_DATA_LENGTH_BYTES); } + + m_frameCount++; + + m_maxFrameCorr = 0; + m_maxDataCorr = 0; } } @@ -501,8 +517,8 @@ void CDStarRX::writeRSSIData(unsigned char* data) bool CDStarRX::correlateFrameSync() { - if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_FRAME_SYNC_MASK) ^ DSTAR_FRAME_SYNC_DATA) <= MAX_FRAME_SYNC_SYMBOLS_ERRS) { - uint16_t ptr = m_dataPtr + DSTAR_FRAME_LENGTH_SAMPLES - DSTAR_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH; + if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_FRAME_SYNC_MASK) ^ DSTAR_FRAME_SYNC_DATA) <= MAX_FRAME_SYNC_BIT_ERRS) { + uint16_t ptr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_FRAME_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH; if (ptr >= DSTAR_DATA_LENGTH_SAMPLES) ptr -= DSTAR_DATA_LENGTH_SAMPLES; @@ -522,21 +538,8 @@ bool CDStarRX::correlateFrameSync() } if (corr > m_maxFrameCorr) { - uint16_t startPtr = m_dataPtr + DSTAR_FRAME_LENGTH_SAMPLES - DSTAR_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH; - if (startPtr >= DSTAR_FRAME_LENGTH_SAMPLES) - startPtr -= DSTAR_FRAME_LENGTH_SAMPLES; - m_maxFrameCorr = corr; - m_lostCount = MAX_SYNC_FRAMES; - m_syncPtr = m_dataPtr; m_headerPtr = 0U; - - m_startPtr = startPtr; - - m_endPtr = m_dataPtr + DSTAR_FRAME_LENGTH_SAMPLES - DSTAR_SYNC_LENGTH_SAMPLES - 1U; - if (m_endPtr >= DSTAR_FRAME_LENGTH_SAMPLES) - m_endPtr -= DSTAR_FRAME_LENGTH_SAMPLES; - return true; } } @@ -546,8 +549,8 @@ bool CDStarRX::correlateFrameSync() bool CDStarRX::correlateDataSync() { - if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_DATA_SYNC_MASK) ^ DSTAR_DATA_SYNC_DATA) <= MAX_DATA_SYNC_SYMBOLS_ERRS) { - uint16_t ptr = m_dataPtr + DSTAR_FRAME_LENGTH_SAMPLES - DSTAR_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH; + if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_DATA_SYNC_MASK) ^ DSTAR_DATA_SYNC_DATA) <= MAX_DATA_SYNC_BIT_ERRS) { + uint16_t ptr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_DATA_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH; if (ptr >= DSTAR_DATA_LENGTH_SAMPLES) ptr -= DSTAR_DATA_LENGTH_SAMPLES; @@ -567,19 +570,20 @@ bool CDStarRX::correlateDataSync() } if (corr > m_maxDataCorr) { - uint16_t startPtr = m_dataPtr + DSTAR_FRAME_LENGTH_SAMPLES - DSTAR_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH; - if (startPtr >= DSTAR_DATA_LENGTH_SAMPLES) - startPtr -= DSTAR_DATA_LENGTH_SAMPLES; - m_maxDataCorr = corr; - m_lostCount = MAX_SYNC_FRAMES; - m_syncPtr = m_dataPtr; + m_frameCount = 0U; - m_startPtr = startPtr; + m_startPtr = m_dataPtr + DSTAR_RADIO_SYMBOL_LENGTH; + if (m_startPtr >= DSTAR_DATA_LENGTH_SAMPLES) + m_startPtr -= DSTAR_DATA_LENGTH_SAMPLES; - m_endPtr = m_dataPtr + 2U; - if (m_endPtr >= DSTAR_DATA_LENGTH_SAMPLES) - m_endPtr -= DSTAR_DATA_LENGTH_SAMPLES; + m_maxSyncPtr = m_startPtr + DSTAR_DATA_LENGTH_SAMPLES + 2U; + if (m_maxSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES) + m_maxSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES; + + m_minSyncPtr = m_startPtr + DSTAR_DATA_LENGTH_SAMPLES - 2U; + if (m_minSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES) + m_minSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES; return true; } @@ -588,7 +592,7 @@ bool CDStarRX::correlateDataSync() return false; } -void CDStarRX::samplesToBits(const uint8_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit) +void CDStarRX::samplesToBits(const q15_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit) { for (uint16_t i = 0U; i < count; i++) { q15_t sample = inBuffer[start]; diff --git a/DStarRX.h b/DStarRX.h index 5c76890..4630e94 100644 --- a/DStarRX.h +++ b/DStarRX.h @@ -39,19 +39,17 @@ public: private: DSRX_STATE m_rxState; uint32_t m_bitBuffer[DSTAR_RADIO_SYMBOL_LENGTH]; - q15_t m_headerBuffer[DSTAR_FEC_SECTION_LENGTH_SAMPLES]; + q15_t m_headerBuffer[DSTAR_FEC_SECTION_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH]; q15_t m_dataBuffer[DSTAR_DATA_LENGTH_SAMPLES]; uint16_t m_bitPtr; uint16_t m_headerPtr; uint16_t m_dataPtr; uint16_t m_startPtr; - uint16_t m_endPtr; uint16_t m_minSyncPtr; uint16_t m_maxSyncPtr; - uint16_t m_syncPtr; q31_t m_maxFrameCorr; q31_t m_maxDataCorr; - uint16_t m_lostCount; + uint16_t m_frameCount; uint8_t m_countdown; unsigned int m_mar; int m_pathMetric[4U]; @@ -70,7 +68,7 @@ private: void processData(); bool correlateFrameSync(); bool correlateDataSync(); - void samplesToBits(const uint8_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit); + void samplesToBits(const q15_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit); void writeRSSIHeader(unsigned char* header); void writeRSSIData(unsigned char* data); bool rxHeader(uint8_t* in, uint8_t* out); diff --git a/DStarTX.cpp b/DStarTX.cpp index 031d75d..e2b3eb1 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -198,7 +198,7 @@ m_txDelay(60U) // 100ms { ::memset(m_modState, 0x00U, 20U * sizeof(q15_t)); - m_modFilter.L = DSTAR_RADIO_BIT_LENGTH; + m_modFilter.L = DSTAR_RADIO_SYMBOL_LENGTH; m_modFilter.phaseLength = GAUSSIAN_0_35_FILTER_PHASE_LEN; m_modFilter.pCoeffs = GAUSSIAN_0_35_FILTER; m_modFilter.pState = m_modState; @@ -252,8 +252,8 @@ void CDStarTX::process() m_buffer.get(); for (uint8_t j = 0U; j < 3U; j++) { - for (uint8_t i = 0U; i < DSTAR_EOT_LENGTH_BYTES; i++) - m_poBuffer[m_poLen++] = DSTAR_EOT_BYTES[i]; + for (uint8_t i = 0U; i < DSTAR_END_SYNC_LENGTH_BYTES; i++) + m_poBuffer[m_poLen++] = DSTAR_END_SYNC_BYTES[i]; } m_poPtr = 0U; @@ -262,11 +262,11 @@ void CDStarTX::process() if (m_poLen > 0U) { uint16_t space = io.getSpace(); - while (space > (8U * DSTAR_RADIO_BIT_LENGTH)) { + while (space > (8U * DSTAR_RADIO_SYMBOL_LENGTH)) { uint8_t c = m_poBuffer[m_poPtr++]; writeByte(c); - space -= 8U * DSTAR_RADIO_BIT_LENGTH; + space -= 8U * DSTAR_RADIO_SYMBOL_LENGTH; if (m_poPtr >= m_poLen) { m_poPtr = 0U; @@ -412,7 +412,7 @@ void CDStarTX::txHeader(const uint8_t* in, uint8_t* out) const void CDStarTX::writeByte(uint8_t c) { q15_t inBuffer[8U]; - q15_t outBuffer[DSTAR_RADIO_BIT_LENGTH * 8U]; + q15_t outBuffer[DSTAR_RADIO_SYMBOL_LENGTH * 8U]; uint8_t mask = 0x01U; @@ -427,7 +427,7 @@ void CDStarTX::writeByte(uint8_t c) ::arm_fir_interpolate_q15(&m_modFilter, inBuffer, outBuffer, 8U); - io.write(STATE_DSTAR, outBuffer, DSTAR_RADIO_BIT_LENGTH * 8U); + io.write(STATE_DSTAR, outBuffer, DSTAR_RADIO_SYMBOL_LENGTH * 8U); } void CDStarTX::setTXDelay(uint8_t delay) From c8208ab1dffb0e264c4f11916dfcebf21110a56b Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 10 Jul 2017 19:58:50 +0100 Subject: [PATCH 07/13] Added extra debugging and updated position calculations. --- DStarRX.cpp | 35 +++++++++++++++++++++++------------ DStarRX.h | 3 ++- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/DStarRX.cpp b/DStarRX.cpp index 3d10ddc..e15a310 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -235,6 +235,7 @@ m_bitPtr(0U), m_headerPtr(0U), m_dataPtr(0U), m_startPtr(NOENDPTR), +m_syncPtr(NOENDPTR), m_minSyncPtr(NOENDPTR), m_maxSyncPtr(NOENDPTR), m_maxFrameCorr(0), @@ -270,6 +271,7 @@ void CDStarRX::reset() m_maxFrameCorr = 0; m_maxDataCorr = 0; m_startPtr = NOENDPTR; + m_syncPtr = NOENDPTR; m_minSyncPtr = NOENDPTR; m_maxSyncPtr = NOENDPTR; m_frameCount = 0U; @@ -333,7 +335,7 @@ void CDStarRX::processNone(q15_t sample) if (ret) { DEBUG1("DStarRX: found frame sync in None"); - m_countdown = 5U; + m_countdown = 5U; m_headerBuffer[m_headerPtr] = sample; m_headerPtr++; @@ -369,9 +371,9 @@ void CDStarRX::processHeader(q15_t sample) m_headerPtr++; // A full FEC header - if (m_headerPtr == DSTAR_FEC_SECTION_LENGTH_SAMPLES) { + if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH)) { uint8_t buffer[DSTAR_FEC_SECTION_LENGTH_BYTES]; - samplesToBits(m_headerBuffer, 0U, DSTAR_FEC_SECTION_LENGTH_SYMBOLS, buffer, DSTAR_FEC_SECTION_LENGTH_SAMPLES); + samplesToBits(m_headerBuffer, DSTAR_RADIO_SYMBOL_LENGTH, DSTAR_FEC_SECTION_LENGTH_SYMBOLS, buffer, DSTAR_FEC_SECTION_LENGTH_SAMPLES); // Process the scrambling, interleaving and FEC, then return true if the chcksum was correct uint8_t header[DSTAR_HEADER_LENGTH_BYTES]; @@ -384,23 +386,26 @@ void CDStarRX::processHeader(q15_t sample) } } - // Reday to start the first data section - if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH)) { + // Ready to start the first data section + if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + 2U * DSTAR_RADIO_SYMBOL_LENGTH)) { m_frameCount = 0U; m_startPtr = m_dataPtr; - m_maxSyncPtr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_DATA_SYNC_LENGTH_SAMPLES + 2U; + m_syncPtr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH; + if (m_syncPtr >= DSTAR_DATA_LENGTH_SAMPLES) + m_syncPtr -= DSTAR_DATA_LENGTH_SAMPLES; + + m_maxSyncPtr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH + 2U; if (m_maxSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES) m_maxSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES; - m_minSyncPtr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_DATA_SYNC_LENGTH_SAMPLES - 2U; + m_minSyncPtr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH - 2U; if (m_minSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES) m_minSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES; - } - // Reday to start the first data section - if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH + DSTAR_RADIO_SYMBOL_LENGTH)) { + DEBUG2("DStarRX: calc sync at", m_syncPtr); + m_rxState = DSRXS_DATA; m_maxFrameCorr = 0; m_maxDataCorr = 0; @@ -458,6 +463,7 @@ void CDStarRX::processData() samplesToBits(m_dataBuffer, m_startPtr, DSTAR_DATA_LENGTH_SYMBOLS, buffer, DSTAR_DATA_LENGTH_SAMPLES); if (m_frameCount == 0U) { + DEBUG2("DStarRX: found sync at", m_syncPtr); buffer[9U] = DSTAR_DATA_SYNC_BYTES[9U]; buffer[10U] = DSTAR_DATA_SYNC_BYTES[10U]; buffer[11U] = DSTAR_DATA_SYNC_BYTES[11U]; @@ -573,15 +579,17 @@ bool CDStarRX::correlateDataSync() m_maxDataCorr = corr; m_frameCount = 0U; + m_syncPtr = m_dataPtr; + m_startPtr = m_dataPtr + DSTAR_RADIO_SYMBOL_LENGTH; if (m_startPtr >= DSTAR_DATA_LENGTH_SAMPLES) m_startPtr -= DSTAR_DATA_LENGTH_SAMPLES; - m_maxSyncPtr = m_startPtr + DSTAR_DATA_LENGTH_SAMPLES + 2U; + m_maxSyncPtr = m_syncPtr + 2U; if (m_maxSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES) m_maxSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES; - m_minSyncPtr = m_startPtr + DSTAR_DATA_LENGTH_SAMPLES - 2U; + m_minSyncPtr = m_syncPtr + DSTAR_DATA_LENGTH_SAMPLES - 2U; if (m_minSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES) m_minSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES; @@ -595,6 +603,9 @@ bool CDStarRX::correlateDataSync() void CDStarRX::samplesToBits(const q15_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit) { for (uint16_t i = 0U; i < count; i++) { + if (i == (count - 1U)) + DEBUG2("DStarRX: last pos", start); + q15_t sample = inBuffer[start]; if (sample < 0) diff --git a/DStarRX.h b/DStarRX.h index 4630e94..b28865d 100644 --- a/DStarRX.h +++ b/DStarRX.h @@ -39,12 +39,13 @@ public: private: DSRX_STATE m_rxState; uint32_t m_bitBuffer[DSTAR_RADIO_SYMBOL_LENGTH]; - q15_t m_headerBuffer[DSTAR_FEC_SECTION_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH]; + q15_t m_headerBuffer[DSTAR_FEC_SECTION_LENGTH_SAMPLES + 2U * DSTAR_RADIO_SYMBOL_LENGTH]; q15_t m_dataBuffer[DSTAR_DATA_LENGTH_SAMPLES]; uint16_t m_bitPtr; uint16_t m_headerPtr; uint16_t m_dataPtr; uint16_t m_startPtr; + uint16_t m_syncPtr; uint16_t m_minSyncPtr; uint16_t m_maxSyncPtr; q31_t m_maxFrameCorr; From ed0717543734730deffa3d0c8e88346886c55d49 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 11 Jul 2017 21:10:03 +0100 Subject: [PATCH 08/13] Tweak the settings. --- DStarRX.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/DStarRX.cpp b/DStarRX.cpp index e15a310..3cb633f 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -333,8 +333,6 @@ void CDStarRX::processNone(q15_t sample) // Fuzzy matching of the frame sync sequence bool ret = correlateFrameSync(); if (ret) { - DEBUG1("DStarRX: found frame sync in None"); - m_countdown = 5U; m_headerBuffer[m_headerPtr] = sample; @@ -383,6 +381,11 @@ void CDStarRX::processHeader(q15_t sample) m_rxState = DSRXS_NONE; m_maxFrameCorr = 0; m_maxDataCorr = 0; + } else { + io.setDecode(true); + io.setADCDetection(true); + + writeRSSIHeader(header); } } @@ -396,15 +399,15 @@ void CDStarRX::processHeader(q15_t sample) if (m_syncPtr >= DSTAR_DATA_LENGTH_SAMPLES) m_syncPtr -= DSTAR_DATA_LENGTH_SAMPLES; - m_maxSyncPtr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH + 2U; + m_maxSyncPtr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH + 1U; if (m_maxSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES) m_maxSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES; - m_minSyncPtr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH - 2U; + m_minSyncPtr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH - 1U; if (m_minSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES) m_minSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES; - DEBUG2("DStarRX: calc sync at", m_syncPtr); + DEBUG5("DStarRX: calc start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr); m_rxState = DSRXS_DATA; m_maxFrameCorr = 0; @@ -463,7 +466,8 @@ void CDStarRX::processData() samplesToBits(m_dataBuffer, m_startPtr, DSTAR_DATA_LENGTH_SYMBOLS, buffer, DSTAR_DATA_LENGTH_SAMPLES); if (m_frameCount == 0U) { - DEBUG2("DStarRX: found sync at", m_syncPtr); + DEBUG5("DStarRX: found start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr); + buffer[9U] = DSTAR_DATA_SYNC_BYTES[9U]; buffer[10U] = DSTAR_DATA_SYNC_BYTES[10U]; buffer[11U] = DSTAR_DATA_SYNC_BYTES[11U]; @@ -546,6 +550,7 @@ bool CDStarRX::correlateFrameSync() if (corr > m_maxFrameCorr) { m_maxFrameCorr = corr; m_headerPtr = 0U; + m_dataPtr = 0U; return true; } } @@ -555,7 +560,11 @@ bool CDStarRX::correlateFrameSync() bool CDStarRX::correlateDataSync() { - if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_DATA_SYNC_MASK) ^ DSTAR_DATA_SYNC_DATA) <= MAX_DATA_SYNC_BIT_ERRS) { + uint8_t maxErrs = 0U; + if (m_rxState == DSRXS_DATA) + maxErrs = MAX_DATA_SYNC_BIT_ERRS; + + if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_DATA_SYNC_MASK) ^ DSTAR_DATA_SYNC_DATA) <= maxErrs) { uint16_t ptr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_DATA_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH; if (ptr >= DSTAR_DATA_LENGTH_SAMPLES) ptr -= DSTAR_DATA_LENGTH_SAMPLES; @@ -585,11 +594,11 @@ bool CDStarRX::correlateDataSync() if (m_startPtr >= DSTAR_DATA_LENGTH_SAMPLES) m_startPtr -= DSTAR_DATA_LENGTH_SAMPLES; - m_maxSyncPtr = m_syncPtr + 2U; + m_maxSyncPtr = m_syncPtr + 1U; if (m_maxSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES) m_maxSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES; - m_minSyncPtr = m_syncPtr + DSTAR_DATA_LENGTH_SAMPLES - 2U; + m_minSyncPtr = m_syncPtr + DSTAR_DATA_LENGTH_SAMPLES - 1U; if (m_minSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES) m_minSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES; @@ -603,9 +612,6 @@ bool CDStarRX::correlateDataSync() void CDStarRX::samplesToBits(const q15_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit) { for (uint16_t i = 0U; i < count; i++) { - if (i == (count - 1U)) - DEBUG2("DStarRX: last pos", start); - q15_t sample = inBuffer[start]; if (sample < 0) From 49383ca9216c35ae68e2e2b1f82926dfd8020df5 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 16 Jul 2017 18:46:09 +0100 Subject: [PATCH 09/13] Get the RSSI working properly and simplify calculations. --- DStarRX.cpp | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/DStarRX.cpp b/DStarRX.cpp index 3cb633f..70bc4ec 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -392,26 +392,16 @@ void CDStarRX::processHeader(q15_t sample) // Ready to start the first data section if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + 2U * DSTAR_RADIO_SYMBOL_LENGTH)) { m_frameCount = 0U; + m_dataPtr = 0U; - m_startPtr = m_dataPtr; - - m_syncPtr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH; - if (m_syncPtr >= DSTAR_DATA_LENGTH_SAMPLES) - m_syncPtr -= DSTAR_DATA_LENGTH_SAMPLES; - - m_maxSyncPtr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH + 1U; - if (m_maxSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES) - m_maxSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES; - - m_minSyncPtr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH - 1U; - if (m_minSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES) - m_minSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES; + m_startPtr = 0U; + m_syncPtr = DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH; + m_maxSyncPtr = DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH + 1U; + m_minSyncPtr = DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH - 1U; DEBUG5("DStarRX: calc start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr); m_rxState = DSRXS_DATA; - m_maxFrameCorr = 0; - m_maxDataCorr = 0; } } @@ -465,12 +455,15 @@ void CDStarRX::processData() uint8_t buffer[DSTAR_DATA_LENGTH_BYTES + 2U]; samplesToBits(m_dataBuffer, m_startPtr, DSTAR_DATA_LENGTH_SYMBOLS, buffer, DSTAR_DATA_LENGTH_SAMPLES); - if (m_frameCount == 0U) { - DEBUG5("DStarRX: found start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr); + if ((m_frameCount % 21U) == 0U) { + if (m_frameCount == 0U) { + buffer[9U] = DSTAR_DATA_SYNC_BYTES[9U]; + buffer[10U] = DSTAR_DATA_SYNC_BYTES[10U]; + buffer[11U] = DSTAR_DATA_SYNC_BYTES[11U]; + + DEBUG5("DStarRX: found start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr); + } - buffer[9U] = DSTAR_DATA_SYNC_BYTES[9U]; - buffer[10U] = DSTAR_DATA_SYNC_BYTES[10U]; - buffer[11U] = DSTAR_DATA_SYNC_BYTES[11U]; writeRSSIData(buffer); } else { serial.writeDStarData(buffer, DSTAR_DATA_LENGTH_BYTES); @@ -550,7 +543,6 @@ bool CDStarRX::correlateFrameSync() if (corr > m_maxFrameCorr) { m_maxFrameCorr = corr; m_headerPtr = 0U; - m_dataPtr = 0U; return true; } } From a033b2db7b9f2eb3acc1c850c82d73ed253833ec Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 17 Jul 2017 21:16:24 +0100 Subject: [PATCH 10/13] Adjust values slightly. --- DStarRX.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DStarRX.cpp b/DStarRX.cpp index ca0a7c8..f79b236 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -383,8 +383,8 @@ void CDStarRX::processHeader(q15_t sample) m_startPtr = 0U; m_syncPtr = DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH; - m_maxSyncPtr = DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH + 1U; - m_minSyncPtr = DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH - 1U; + m_maxSyncPtr = DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH + 3U; + m_minSyncPtr = DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH - 3U; DEBUG5("DStarRX: calc start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr); From 16a43db79a8b7f7e2aa015f6f7af1a712bc9c464 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 17 Jul 2017 21:26:39 +0100 Subject: [PATCH 11/13] Further optimisation of the calculated values. --- DStarRX.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DStarRX.cpp b/DStarRX.cpp index f79b236..b444f04 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -381,10 +381,10 @@ void CDStarRX::processHeader(q15_t sample) m_frameCount = 0U; m_dataPtr = 0U; - m_startPtr = 0U; - m_syncPtr = DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH; - m_maxSyncPtr = DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH + 3U; - m_minSyncPtr = DSTAR_DATA_LENGTH_SAMPLES - DSTAR_RADIO_SYMBOL_LENGTH - 3U; + m_startPtr = 476U; + m_syncPtr = 471U; + m_maxSyncPtr = 472U; + m_minSyncPtr = 470U; DEBUG5("DStarRX: calc start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr); From e6adc0a2961e45272fc6529f00cd7e1cb5da1972 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 2 Aug 2017 20:38:46 +0100 Subject: [PATCH 12/13] Forgot the Q31 to Q15 conversion. --- DStarRX.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DStarRX.cpp b/DStarRX.cpp index 962f958..79721cd 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -304,11 +304,13 @@ void CDStarRX::samples(q15_t* samples, const uint16_t* rssi, uint8_t length) dcLevel += dcVals[i]; dcLevel /= length; + q15_t offset = q15_t(__SSAT((dcLevel >> 16), 16)); + for (uint16_t i = 0U; i < length; i++) { m_rssiAccum += rssi[i]; m_rssiCount++; - q15_t sample = samples[i] - dcLevel; + q15_t sample = samples[i] - offset; m_bitBuffer[m_bitPtr] <<= 1; if (sample < 0) From c43616f3c528ec0e1175c27526e5926fd4965623 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 13 Aug 2017 18:40:05 +0100 Subject: [PATCH 13/13] Enhancements suggested by IZ1MLT. --- DStarRX.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/DStarRX.cpp b/DStarRX.cpp index 79721cd..519c23a 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -22,12 +22,12 @@ #include "DStarRX.h" #include "Utils.h" -const unsigned int MAX_FRAMES = 75U; +const unsigned int MAX_FRAMES = 150U; // D-Star bit order version of 0x55 0x55 0x6E 0x0A const uint32_t FRAME_SYNC_DATA = 0x00557650U; const uint32_t FRAME_SYNC_MASK = 0x00FFFFFFU; -const uint8_t FRAME_SYNC_ERRS = 2U; +const uint8_t FRAME_SYNC_ERRS = 1U; // D-Star bit order version of 0x55 0x2D 0x16 const uint32_t DATA_SYNC_DATA = 0x00AAB468U; @@ -436,14 +436,12 @@ void CDStarRX::processData() } // Fuzzy matching of the data sync bit sequence - if ((m_frameCount % 21U) == 0U) { - if (m_minSyncPtr < m_maxSyncPtr) { - if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr) - correlateDataSync(); - } else { - if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr) - correlateDataSync(); - } + if (m_minSyncPtr < m_maxSyncPtr) { + if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr) + correlateDataSync(); + } else { + if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr) + correlateDataSync(); } // We've not seen a data sync for too long, signal RXLOST and change to RX_NONE