mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-12-08 12:03:41 -05:00
LoRa demod: try to enhance detection
This commit is contained in:
parent
a5dc668376
commit
60db0ab868
@ -137,7 +137,7 @@ void LoRaDemodBaseband::applySettings(const LoRaDemodSettings& settings, bool fo
|
|||||||
|| (settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force)
|
|| (settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force)
|
||||||
{
|
{
|
||||||
m_channelizer->setChannelization(
|
m_channelizer->setChannelization(
|
||||||
LoRaDemodSettings::bandwidths[settings.m_bandwidthIndex],
|
LoRaDemodSettings::bandwidths[settings.m_bandwidthIndex]*LoRaDemodSettings::oversampling,
|
||||||
settings.m_inputFrequencyOffset
|
settings.m_inputFrequencyOffset
|
||||||
);
|
);
|
||||||
m_sink.applyChannelSettings(
|
m_sink.applyChannelSettings(
|
||||||
|
|||||||
@ -282,7 +282,7 @@ void LoRaDemodGUI::displaySettings()
|
|||||||
|
|
||||||
void LoRaDemodGUI::setBandwidths()
|
void LoRaDemodGUI::setBandwidths()
|
||||||
{
|
{
|
||||||
int maxBandwidth = m_basebandSampleRate;
|
int maxBandwidth = m_basebandSampleRate/LoRaDemodSettings::oversampling;
|
||||||
int maxIndex = 0;
|
int maxIndex = 0;
|
||||||
|
|
||||||
for (; (maxIndex < LoRaDemodSettings::nbBandwidths) && (LoRaDemodSettings::bandwidths[maxIndex] <= maxBandwidth); maxIndex++)
|
for (; (maxIndex < LoRaDemodSettings::nbBandwidths) && (LoRaDemodSettings::bandwidths[maxIndex] <= maxBandwidth); maxIndex++)
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
const int LoRaDemodSettings::bandwidths[] = {2500, 7813, 10417, 15625, 20833, 31250, 41667, 62500, 125000, 250000, 500000};
|
const int LoRaDemodSettings::bandwidths[] = {2500, 7813, 10417, 15625, 20833, 31250, 41667, 62500, 125000, 250000, 500000};
|
||||||
const int LoRaDemodSettings::nbBandwidths = 11;
|
const int LoRaDemodSettings::nbBandwidths = 11;
|
||||||
|
const int LoRaDemodSettings::oversampling = 2;
|
||||||
|
|
||||||
LoRaDemodSettings::LoRaDemodSettings() :
|
LoRaDemodSettings::LoRaDemodSettings() :
|
||||||
m_inputFrequencyOffset(0),
|
m_inputFrequencyOffset(0),
|
||||||
|
|||||||
@ -40,6 +40,7 @@ struct LoRaDemodSettings
|
|||||||
|
|
||||||
static const int bandwidths[];
|
static const int bandwidths[];
|
||||||
static const int nbBandwidths;
|
static const int nbBandwidths;
|
||||||
|
static const int oversampling;
|
||||||
|
|
||||||
LoRaDemodSettings();
|
LoRaDemodSettings();
|
||||||
void resetToDefaults();
|
void resetToDefaults();
|
||||||
|
|||||||
@ -30,7 +30,8 @@ LoRaDemodSink::LoRaDemodSink() :
|
|||||||
m_spectrumBuffer(nullptr),
|
m_spectrumBuffer(nullptr),
|
||||||
m_downChirps(nullptr),
|
m_downChirps(nullptr),
|
||||||
m_upChirps(nullptr),
|
m_upChirps(nullptr),
|
||||||
m_fftBuffer(nullptr)
|
m_fftBuffer(nullptr),
|
||||||
|
m_spectrumLine(nullptr)
|
||||||
{
|
{
|
||||||
m_bandwidth = LoRaDemodSettings::bandwidths[0];
|
m_bandwidth = LoRaDemodSettings::bandwidths[0];
|
||||||
m_channelSampleRate = 96000;
|
m_channelSampleRate = 96000;
|
||||||
@ -47,7 +48,7 @@ LoRaDemodSink::LoRaDemodSink() :
|
|||||||
m_fft = FFTEngine::create();
|
m_fft = FFTEngine::create();
|
||||||
m_fftSFD = FFTEngine::create();
|
m_fftSFD = FFTEngine::create();
|
||||||
|
|
||||||
initSF(m_settings.m_spreadFactor);
|
initSF(m_settings.m_spreadFactor, m_settings.m_deBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
LoRaDemodSink::~LoRaDemodSink()
|
LoRaDemodSink::~LoRaDemodSink()
|
||||||
@ -57,9 +58,10 @@ LoRaDemodSink::~LoRaDemodSink()
|
|||||||
delete[] m_downChirps;
|
delete[] m_downChirps;
|
||||||
delete[] m_upChirps;
|
delete[] m_upChirps;
|
||||||
delete[] m_spectrumBuffer;
|
delete[] m_spectrumBuffer;
|
||||||
|
delete[] m_spectrumLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoRaDemodSink::initSF(unsigned int sf)
|
void LoRaDemodSink::initSF(unsigned int sf, unsigned int deBits)
|
||||||
{
|
{
|
||||||
if (m_downChirps) {
|
if (m_downChirps) {
|
||||||
delete[] m_downChirps;
|
delete[] m_downChirps;
|
||||||
@ -73,8 +75,12 @@ void LoRaDemodSink::initSF(unsigned int sf)
|
|||||||
if (m_spectrumBuffer) {
|
if (m_spectrumBuffer) {
|
||||||
delete[] m_spectrumBuffer;
|
delete[] m_spectrumBuffer;
|
||||||
}
|
}
|
||||||
|
if (m_spectrumLine) {
|
||||||
|
delete[] m_spectrumLine;
|
||||||
|
}
|
||||||
|
|
||||||
m_nbSymbols = 1 << sf;
|
m_nbSymbols = 1 << sf;
|
||||||
|
m_nbSymbolsEff = 1 << (sf - deBits);
|
||||||
m_fftLength = m_nbSymbols;
|
m_fftLength = m_nbSymbols;
|
||||||
m_fft->configure(m_fftInterpolation*m_fftLength, false);
|
m_fft->configure(m_fftInterpolation*m_fftLength, false);
|
||||||
m_fftSFD->configure(m_fftInterpolation*m_fftLength, false);
|
m_fftSFD->configure(m_fftInterpolation*m_fftLength, false);
|
||||||
@ -82,22 +88,28 @@ void LoRaDemodSink::initSF(unsigned int sf)
|
|||||||
m_sfdSkip = m_fftLength / 4;
|
m_sfdSkip = m_fftLength / 4;
|
||||||
m_fftWindow.create(FFTWindow::Function::Kaiser, m_fftLength);
|
m_fftWindow.create(FFTWindow::Function::Kaiser, m_fftLength);
|
||||||
m_fftWindow.setKaiserAlpha(M_PI);
|
m_fftWindow.setKaiserAlpha(M_PI);
|
||||||
m_downChirps = new Complex[2*m_nbSymbols]; // Each table is 2 chirps long to allow memcpying from arbitrary offsets.
|
m_downChirps = new Complex[2*m_nbSymbols]; // Each table is 2 chirps long to allow processing from arbitrary offsets.
|
||||||
m_upChirps = new Complex[2*m_nbSymbols];
|
m_upChirps = new Complex[2*m_nbSymbols];
|
||||||
m_fftBuffer = new Complex[m_fftInterpolation*m_fftLength];
|
m_fftBuffer = new Complex[m_fftInterpolation*m_fftLength];
|
||||||
m_spectrumBuffer = new Complex[m_nbSymbols];
|
m_spectrumBuffer = new Complex[m_nbSymbols];
|
||||||
|
m_spectrumLine = new Complex[m_nbSymbols];
|
||||||
|
std::fill(m_spectrumLine, m_spectrumLine+m_nbSymbols, Complex(std::polar(1e-6*SDR_RX_SCALED, 0.0)));
|
||||||
|
|
||||||
float halfAngle = M_PI;
|
float halfAngle = M_PI;
|
||||||
float phase = -halfAngle;
|
float phase = -halfAngle;
|
||||||
double accumulator = 0;
|
double accumulator = 0;
|
||||||
|
|
||||||
for (int i = 0; i < 2*m_nbSymbols; i++)
|
for (int i = 0; i < m_fftLength; i++)
|
||||||
{
|
{
|
||||||
accumulator = fmod(accumulator + phase, 2*M_PI);
|
accumulator = fmod(accumulator + phase, 2*M_PI);
|
||||||
m_downChirps[i] = Complex(std::conj(std::polar(1.0, accumulator)));
|
m_downChirps[i] = Complex(std::conj(std::polar(1.0, accumulator)));
|
||||||
m_upChirps[i] = Complex(std::polar(1.0, accumulator));
|
m_upChirps[i] = Complex(std::polar(1.0, accumulator));
|
||||||
phase += (2*halfAngle) / m_nbSymbols;
|
phase += (2*halfAngle) / m_nbSymbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Duplicate table to allow processing from arbitrary offsets
|
||||||
|
std::copy(m_downChirps, m_downChirps+m_fftLength, m_downChirps+m_fftLength);
|
||||||
|
std::copy(m_upChirps, m_upChirps+m_fftLength, m_upChirps+m_fftLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoRaDemodSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
|
void LoRaDemodSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
|
||||||
@ -166,22 +178,36 @@ void LoRaDemodSink::processSample(const Complex& ci)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preambleFound)
|
if ((preambleFound) && (m_magsq > 1e-9))
|
||||||
{
|
{
|
||||||
if (m_spectrumSink) {
|
if (m_spectrumSink) {
|
||||||
m_spectrumSink->feed(m_spectrumBuffer, m_nbSymbols);
|
m_spectrumSink->feed(m_spectrumBuffer, m_nbSymbols);
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug("LoRaDemodSink::processSample: preamble found: %u|%f", m_argMaxHistory[0], m_magsq);
|
qDebug("LoRaDemodSink::processSample: preamble found: %u|%f", m_argMaxHistory[0], m_magsq);
|
||||||
m_chirp0 = m_argMaxHistory[0];
|
m_chirp = m_argMaxHistory[0];
|
||||||
m_chirp = m_chirp0;
|
m_fftCounter = m_chirp;
|
||||||
m_fftCounter = 0;
|
m_chirp0 = 0;
|
||||||
m_chirpCount = 0;
|
m_chirpCount = 0;
|
||||||
|
m_state = LoRaStatePreambleResyc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_state == LoRaStatePreambleResyc)
|
||||||
|
{
|
||||||
|
m_fftCounter++;
|
||||||
|
|
||||||
|
if (m_fftCounter == m_fftLength)
|
||||||
|
{
|
||||||
|
if (m_spectrumSink) {
|
||||||
|
m_spectrumSink->feed(m_spectrumLine, m_nbSymbols);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_fftCounter = 0;
|
||||||
m_state = LoRaStatePreamble;
|
m_state = LoRaStatePreamble;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (m_state == LoRaStatePreamble) // preamble found look for SFD start
|
else if (m_state == LoRaStatePreamble) // preamble found look for SFD start
|
||||||
{
|
{
|
||||||
m_fft->in()[m_fftCounter] = ci * m_downChirps[m_chirp]; // de-chirp the up ramp
|
m_fft->in()[m_fftCounter] = ci * m_downChirps[m_chirp]; // de-chirp the up ramp
|
||||||
@ -234,12 +260,29 @@ void LoRaDemodSink::processSample(const Complex& ci)
|
|||||||
{
|
{
|
||||||
m_syncWord = round(m_preambleHistory[m_chirpCount-2] / 8.0);
|
m_syncWord = round(m_preambleHistory[m_chirpCount-2] / 8.0);
|
||||||
m_syncWord += 16 * round(m_preambleHistory[m_chirpCount-3] / 8.0);
|
m_syncWord += 16 * round(m_preambleHistory[m_chirpCount-3] / 8.0);
|
||||||
qDebug("LoRaDemodSink::processSample: SFD found: up: %u|%f down: %u|%f sync: %x", imax, magsq, imaxSFD, magsqSFD, m_syncWord);
|
qDebug("LoRaDemodSink::processSample: SFD found: up: %4u|%11.6f - down: %4u|%11.6f sync: %x", imax, magsq, imaxSFD, magsqSFD, m_syncWord);
|
||||||
|
|
||||||
|
int sadj = 0;
|
||||||
|
int nadj = 0;
|
||||||
|
int zadj;
|
||||||
|
int sfdSkip = m_sfdSkip;
|
||||||
|
|
||||||
|
for (int i = 0; i < m_chirpCount-3; i++)
|
||||||
|
{
|
||||||
|
sadj += m_preambleHistory[i] > m_nbSymbols/2 ? m_preambleHistory[i] - m_nbSymbols : m_preambleHistory[i];
|
||||||
|
nadj++;
|
||||||
|
}
|
||||||
|
|
||||||
|
zadj = nadj == 0 ? 0 : sadj / nadj;
|
||||||
|
zadj = zadj < -(sfdSkip/2) ? -(sfdSkip/2) : zadj > sfdSkip/2 ? sfdSkip/2 : zadj;
|
||||||
|
qDebug("LoRaDemodSink::processSample: zero adjust: %d (%d)", zadj, nadj);
|
||||||
|
|
||||||
m_sfdSkipCounter = 0;
|
m_sfdSkipCounter = 0;
|
||||||
m_fftCounter = m_fftLength - m_sfdSkip;
|
m_fftCounter = m_fftLength - m_sfdSkip + zadj;
|
||||||
std::copy(m_fftBuffer+m_sfdSkip, m_fftBuffer+(m_fftLength-m_sfdSkip), m_fftBuffer); // prepare sliding fft
|
m_chirp += zadj;
|
||||||
m_state = LoRaStateSlideSFD;
|
//std::copy(m_fftBuffer+m_sfdSkip, m_fftBuffer+(m_fftLength-m_sfdSkip), m_fftBuffer); // prepare sliding fft
|
||||||
m_magsq = magsqSFD;
|
m_magsq = magsqSFD;
|
||||||
|
m_state = LoRaStateSkipSFD; //LoRaStateSlideSFD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_chirpCount > m_maxSFDSearchChirps) // SFD missed start over
|
else if (m_chirpCount > m_maxSFDSearchChirps) // SFD missed start over
|
||||||
@ -252,7 +295,7 @@ void LoRaDemodSink::processSample(const Complex& ci)
|
|||||||
m_spectrumSink->feed(m_spectrumBuffer, m_nbSymbols);
|
m_spectrumSink->feed(m_spectrumBuffer, m_nbSymbols);
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug("LoRaDemodSink::processSample: SFD search: up: %u|%f down: %u|%f", imax, magsq, imaxSFD, magsqSFD);
|
qDebug("LoRaDemodSink::processSample: SFD search: up: %4u|%11.6f - down: %4u|%11.6f", imax, magsq, imaxSFD, magsqSFD);
|
||||||
m_magsq = magsq;
|
m_magsq = magsq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -302,7 +345,11 @@ void LoRaDemodSink::processSample(const Complex& ci)
|
|||||||
m_fftInterpolation
|
m_fftInterpolation
|
||||||
) / m_fftInterpolation;
|
) / m_fftInterpolation;
|
||||||
|
|
||||||
qDebug("LoRaDemodSink::processSample: SFD slide %u %u|%f", m_sfdSkipCounter, imaxSFD, magsqSFD);
|
if (m_spectrumSink) {
|
||||||
|
m_spectrumSink->feed(m_spectrumBuffer, m_nbSymbols);
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug("LoRaDemodSink::processSample: SFD slide %u %4u|%11.6f", m_sfdSkipCounter, imaxSFD, magsqSFD);
|
||||||
|
|
||||||
if (m_sfdSkipCounter == m_sfdFourths) // 1.25 SFD chips length
|
if (m_sfdSkipCounter == m_sfdFourths) // 1.25 SFD chips length
|
||||||
{
|
{
|
||||||
@ -328,7 +375,7 @@ void LoRaDemodSink::processSample(const Complex& ci)
|
|||||||
m_fftCounter = 0;
|
m_fftCounter = 0;
|
||||||
double magsq;
|
double magsq;
|
||||||
|
|
||||||
unsigned int symbol = round(
|
unsigned int symbol = evalSymbol(
|
||||||
argmax(
|
argmax(
|
||||||
m_fft->out(),
|
m_fft->out(),
|
||||||
m_fftInterpolation,
|
m_fftInterpolation,
|
||||||
@ -336,8 +383,8 @@ void LoRaDemodSink::processSample(const Complex& ci)
|
|||||||
magsq,
|
magsq,
|
||||||
m_spectrumBuffer,
|
m_spectrumBuffer,
|
||||||
m_fftInterpolation
|
m_fftInterpolation
|
||||||
) / ((float) m_fftInterpolation * (1<<m_settings.m_deBits))
|
)
|
||||||
);
|
) % m_nbSymbolsEff;
|
||||||
|
|
||||||
if (m_spectrumSink) {
|
if (m_spectrumSink) {
|
||||||
m_spectrumSink->feed(m_spectrumBuffer, m_nbSymbols);
|
m_spectrumSink->feed(m_spectrumBuffer, m_nbSymbols);
|
||||||
@ -439,6 +486,17 @@ int LoRaDemodSink::toSigned(int u, int intSize)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int LoRaDemodSink::evalSymbol(unsigned int rawSymbol)
|
||||||
|
{
|
||||||
|
unsigned int spread = m_fftInterpolation * (1<<m_settings.m_deBits);
|
||||||
|
|
||||||
|
if (spread < 2 ) {
|
||||||
|
return rawSymbol;
|
||||||
|
} else {
|
||||||
|
return (rawSymbol + spread/2 - 1) / spread; // middle point goes to symbol below (smear to the right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LoRaDemodSink::applyChannelSettings(int channelSampleRate, int bandwidth, int channelFrequencyOffset, bool force)
|
void LoRaDemodSink::applyChannelSettings(int channelSampleRate, int bandwidth, int channelFrequencyOffset, bool force)
|
||||||
{
|
{
|
||||||
qDebug() << "LoRaDemodSink::applyChannelSettings:"
|
qDebug() << "LoRaDemodSink::applyChannelSettings:"
|
||||||
@ -455,7 +513,7 @@ void LoRaDemodSink::applyChannelSettings(int channelSampleRate, int bandwidth, i
|
|||||||
if ((channelSampleRate != m_channelSampleRate) ||
|
if ((channelSampleRate != m_channelSampleRate) ||
|
||||||
(bandwidth != m_bandwidth) || force)
|
(bandwidth != m_bandwidth) || force)
|
||||||
{
|
{
|
||||||
m_interpolator.create(16, channelSampleRate, bandwidth / 1.9f);
|
m_interpolator.create(16, channelSampleRate, bandwidth / 1.25f);
|
||||||
m_interpolatorDistance = (Real) channelSampleRate / (Real) bandwidth;
|
m_interpolatorDistance = (Real) channelSampleRate / (Real) bandwidth;
|
||||||
m_sampleDistanceRemain = 0;
|
m_sampleDistanceRemain = 0;
|
||||||
qDebug() << "LoRaDemodSink::applyChannelSettings: m_interpolator.create:"
|
qDebug() << "LoRaDemodSink::applyChannelSettings: m_interpolator.create:"
|
||||||
@ -477,8 +535,9 @@ void LoRaDemodSink::applySettings(const LoRaDemodSettings& settings, bool force)
|
|||||||
<< " m_title: " << settings.m_title
|
<< " m_title: " << settings.m_title
|
||||||
<< " force: " << force;
|
<< " force: " << force;
|
||||||
|
|
||||||
if ((settings.m_spreadFactor != m_settings.m_spreadFactor) || force) {
|
if ((settings.m_spreadFactor != m_settings.m_spreadFactor)
|
||||||
initSF(settings.m_spreadFactor);
|
|| (settings.m_deBits != m_settings.m_deBits) || force) {
|
||||||
|
initSF(settings.m_spreadFactor, settings.m_deBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
|
|||||||
@ -36,7 +36,6 @@ public:
|
|||||||
LoRaDemodSink();
|
LoRaDemodSink();
|
||||||
~LoRaDemodSink();
|
~LoRaDemodSink();
|
||||||
|
|
||||||
void initSF(unsigned int sf); //!< Init tables, FFTs, depending on spread factor
|
|
||||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
|
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
|
||||||
|
|
||||||
void setSpectrumSink(BasebandSampleSink* spectrumSink) { m_spectrumSink = spectrumSink; }
|
void setSpectrumSink(BasebandSampleSink* spectrumSink) { m_spectrumSink = spectrumSink; }
|
||||||
@ -48,6 +47,7 @@ private:
|
|||||||
{
|
{
|
||||||
LoRaStateReset, //!< Reset everything to start all over
|
LoRaStateReset, //!< Reset everything to start all over
|
||||||
LoRaStateDetectPreamble, //!< Look for preamble
|
LoRaStateDetectPreamble, //!< Look for preamble
|
||||||
|
LoRaStatePreambleResyc, //!< Synchronize with what is left of preamble chirp
|
||||||
LoRaStatePreamble, //!< Preamble is found and look for SFD start
|
LoRaStatePreamble, //!< Preamble is found and look for SFD start
|
||||||
LoRaStateSkipSFD, //!< Skip SFD
|
LoRaStateSkipSFD, //!< Skip SFD
|
||||||
LoRaStateSlideSFD, //!< Sliding FFTs while going through SFD (not the skip option)
|
LoRaStateSlideSFD, //!< Sliding FFTs while going through SFD (not the skip option)
|
||||||
@ -66,7 +66,7 @@ private:
|
|||||||
static const unsigned int m_requiredPreambleChirps = 4; //!< Number of chirps required to estimate preamble
|
static const unsigned int m_requiredPreambleChirps = 4; //!< Number of chirps required to estimate preamble
|
||||||
static const unsigned int m_maxSFDSearchChirps = 8; //!< Maximum number of chirps when looking for SFD after preamble detection
|
static const unsigned int m_maxSFDSearchChirps = 8; //!< Maximum number of chirps when looking for SFD after preamble detection
|
||||||
static const unsigned int m_sfdFourths = 5; //!< Number of SFD chip period fourths to skip until payload
|
static const unsigned int m_sfdFourths = 5; //!< Number of SFD chip period fourths to skip until payload
|
||||||
static const unsigned int m_fftInterpolation = 1; //!< FFT interpolation factor (usually a power of 2)
|
static const unsigned int m_fftInterpolation = 2; //!< FFT interpolation factor (usually a power of 2)
|
||||||
|
|
||||||
FFTEngine *m_fft;
|
FFTEngine *m_fft;
|
||||||
FFTEngine *m_fftSFD;
|
FFTEngine *m_fftSFD;
|
||||||
@ -74,6 +74,7 @@ private:
|
|||||||
Complex *m_downChirps;
|
Complex *m_downChirps;
|
||||||
Complex *m_upChirps;
|
Complex *m_upChirps;
|
||||||
Complex *m_fftBuffer;
|
Complex *m_fftBuffer;
|
||||||
|
Complex *m_spectrumLine;
|
||||||
unsigned int m_fftCounter;
|
unsigned int m_fftCounter;
|
||||||
unsigned int m_argMaxHistory[m_requiredPreambleChirps];
|
unsigned int m_argMaxHistory[m_requiredPreambleChirps];
|
||||||
unsigned int m_argMaxHistoryCounter;
|
unsigned int m_argMaxHistoryCounter;
|
||||||
@ -93,9 +94,11 @@ private:
|
|||||||
Complex *m_spectrumBuffer;
|
Complex *m_spectrumBuffer;
|
||||||
|
|
||||||
unsigned int m_nbSymbols;
|
unsigned int m_nbSymbols;
|
||||||
|
unsigned int m_nbSymbolsEff; //!< effective symbols considering DE bits
|
||||||
unsigned int m_fftLength;
|
unsigned int m_fftLength;
|
||||||
|
|
||||||
void processSample(const Complex& ci);
|
void processSample(const Complex& ci);
|
||||||
|
void initSF(unsigned int sf, unsigned int deBits); //!< Init tables, FFTs, depending on spread factor
|
||||||
void reset();
|
void reset();
|
||||||
unsigned int argmax(
|
unsigned int argmax(
|
||||||
const Complex *fftBins,
|
const Complex *fftBins,
|
||||||
@ -107,6 +110,7 @@ private:
|
|||||||
);
|
);
|
||||||
void decimateSpectrum(Complex *in, Complex *out, unsigned int size, unsigned int decimation);
|
void decimateSpectrum(Complex *in, Complex *out, unsigned int size, unsigned int decimation);
|
||||||
int toSigned(int u, int intSize);
|
int toSigned(int u, int intSize);
|
||||||
|
unsigned int evalSymbol(unsigned int rawSymbol);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Interleaving is "easiest" if the same number of bits is used per symbol as for FEC
|
Interleaving is "easiest" if the same number of bits is used per symbol as for FEC
|
||||||
|
|||||||
@ -8,11 +8,11 @@
|
|||||||
const PluginDescriptor LoRaPlugin::m_pluginDescriptor = {
|
const PluginDescriptor LoRaPlugin::m_pluginDescriptor = {
|
||||||
LoRaDemod::m_channelId,
|
LoRaDemod::m_channelId,
|
||||||
QString("LoRa Demodulator"),
|
QString("LoRa Demodulator"),
|
||||||
QString("4.12.3"),
|
QString("5.2.0"),
|
||||||
QString("(c) 2015 John Greb"),
|
QString("(c) Edouard Griffiths, F4EXB"),
|
||||||
QString("http://www.maintech.de"),
|
QString("https://github.com/f4exb/sdrangel"),
|
||||||
true,
|
true,
|
||||||
QString("github.com/hexameron/rtl-sdrangelove")
|
QString("https://github.com/f4exb/sdrangel")
|
||||||
};
|
};
|
||||||
|
|
||||||
LoRaPlugin::LoRaPlugin(QObject* parent) :
|
LoRaPlugin::LoRaPlugin(QObject* parent) :
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user