diff --git a/DMRDMORX.cpp b/DMRDMORX.cpp index 42eb4b8..3347e55 100644 --- a/DMRDMORX.cpp +++ b/DMRDMORX.cpp @@ -46,9 +46,11 @@ m_bitBuffer(), m_buffer(), m_bitPtr(0U), m_dataPtr(0U), -m_syncPtr(0U), +m_syncPtr(NOENDPTR), m_startPtr(0U), m_endPtr(NOENDPTR), +m_minSyncPtr(NOENDPTR), +m_maxSyncPtr(NOENDPTR), m_maxCorr(0), m_centre(), m_centreVal(0), @@ -69,7 +71,9 @@ m_rssi() void CDMRDMORX::reset() { - m_syncPtr = 0U; + m_syncPtr = NOENDPTR; + m_minSyncPtr = NOENDPTR; + m_maxSyncPtr = NOENDPTR; m_maxCorr = 0; m_control = CONTROL_NONE; m_syncCount = 0U; @@ -96,7 +100,7 @@ void CDMRDMORX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t leng bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi) { m_buffer[m_dataPtr] = sample; - m_rssi[m_dataPtr] = rssi; + m_rssi[m_dataPtr] = rssi; m_bitBuffer[m_bitPtr] <<= 1; if (sample < 0) @@ -105,19 +109,11 @@ bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi) if (m_state == DMORXS_NONE) { correlateSync(true); } else { - uint16_t min = m_syncPtr + DMO_BUFFER_LENGTH_SAMPLES - 1U; - uint16_t max = m_syncPtr + 1U; - - if (min >= DMO_BUFFER_LENGTH_SAMPLES) - min -= DMO_BUFFER_LENGTH_SAMPLES; - if (max >= DMO_BUFFER_LENGTH_SAMPLES) - max -= DMO_BUFFER_LENGTH_SAMPLES; - - if (min < max) { - if (m_dataPtr >= min && m_dataPtr <= max) + if (m_minSyncPtr < m_maxSyncPtr) { + if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr) correlateSync(false); } else { - if (m_dataPtr >= min || m_dataPtr <= max) + if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr) correlateSync(false); } } @@ -125,7 +121,7 @@ bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi) if (m_dataPtr == m_endPtr) { if (m_control == CONTROL_DATA || m_control == CONTROL_VOICE) { m_threshold[m_averagePtr] = m_thresholdBest; - m_centre[m_averagePtr] = m_centreBest; + m_centre[m_averagePtr] = m_centreBest; m_averagePtr++; if (m_averagePtr >= 4U) @@ -134,6 +130,14 @@ bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi) // Find the average centre and threshold values m_centreVal = (m_centre[0U] + m_centre[1U] + m_centre[2U] + m_centre[3U]) >> 2; m_thresholdVal = (m_threshold[0U] + m_threshold[1U] + m_threshold[2U] + m_threshold[3U]) >> 2; + + m_minSyncPtr = m_syncPtr + DMO_BUFFER_LENGTH_SAMPLES - 1U; + if (m_minSyncPtr >= DMO_BUFFER_LENGTH_SAMPLES) + m_minSyncPtr -= DMO_BUFFER_LENGTH_SAMPLES; + + m_maxSyncPtr = m_syncPtr + 1U; + if (m_maxSyncPtr >= DMO_BUFFER_LENGTH_SAMPLES) + m_maxSyncPtr -= DMO_BUFFER_LENGTH_SAMPLES; } uint8_t frame[DMR_FRAME_LENGTH_BYTES + 3U]; diff --git a/DMRDMORX.h b/DMRDMORX.h index 6cabb62..6638767 100644 --- a/DMRDMORX.h +++ b/DMRDMORX.h @@ -48,6 +48,8 @@ private: uint16_t m_syncPtr; uint16_t m_startPtr; uint16_t m_endPtr; + uint16_t m_minSyncPtr; + uint16_t m_maxSyncPtr; q31_t m_maxCorr; q15_t m_centre[4U]; q15_t m_centreVal; diff --git a/DMRIdleRX.cpp b/DMRIdleRX.cpp index 8205150..b000f9c 100644 --- a/DMRIdleRX.cpp +++ b/DMRIdleRX.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2016 by Jonathan Naylor G4KLX + * Copyright (C) 2009-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 @@ -150,7 +150,7 @@ void CDMRIdleRX::processSample(q15_t sample) } m_endPtr = NOENDPTR; - m_maxCorr = 0U; + m_maxCorr = 0; } m_dataPtr++; diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index ad87573..78d014b 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -125,7 +125,6 @@ bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi) if (m_dataPtr >= SCAN_START && m_dataPtr <= SCAN_END) correlateSync(true); } else { - uint16_t min = m_syncPtr - 1U; uint16_t max = m_syncPtr + 1U; if (m_dataPtr >= min && m_dataPtr <= max) @@ -310,8 +309,8 @@ void CDMRSlotRX::correlateSync(bool first) m_centreBest = m_centreVal = m_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre; m_averagePtr = 0U; } else { - m_thresholdBest = threshold; - m_centreBest = centre; + m_thresholdBest = threshold; + m_centreBest = centre; } m_maxCorr = corr; @@ -331,8 +330,8 @@ void CDMRSlotRX::correlateSync(bool first) m_centreBest = m_centreVal = m_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre; m_averagePtr = 0U; } else { - m_thresholdBest = threshold; - m_centreBest = centre; + m_thresholdBest = threshold; + m_centreBest = centre; } m_maxCorr = corr; diff --git a/P25Defines.h b/P25Defines.h index da21229..21c2ff0 100644 --- a/P25Defines.h +++ b/P25Defines.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 by Jonathan Naylor G4KLX + * Copyright (C) 2016,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 @@ -24,25 +24,31 @@ const unsigned int P25_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate const unsigned int P25_HDR_FRAME_LENGTH_BYTES = 99U; const unsigned int P25_HDR_FRAME_LENGTH_BITS = P25_HDR_FRAME_LENGTH_BYTES * 8U; const unsigned int P25_HDR_FRAME_LENGTH_SYMBOLS = P25_HDR_FRAME_LENGTH_BYTES * 4U; +const unsigned int P25_HDR_FRAME_LENGTH_SAMPLES = P25_HDR_FRAME_LENGTH_SYMBOLS * P25_RADIO_SYMBOL_LENGTH; const unsigned int P25_LDU_FRAME_LENGTH_BYTES = 216U; const unsigned int P25_LDU_FRAME_LENGTH_BITS = P25_LDU_FRAME_LENGTH_BYTES * 8U; const unsigned int P25_LDU_FRAME_LENGTH_SYMBOLS = P25_LDU_FRAME_LENGTH_BYTES * 4U; +const unsigned int P25_LDU_FRAME_LENGTH_SAMPLES = P25_LDU_FRAME_LENGTH_SYMBOLS * P25_RADIO_SYMBOL_LENGTH; const unsigned int P25_TERMLC_FRAME_LENGTH_BYTES = 54U; const unsigned int P25_TERMLC_FRAME_LENGTH_BITS = P25_TERMLC_FRAME_LENGTH_BYTES * 8U; const unsigned int P25_TERMLC_FRAME_LENGTH_SYMBOLS = P25_TERMLC_FRAME_LENGTH_BYTES * 4U; +const unsigned int P25_TERMLC_FRAME_LENGTH_SAMPLES = P25_TERMLC_FRAME_LENGTH_SYMBOLS * P25_RADIO_SYMBOL_LENGTH; const unsigned int P25_TERM_FRAME_LENGTH_BYTES = 18U; const unsigned int P25_TERM_FRAME_LENGTH_BITS = P25_TERM_FRAME_LENGTH_BYTES * 8U; const unsigned int P25_TERM_FRAME_LENGTH_SYMBOLS = P25_TERM_FRAME_LENGTH_BYTES * 4U; +const unsigned int P25_TERM_FRAME_LENGTH_SAMPLES = P25_TERM_FRAME_LENGTH_SYMBOLS * P25_RADIO_SYMBOL_LENGTH; const unsigned int P25_SYNC_LENGTH_BYTES = 6U; const unsigned int P25_SYNC_LENGTH_BITS = P25_SYNC_LENGTH_BYTES * 8U; const unsigned int P25_SYNC_LENGTH_SYMBOLS = P25_SYNC_LENGTH_BYTES * 4U; +const unsigned int P25_SYNC_LENGTH_SAMPLES = P25_SYNC_LENGTH_SYMBOLS * P25_RADIO_SYMBOL_LENGTH; -const unsigned int P25_NID_LENGTH_BITS = 64U; -const unsigned int P25_NID_LENGTH_SYMBOLS = 32U; +const unsigned int P25_NID_LENGTH_BITS = 64U; +const unsigned int P25_NID_LENGTH_SYMBOLS = 32U; +const unsigned int P25_NID_LENGTH_SAMPLESS = P25_NID_LENGTH_SYMBOLS * P25_RADIO_SYMBOL_LENGTH; const uint8_t P25_SYNC_BYTES[] = {0x55U, 0x75U, 0xF5U, 0xFFU, 0x77U, 0xFFU}; const uint8_t P25_SYNC_BYTES_LENGTH = 6U; diff --git a/YSFDefines.h b/YSFDefines.h index 029683c..c724451 100644 --- a/YSFDefines.h +++ b/YSFDefines.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2015 by Jonathan Naylor G4KLX + * Copyright (C) 2016,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 diff --git a/YSFRX.cpp b/YSFRX.cpp index 0052c6f..daf738a 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -20,7 +20,7 @@ #include "Config.h" #include "Globals.h" -#include "DMRIdleRX.h" +#include "YSFRX.h" #include "Utils.h" const q15_t SCALING_FACTOR = 18750; // Q15(0.55) @@ -44,9 +44,8 @@ m_bitPtr(0U), m_dataPtr(0U), m_endPtr(NOENDPTR), m_syncPtr(NOENDPTR), -m_syncStartPtr(NOENDPTR), -m_syncEndPtr(NOENDPTR), -m_syncCheck(false), +m_minSyncPtr(NOENDPTR), +m_maxSyncPtr(NOENDPTR), m_maxCorr(0), m_lostCount(0U), m_centre(), @@ -70,11 +69,10 @@ void CYSFRX::reset() m_averagePtr = 0U; m_endPtr = NOENDPTR; m_syncPtr = NOENDPTR; - m_syncStartPtr = NOENDPTR; - m_syncEndPtr = NOENDPTR; + m_minSyncPtr = NOENDPTR; + m_maxSyncPtr = NOENDPTR; m_centreVal = 0; m_thresholdVal = 0; - m_syncCheck = false; m_lostCount = 0U; m_rssiAccum = 0U; m_rssiCount = 0U; @@ -83,24 +81,145 @@ void CYSFRX::reset() void CYSFRX::samples(const q15_t* samples, uint16_t* rssi, uint8_t length) { for (uint8_t i = 0U; i < length; i++) { + q15_t sample = samples[i]; + m_rssiAccum += rssi[i]; m_rssiCount++; + m_bitBuffer[m_bitPtr] <<= 1; + if (sample < 0) + m_bitBuffer[m_bitPtr] |= 0x01U; + + m_buffer[m_dataPtr] = sample; + if (m_state == YSFRXS_NONE) - processNone(samples[i]); + processNone(sample); else - processData(samples[i]); + processData(sample); + + m_dataPtr++; + if (m_dataPtr >= YSF_FRAME_LENGTH_SAMPLES) + m_dataPtr = 0U; + + m_bitPtr++; + if (m_bitPtr >= YSF_RADIO_SYMBOL_LENGTH) + m_bitPtr = 0U; } } void CYSFRX::processNone(q15_t sample) { - m_bitBuffer[m_bitPtr] <<= 1; - if (sample < 0) - m_bitBuffer[m_bitPtr] |= 0x01U; + bool ret = correlateSync(true); + if (ret) { + m_rssiAccum = 0U; + m_rssiCount = 0U; - m_buffer[m_dataPtr] = sample; + io.setDecode(true); + io.setADCDetection(true); + } + if (m_dataPtr == m_endPtr) { + m_centreVal = m_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = m_centreBest; + m_thresholdVal = m_threshold[0U] = m_threshold[1U] = m_threshold[2U] = m_threshold[3U] = m_thresholdBest; + m_averagePtr = 0U; + + DEBUG4("YSFRX: sync found in None pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal); + + uint16_t ptr = m_endPtr + YSF_RADIO_SYMBOL_LENGTH + 1U; + if (ptr >= YSF_FRAME_LENGTH_SAMPLES) + ptr -= YSF_FRAME_LENGTH_SAMPLES; + + m_minSyncPtr = m_syncPtr + YSF_FRAME_LENGTH_SAMPLES - 1U; + if (m_minSyncPtr >= YSF_FRAME_LENGTH_SAMPLES) + m_minSyncPtr -= YSF_FRAME_LENGTH_SAMPLES; + + m_maxSyncPtr = m_syncPtr + 1U; + if (m_maxSyncPtr >= YSF_FRAME_LENGTH_SAMPLES) + m_maxSyncPtr -= YSF_FRAME_LENGTH_SAMPLES; + + uint8_t frame[YSF_FRAME_LENGTH_BYTES + 3U]; + samplesToBits(ptr, YSF_FRAME_LENGTH_SYMBOLS, frame, 8U, m_centreVal, m_thresholdVal); + + frame[0U] = 0x01U; + writeRSSIData(frame); + + // Start the next frame + ::memset(frame, 0x00U, YSF_FRAME_LENGTH_BYTES + 3U); + + m_state = YSFRXS_DATA; + m_maxCorr = 0; + } +} + +void CYSFRX::processData(q15_t sample) +{ + if (m_minSyncPtr < m_maxSyncPtr) { + if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr) + correlateSync(false); + } else { + if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr) + correlateSync(false); + } + + if (m_dataPtr == m_endPtr) { + uint16_t ptr = m_endPtr + YSF_RADIO_SYMBOL_LENGTH + 1U; + if (ptr >= YSF_FRAME_LENGTH_SAMPLES) + ptr -= YSF_FRAME_LENGTH_SAMPLES; + + // Only update the centre and threshold if they are from a good sync + if (m_lostCount == MAX_SYNC_FRAMES) { + m_threshold[m_averagePtr] = m_thresholdBest; + m_centre[m_averagePtr] = m_centreBest; + + m_averagePtr++; + if (m_averagePtr >= 4U) + m_averagePtr = 0U; + + // Find the average centre and threshold values + m_centreVal = (m_centre[0U] + m_centre[1U] + m_centre[2U] + m_centre[3U]) >> 2; + m_thresholdVal = (m_threshold[0U] + m_threshold[1U] + m_threshold[2U] + m_threshold[3U]) >> 2; + + DEBUG4("YSFRX: sync found in Data pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal); + + m_minSyncPtr = m_syncPtr + YSF_FRAME_LENGTH_SAMPLES - 1U; + if (m_minSyncPtr >= YSF_FRAME_LENGTH_SAMPLES) + m_minSyncPtr -= YSF_FRAME_LENGTH_SAMPLES; + + m_maxSyncPtr = m_syncPtr + 1U; + if (m_maxSyncPtr >= YSF_FRAME_LENGTH_SAMPLES) + m_maxSyncPtr -= YSF_FRAME_LENGTH_SAMPLES; + } + + uint8_t frame[YSF_FRAME_LENGTH_BYTES + 3U]; + samplesToBits(ptr, YSF_FRAME_LENGTH_SYMBOLS, frame, 8U, m_centreVal, m_thresholdVal); + + // We've not seen a data sync for too long, signal RXLOST and change to RX_NONE + m_lostCount--; + if (m_lostCount == 0U) { + DEBUG1("YSFRX: sync timed out, lost lock"); + + io.setDecode(false); + io.setADCDetection(false); + + serial.writeYSFLost(); + + m_state = YSFRXS_NONE; + m_endPtr = NOENDPTR; + } else { + frame[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; + + writeRSSIData(frame); + + // Start the next frame + ::memset(frame, 0x00U, YSF_FRAME_LENGTH_BYTES + 3U); + } + + m_maxCorr = 0; + } +} + +bool CYSFRX::correlateSync(bool none) +{ if (countBits32((m_bitBuffer[m_bitPtr] & YSF_SYNC_SYMBOLS_MASK) ^ YSF_SYNC_SYMBOLS) <= MAX_SYNC_SYMBOLS_ERRS) { uint16_t ptr = m_dataPtr + YSF_FRAME_LENGTH_SAMPLES - YSF_SYNC_LENGTH_SAMPLES + YSF_RADIO_SYMBOL_LENGTH; if (ptr >= YSF_FRAME_LENGTH_SAMPLES) @@ -108,7 +227,7 @@ void CYSFRX::processNone(q15_t sample) q31_t corr = 0; q15_t max = -16000; - q15_t min = 16000; + q15_t min = 16000; uint32_t mask = 0x00080000U; for (uint8_t i = 0U; i < YSF_SYNC_LENGTH_SYMBOLS; i++, mask >>= 1) { @@ -138,208 +257,42 @@ void CYSFRX::processNone(q15_t sample) if (ptr >= YSF_FRAME_LENGTH_SAMPLES) ptr -= YSF_FRAME_LENGTH_SAMPLES; - samplesToBits(ptr, YSF_SYNC_LENGTH_SYMBOLS, sync, 0U, centre, threshold); + if (none) + samplesToBits(ptr, YSF_SYNC_LENGTH_SYMBOLS, sync, 0U, centre, threshold); + else + samplesToBits(ptr, YSF_SYNC_LENGTH_SYMBOLS, sync, 0U, m_centreVal, m_thresholdVal); uint8_t errs = 0U; for (uint8_t i = 0U; i < YSF_SYNC_BYTES_LENGTH; i++) errs += countBits8(sync[i] ^ YSF_SYNC_BYTES[i]); if (errs <= MAX_SYNC_BYTES_ERRS) { - DEBUG4("YSFRX: sync found in None pos/centre/threshold", m_dataPtr, centre, threshold); + DEBUG4("YSFRX: prov sync found pos/centre/threshold", m_dataPtr, centre, threshold); m_maxCorr = corr; - m_thresholdBest = m_thresholdVal = m_threshold[0U] = m_threshold[1U] = m_threshold[2U] = m_threshold[3U] = threshold; - m_centreBest = m_centreVal = m_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre; - m_averagePtr = 0U; - m_rssiAccum = 0U; - m_rssiCount = 0U; + m_thresholdBest = threshold; + m_centreBest = centre; m_lostCount = MAX_SYNC_FRAMES; m_syncPtr = m_dataPtr; - io.setDecode(true); - io.setADCDetection(true); - m_endPtr = m_dataPtr + YSF_FRAME_LENGTH_SAMPLES - YSF_SYNC_LENGTH_SAMPLES - 1U; if (m_endPtr >= YSF_FRAME_LENGTH_SAMPLES) m_endPtr -= YSF_FRAME_LENGTH_SAMPLES; + + return true; } } } - if (m_dataPtr == m_endPtr) { - uint16_t ptr = m_endPtr + YSF_RADIO_SYMBOL_LENGTH + 1U; - if (ptr >= YSF_FRAME_LENGTH_SAMPLES) - ptr -= YSF_FRAME_LENGTH_SAMPLES; - - uint8_t frame[YSF_FRAME_LENGTH_BYTES + 3U]; - samplesToBits(ptr, YSF_FRAME_LENGTH_SYMBOLS, frame, 8U, m_centreVal, m_thresholdVal); - - frame[0U] = 0x01U; - writeRSSIData(frame); - - // Start the next frame - ::memset(frame, 0x00U, YSF_FRAME_LENGTH_BYTES + 3U); - - m_syncStartPtr = m_syncPtr + YSF_FRAME_LENGTH_SAMPLES - 2U; - if (m_syncStartPtr >= YSF_FRAME_LENGTH_SAMPLES) - m_syncStartPtr -= YSF_FRAME_LENGTH_SAMPLES; - - m_syncEndPtr = m_syncPtr + 2U; - if (m_syncEndPtr >= YSF_FRAME_LENGTH_SAMPLES) - m_syncEndPtr -= YSF_FRAME_LENGTH_SAMPLES; - - m_syncCheck = false; - m_state = YSFRXS_DATA; - m_maxCorr = 0U; - } - - m_dataPtr++; - if (m_dataPtr >= YSF_FRAME_LENGTH_SAMPLES) - m_dataPtr = 0U; - - m_bitPtr++; - if (m_bitPtr >= YSF_RADIO_SYMBOL_LENGTH) - m_bitPtr = 0U; -} - -void CYSFRX::processData(q15_t sample) -{ - m_bitBuffer[m_bitPtr] <<= 1; - if (sample < 0) - m_bitBuffer[m_bitPtr] |= 0x01U; - - m_buffer[m_dataPtr] = sample; - - if (m_dataPtr == m_syncStartPtr) m_syncCheck = true; - if (m_dataPtr == m_syncEndPtr) m_syncCheck = false; - - if (m_syncCheck) { - if (countBits32((m_bitBuffer[m_bitPtr] & YSF_SYNC_SYMBOLS_MASK) ^ YSF_SYNC_SYMBOLS) <= MAX_SYNC_SYMBOLS_ERRS) { - uint16_t ptr = m_dataPtr + YSF_FRAME_LENGTH_SAMPLES - YSF_SYNC_LENGTH_SAMPLES + YSF_RADIO_SYMBOL_LENGTH; - if (ptr >= YSF_FRAME_LENGTH_SAMPLES) - ptr -= YSF_FRAME_LENGTH_SAMPLES; - - q31_t corr = 0; - q15_t max = -16000; - q15_t min = 16000; - - uint32_t mask = 0x00080000U; - for (uint8_t i = 0U; i < YSF_SYNC_LENGTH_SYMBOLS; i++, mask >>= 1) { - bool b = (YSF_SYNC_SYMBOLS & mask) == mask; - - if (m_buffer[ptr] > max) - max = m_buffer[ptr]; - if (m_buffer[ptr] < min) - min = m_buffer[ptr]; - - corr += b ? -m_buffer[ptr] : m_buffer[ptr]; - - ptr += YSF_RADIO_SYMBOL_LENGTH; - if (ptr >= YSF_FRAME_LENGTH_SAMPLES) - ptr -= YSF_FRAME_LENGTH_SAMPLES; - } - - if (corr > m_maxCorr) { - q15_t centre = (max + min) >> 1; - - q31_t v1 = (max - centre) * SCALING_FACTOR; - q15_t threshold = q15_t(v1 >> 15); - - uint16_t ptr = m_dataPtr + YSF_FRAME_LENGTH_SAMPLES - YSF_SYNC_LENGTH_SAMPLES + YSF_RADIO_SYMBOL_LENGTH; - if (ptr >= YSF_FRAME_LENGTH_SAMPLES) - ptr -= YSF_FRAME_LENGTH_SAMPLES; - - uint8_t sync[YSF_SYNC_BYTES_LENGTH]; - samplesToBits(ptr, YSF_SYNC_LENGTH_SYMBOLS, sync, 0U, m_centreVal, m_thresholdVal); - - uint8_t errs = 0U; - for (uint8_t i = 0U; i < YSF_SYNC_BYTES_LENGTH; i++) - errs += countBits8(sync[i] ^ YSF_SYNC_BYTES[i]); - - if (errs <= MAX_SYNC_BYTES_ERRS) { - DEBUG4("YSFRX: sync found in Data pos/centre/threshold", m_dataPtr, centre, threshold); - m_maxCorr = corr; - m_lostCount = MAX_SYNC_FRAMES; - m_syncPtr = m_dataPtr; - m_centreBest = centre; - m_thresholdBest = threshold; - - m_endPtr = m_dataPtr + YSF_FRAME_LENGTH_SAMPLES - YSF_SYNC_LENGTH_SAMPLES - 1U; - if (m_endPtr >= YSF_FRAME_LENGTH_SAMPLES) - m_endPtr -= YSF_FRAME_LENGTH_SAMPLES; - } - } - } - } - - if (m_dataPtr == m_endPtr) { - uint16_t ptr = m_endPtr + YSF_RADIO_SYMBOL_LENGTH + 1U; - if (ptr >= YSF_FRAME_LENGTH_SAMPLES) - ptr -= YSF_FRAME_LENGTH_SAMPLES; - - // Only update the centre and threshold if they are from a good sync - if (m_lostCount == MAX_SYNC_FRAMES) { - m_threshold[m_averagePtr] = m_thresholdBest; - m_centre[m_averagePtr] = m_centreBest; - - m_averagePtr++; - if (m_averagePtr >= 4U) - m_averagePtr = 0U; - - // Find the average centre and threshold values - m_centreVal = (m_centre[0U] + m_centre[1U] + m_centre[2U] + m_centre[3U]) >> 2; - m_thresholdVal = (m_threshold[0U] + m_threshold[1U] + m_threshold[2U] + m_threshold[3U]) >> 2; - } - - uint8_t frame[YSF_FRAME_LENGTH_BYTES + 3U]; - samplesToBits(ptr, YSF_FRAME_LENGTH_SYMBOLS, frame, 8U, m_centreVal, m_thresholdVal); - - // We've not seen a data sync for too long, signal RXLOST and change to RX_NONE - m_lostCount--; - if (m_lostCount == 0U) { - DEBUG1("YSFRX: sync timed out, lost lock"); - - io.setDecode(false); - io.setADCDetection(false); - - serial.writeYSFLost(); - - m_state = YSFRXS_NONE; - m_endPtr = NOENDPTR; - } else { - frame[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; - - writeRSSIData(frame); - - m_syncStartPtr = m_syncPtr + YSF_FRAME_LENGTH_SAMPLES - 2U; - if (m_syncStartPtr >= YSF_FRAME_LENGTH_SAMPLES) - m_syncStartPtr -= YSF_FRAME_LENGTH_SAMPLES; - - m_syncEndPtr = m_syncPtr + 2U; - if (m_syncEndPtr >= YSF_FRAME_LENGTH_SAMPLES) - m_syncEndPtr -= YSF_FRAME_LENGTH_SAMPLES; - - // Start the next frame - ::memset(frame, 0x00U, YSF_FRAME_LENGTH_BYTES + 3U); - } - - m_syncCheck = false; - m_maxCorr = 0U; - m_centreBest = 0; - m_thresholdBest = 0; - } - - m_dataPtr++; - if (m_dataPtr >= YSF_FRAME_LENGTH_SAMPLES) - m_dataPtr = 0U; - - m_bitPtr++; - if (m_bitPtr >= YSF_RADIO_SYMBOL_LENGTH) - m_bitPtr = 0U; + return false; } void CYSFRX::samplesToBits(uint16_t start, uint16_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold) { for (uint16_t i = 0U; i < count; i++) { + if (i == (YSF_SYNC_LENGTH_SYMBOLS - 1U)) { + DEBUG5("YSFRX: i/sync/samples/count", i, m_syncPtr, start, count); + } + q15_t sample = m_buffer[start] - centre; if (sample < -threshold) { diff --git a/YSFRX.h b/YSFRX.h index c64b7c8..34a440b 100644 --- a/YSFRX.h +++ b/YSFRX.h @@ -23,8 +23,8 @@ #include "YSFDefines.h" enum YSFRX_STATE { - YSFRXS_NONE, - YSFRXS_DATA + YSFRXS_NONE, + YSFRXS_DATA }; class CYSFRX { @@ -42,10 +42,9 @@ private: uint16_t m_bitPtr; uint16_t m_dataPtr; uint16_t m_endPtr; + uint16_t m_minSyncPtr; + uint16_t m_maxSyncPtr; uint16_t m_syncPtr; - uint16_t m_syncStartPtr; - uint16_t m_syncEndPtr; - bool m_syncCheck; q31_t m_maxCorr; uint16_t m_lostCount; q15_t m_centre[4U]; @@ -60,6 +59,7 @@ private: void processNone(q15_t sample); void processData(q15_t sample); + bool correlateSync(bool none); void samplesToBits(uint16_t start, uint16_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); void writeRSSIData(uint8_t* data); };