mirror of https://github.com/g4klx/MMDVM.git
Cleanups but still untested.
This commit is contained in:
parent
9a7b07027a
commit
b15933bf8a
34
DMRDMORX.cpp
34
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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
|
|
12
P25Defines.h
12
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;
|
||||
|
|
|
@ -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
|
||||
|
|
341
YSFRX.cpp
341
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) {
|
||||
|
|
10
YSFRX.h
10
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);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue