mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-30 03:38:55 -05:00
147 lines
6.3 KiB
C++
147 lines
6.3 KiB
C++
///////////////////////////////////////////////////////////////////////////////////
|
|
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
|
|
// //
|
|
// 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 //
|
|
// the Free Software Foundation as version 3 of the License, or //
|
|
// (at your option) any later version. //
|
|
// //
|
|
// This program is distributed in the hope that it will be useful, //
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
|
// GNU General Public License V3 for more details. //
|
|
// //
|
|
// You should have received a copy of the GNU General Public License //
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef INCLUDE_CHIRPCHATDEMODSINK_H
|
|
#define INCLUDE_CHIRPCHATDEMODSINK_H
|
|
|
|
#include <vector>
|
|
#include <queue>
|
|
|
|
#include "dsp/channelsamplesink.h"
|
|
#include "dsp/nco.h"
|
|
#include "dsp/interpolator.h"
|
|
#include "dsp/fftwindow.h"
|
|
#include "util/message.h"
|
|
#include "util/movingaverage.h"
|
|
|
|
#include "chirpchatdemodsettings.h"
|
|
|
|
class BasebandSampleSink;
|
|
class FFTEngine;
|
|
namespace ChirpChatDemodMsg {
|
|
class MsgDecodeSymbols;
|
|
}
|
|
class MessageQueue;
|
|
|
|
class ChirpChatDemodSink : public ChannelSampleSink {
|
|
public:
|
|
ChirpChatDemodSink();
|
|
~ChirpChatDemodSink();
|
|
|
|
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
|
|
|
|
bool getDemodActive() const { return m_demodActive; }
|
|
void setDecoderMessageQueue(MessageQueue *messageQueue) { m_decoderMsgQueue = messageQueue; }
|
|
void setSpectrumSink(BasebandSampleSink* spectrumSink) { m_spectrumSink = spectrumSink; }
|
|
void applyChannelSettings(int channelSampleRate, int bandwidth, int channelFrequencyOffset, bool force = false);
|
|
void applySettings(const ChirpChatDemodSettings& settings, bool force = false);
|
|
double getCurrentNoiseLevel() const { return m_magsqOffAvg.instantAverage() / (1<<m_settings.m_spreadFactor); }
|
|
double getTotalPower() const { return m_magsqTotalAvg.instantAverage() / (1<<m_settings.m_spreadFactor); }
|
|
|
|
private:
|
|
enum ChirpChatState
|
|
{
|
|
ChirpChatStateReset, //!< Reset everything to start all over
|
|
ChirpChatStateDetectPreamble, //!< Look for preamble
|
|
ChirpChatStatePreambleResyc, //!< Synchronize with what is left of preamble chirp
|
|
ChirpChatStatePreamble, //!< Preamble is found and look for SFD start
|
|
ChirpChatStateSkipSFD, //!< Skip SFD
|
|
ChirpChatStateReadPayload,
|
|
ChirpChatStateTest
|
|
};
|
|
|
|
ChirpChatDemodSettings m_settings;
|
|
ChirpChatState m_state;
|
|
bool m_demodActive;
|
|
ChirpChatDemodMsg::MsgDecodeSymbols *m_decodeMsg;
|
|
MessageQueue *m_decoderMsgQueue;
|
|
int m_bandwidth;
|
|
int m_channelSampleRate;
|
|
int m_channelFrequencyOffset;
|
|
unsigned int m_chirp;
|
|
unsigned int m_chirp0;
|
|
|
|
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_fftInterpolation = 2; //!< FFT interpolation factor (usually a power of 2)
|
|
|
|
FFTEngine *m_fft;
|
|
FFTEngine *m_fftSFD;
|
|
int m_fftSequence;
|
|
int m_fftSFDSequence;
|
|
FFTWindow m_fftWindow;
|
|
Complex *m_downChirps;
|
|
Complex *m_upChirps;
|
|
Complex *m_spectrumLine;
|
|
unsigned int m_fftCounter;
|
|
int m_argMaxHistory[m_requiredPreambleChirps];
|
|
unsigned int m_argMaxHistoryCounter;
|
|
unsigned int m_preambleHistory[m_maxSFDSearchChirps];
|
|
unsigned int m_syncWord;
|
|
double m_magsqMax;
|
|
MovingAverageUtil<double, double, 10> m_magsqOnAvg;
|
|
MovingAverageUtil<double, double, 10> m_magsqOffAvg;
|
|
MovingAverageUtil<double, double, 10> m_magsqTotalAvg;
|
|
std::queue<double> m_magsqQueue;
|
|
unsigned int m_chirpCount; //!< Generic chirp counter
|
|
unsigned int m_sfdSkip; //!< Number of samples in a SFD skip or slide (1/4) period
|
|
unsigned int m_sfdSkipCounter; //!< Counter of skip or slide periods
|
|
|
|
NCO m_nco;
|
|
Interpolator m_interpolator;
|
|
Real m_sampleDistanceRemain;
|
|
Real m_interpolatorDistance;
|
|
|
|
BasebandSampleSink* m_spectrumSink;
|
|
Complex *m_spectrumBuffer;
|
|
|
|
unsigned int m_nbSymbols; //!< Number of symbols = length of base FFT
|
|
unsigned int m_nbSymbolsEff; //!< effective symbols considering DE bits
|
|
unsigned int m_fftLength; //!< Length of base FFT
|
|
unsigned int m_interpolatedFFTLength; //!< Length of interpolated FFT
|
|
int m_deLength; //!< Number of FFT bins collated to represent one symbol
|
|
int m_preambleTolerance; //!< Number of FFT bins to collate when looking for preamble
|
|
|
|
void processSample(const Complex& ci);
|
|
void initSF(unsigned int sf, unsigned int deBits, FFTWindow::Function fftWindow); //!< Init tables, FFTs, depending on spread factor
|
|
void reset();
|
|
unsigned int argmax(
|
|
const Complex *fftBins,
|
|
unsigned int fftMult,
|
|
unsigned int fftLength,
|
|
double& magsqMax,
|
|
double& magSqTotal,
|
|
Complex *specBuffer,
|
|
unsigned int specDecim
|
|
);
|
|
unsigned int argmaxSpreaded( //!< count energy in adjacent bins for same symbol (needs DE bits > 0)
|
|
const Complex *fftBins,
|
|
unsigned int fftMult,
|
|
unsigned int fftLength,
|
|
double& magsqMax,
|
|
double& magsqNoise,
|
|
double& magSqTotal,
|
|
Complex *specBuffer,
|
|
unsigned int specDecim
|
|
);
|
|
void decimateSpectrum(Complex *in, Complex *out, unsigned int size, unsigned int decimation);
|
|
int toSigned(int u, int intSize);
|
|
unsigned int evalSymbol(unsigned int rawSymbol);
|
|
};
|
|
|
|
#endif // INCLUDE_CHIRPCHATDEMODSINK_H
|