1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-09-05 14:47:50 -04:00

DATV demod: fixed compilation warnings

This commit is contained in:
f4exb 2018-02-25 00:07:08 +01:00
parent 2e5cfcafee
commit 3354c774fc
11 changed files with 4361 additions and 3427 deletions

View File

@ -16,9 +16,9 @@ if(LIBDSDCC_FOUND AND LIBMBE_FOUND)
add_subdirectory(demoddsd) add_subdirectory(demoddsd)
endif(LIBDSDCC_FOUND AND LIBMBE_FOUND) endif(LIBDSDCC_FOUND AND LIBMBE_FOUND)
if (NOT RX_SAMPLE_24BIT) #if (NOT RX_SAMPLE_24BIT)
add_subdirectory(demoddatv) add_subdirectory(demoddatv)
endif() #endif()
if (BUILD_DEBIAN) if (BUILD_DEBIAN)
add_subdirectory(demoddsd) add_subdirectory(demoddsd)

View File

@ -24,8 +24,6 @@ set(datv_FORMS
datvdemodgui.ui datvdemodgui.ui
) )
set (CMAKE_CXX_FLAGS "-Wno-unused-variable -Wno-deprecated-declarations")
include_directories( include_directories(
. .
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}

View File

@ -31,25 +31,32 @@ namespace leansdr
template<typename T> struct datvconstellation: runnable template<typename T> struct datvconstellation: runnable
{ {
T xymin, xymax; T xymin;
T xymax;
unsigned long decimation; unsigned long decimation;
unsigned long pixels_per_frame; unsigned long pixels_per_frame;
cstln_lut<256> **cstln; // Optional ptr to optional constellation cstln_lut<256> **cstln; // Optional ptr to optional constellation
pipereader<complex<T> > in;
unsigned long phase;
DATVScreen *m_objDATVScreen; DATVScreen *m_objDATVScreen;
datvconstellation(
datvconstellation(scheduler *sch, pipebuf< complex<T> > &_in, T _xymin, T _xymax, const char *_name=NULL, DATVScreen * objDATVScreen=NULL) : scheduler *sch,
pipebuf<complex<T> > &_in,
T _xymin,
T _xymax,
const char *_name = 0,
DATVScreen * objDATVScreen = 0) :
runnable(sch, _name ? _name : _in.name), runnable(sch, _name ? _name : _in.name),
xymin(_xymin), xymin(_xymin),
xymax(_xymax), xymax(_xymax),
decimation(DEFAULT_GUI_DECIMATION), decimation(DEFAULT_GUI_DECIMATION),
pixels_per_frame(1024), pixels_per_frame(1024),
cstln(NULL), cstln(0),
in(_in), in(_in),
phase(0), phase(0),
m_objDATVScreen(objDATVScreen) m_objDATVScreen(objDATVScreen)
{ {
} }
void run() void run()
@ -69,8 +76,11 @@ namespace leansdr
if (m_objDATVScreen != NULL) if (m_objDATVScreen != NULL)
{ {
m_objDATVScreen->selectRow(256*(p->re-xymin)/(xymax-xymin)); m_objDATVScreen->selectRow(
m_objDATVScreen->setDataColor(256- 256*((p->im-xymin)/(xymax-xymin)),255,0,255); 256 * (p->re - xymin) / (xymax - xymin));
m_objDATVScreen->setDataColor(
256 - 256 * ((p->im - xymin) / (xymax - xymin)),
255, 0, 255);
} }
} }
@ -109,8 +119,6 @@ namespace leansdr
} }
//private: //private:
pipereader< complex<T> > in;
unsigned long phase;
//gfx g; //gfx g;
void draw_begin() void draw_begin()

View File

@ -38,21 +38,22 @@ MESSAGE_CLASS_DEFINITION(DATVDemod::MsgConfigureChannelizer, Message)
DATVDemod::DATVDemod(DeviceSourceAPI *deviceAPI) : DATVDemod::DATVDemod(DeviceSourceAPI *deviceAPI) :
ChannelSinkAPI(m_channelIdURI), ChannelSinkAPI(m_channelIdURI),
m_deviceAPI(deviceAPI),
m_objSettingsMutex(QMutex::NonRecursive),
m_objRegisteredDATVScreen(NULL),
m_objVideoStream(NULL),
m_objRegisteredVideoRender(NULL),
m_objRenderThread(NULL),
m_enmModulation(BPSK /*DATV_FM1*/),
m_blnNeedConfigUpdate(false), m_blnNeedConfigUpdate(false),
m_blnRenderingVideo(false) m_deviceAPI(deviceAPI),
m_objRegisteredDATVScreen(NULL),
m_objRegisteredVideoRender(NULL),
m_objVideoStream(NULL),
m_objRenderThread(NULL),
m_blnRenderingVideo(false),
m_enmModulation(BPSK /*DATV_FM1*/),
m_objSettingsMutex(QMutex::NonRecursive)
{ {
setObjectName("DATVDemod"); setObjectName("DATVDemod");
qDebug("DATVDemod::DATVDemod: sizeof FixReal: %lu: SDR_RX_SAMP_SZ: %u", sizeof(FixReal), (unsigned int) SDR_RX_SAMP_SZ);
//*************** DATV PARAMETERS *************** //*************** DATV PARAMETERS ***************
m_blnInitialized=false; m_blnInitialized=false;
CleanUpDATVFramework(false); CleanUpDATVFramework();
m_objVideoStream = new DATVideostream(); m_objVideoStream = new DATVideostream();
@ -102,6 +103,7 @@ DATVDemod::~DATVDemod()
bool DATVDemod::SetDATVScreen(DATVScreen *objScreen) bool DATVDemod::SetDATVScreen(DATVScreen *objScreen)
{ {
m_objRegisteredDATVScreen = objScreen; m_objRegisteredDATVScreen = objScreen;
return true;
} }
DATVideostream * DATVDemod::SetVideoRender(DATVideoRender *objScreen) DATVideostream * DATVDemod::SetVideoRender(DATVideoRender *objScreen)
@ -240,185 +242,185 @@ void DATVDemod::InitDATVParameters(int intMsps,
m_blnInitialized=true; m_blnInitialized=true;
} }
void DATVDemod::CleanUpDATVFramework(bool blnRelease) void DATVDemod::CleanUpDATVFramework()
{ {
//if(blnRelease==true) //if(blnRelease==true)
if(false) // if (false)
{ // {
if(m_objScheduler!=NULL) // if(m_objScheduler!=NULL)
{ // {
m_objScheduler->shutdown(); // m_objScheduler->shutdown();
delete m_objScheduler; // delete m_objScheduler;
} // }
//
// // INPUT
// if(p_rawiq!=NULL) delete p_rawiq;
// if(p_rawiq_writer!=NULL) delete p_rawiq_writer;
// if(p_preprocessed!=NULL) delete p_preprocessed;
//
// // NOTCH FILTER
// if(r_auto_notch!=NULL) delete r_auto_notch;
// if(p_autonotched!=NULL) delete p_autonotched;
//
// // FREQUENCY CORRECTION : DEROTATOR
// if(p_derot!=NULL) delete p_derot;
// if(r_derot!=NULL) delete r_derot;
//
// // CNR ESTIMATION
// if(p_cnr!=NULL) delete p_cnr;
// if(r_cnr!=NULL) delete r_cnr;
//
// //FILTERING
// if(r_resample!=NULL) delete r_resample;
// if(p_resampled!=NULL) delete p_resampled;
// if(coeffs!=NULL) delete coeffs;
//
// // OUTPUT PREPROCESSED DATA
// if(sampler!=NULL) delete sampler;
// if(coeffs_sampler!=NULL) delete coeffs_sampler;
// if(p_symbols!=NULL) delete p_symbols;
// if(p_freq!=NULL) delete p_freq;
// if(p_ss!=NULL) delete p_ss;
// if(p_mer!=NULL) delete p_mer;
// if(p_sampled!=NULL) delete p_sampled;
//
// //DECIMATION
// if(p_decimated!=NULL) delete p_decimated;
// if(p_decim!=NULL) delete p_decim;
// if(r_ppout!=NULL) delete r_ppout;
//
// //GENERIC CONSTELLATION RECEIVER
// if(m_objDemodulator!=NULL) delete m_objDemodulator;
//
// //DECONVOLUTION AND SYNCHRONIZATION
// if(p_bytes!=NULL) delete p_bytes;
// if(r_deconv!=NULL) delete r_deconv;
// if(r!=NULL) delete r;
// if(p_descrambled!=NULL) delete p_descrambled;
// if(p_frames!=NULL) delete p_frames;
// if(r_etr192_descrambler!=NULL) delete r_etr192_descrambler;
// if(r_sync!=NULL) delete r_sync;
// if(p_mpegbytes!=NULL) delete p_mpegbytes;
// if(p_lock!=NULL) delete p_lock;
// if(p_locktime!=NULL) delete p_locktime;
// if(r_sync_mpeg!=NULL) delete r_sync_mpeg;
//
//
// // DEINTERLEAVING
// if(p_rspackets!=NULL) delete p_rspackets;
// if(r_deinter!=NULL) delete r_deinter;
// if(p_vbitcount!=NULL) delete p_vbitcount;
// if(p_verrcount!=NULL) delete p_verrcount;
// if(p_rtspackets!=NULL) delete p_rtspackets;
// if(r_rsdec!=NULL) delete r_rsdec;
//
// //BER ESTIMATION
// if(p_vber!=NULL) delete p_vber;
// if(r_vber!=NULL) delete r_vber;
//
// // DERANDOMIZATION
// if(p_tspackets!=NULL) delete p_tspackets;
// if(r_derand!=NULL) delete r_derand;
//
//
// //OUTPUT : To remove
// if(r_stdout!=NULL) delete r_stdout;
// if(r_videoplayer!=NULL) delete r_videoplayer;
//
// //CONSTELLATION
// if(r_scope_symbols!=NULL) delete r_scope_symbols;
//
// }
// INPUT m_objScheduler = 0;
if(p_rawiq!=NULL) delete p_rawiq;
if(p_rawiq_writer!=NULL) delete p_rawiq_writer;
if(p_preprocessed!=NULL) delete p_preprocessed;
// NOTCH FILTER
if(r_auto_notch!=NULL) delete r_auto_notch;
if(p_autonotched!=NULL) delete p_autonotched;
// FREQUENCY CORRECTION : DEROTATOR
if(p_derot!=NULL) delete p_derot;
if(r_derot!=NULL) delete r_derot;
// CNR ESTIMATION
if(p_cnr!=NULL) delete p_cnr;
if(r_cnr!=NULL) delete r_cnr;
//FILTERING
if(r_resample!=NULL) delete r_resample;
if(p_resampled!=NULL) delete p_resampled;
if(coeffs!=NULL) delete coeffs;
// OUTPUT PREPROCESSED DATA
if(sampler!=NULL) delete sampler;
if(coeffs_sampler!=NULL) delete coeffs_sampler;
if(p_symbols!=NULL) delete p_symbols;
if(p_freq!=NULL) delete p_freq;
if(p_ss!=NULL) delete p_ss;
if(p_mer!=NULL) delete p_mer;
if(p_sampled!=NULL) delete p_sampled;
//DECIMATION
if(p_decimated!=NULL) delete p_decimated;
if(p_decim!=NULL) delete p_decim;
if(r_ppout!=NULL) delete r_ppout;
//GENERIC CONSTELLATION RECEIVER
if(m_objDemodulator!=NULL) delete m_objDemodulator;
//DECONVOLUTION AND SYNCHRONIZATION
if(p_bytes!=NULL) delete p_bytes;
if(r_deconv!=NULL) delete r_deconv;
if(r!=NULL) delete r;
if(p_descrambled!=NULL) delete p_descrambled;
if(p_frames!=NULL) delete p_frames;
if(r_etr192_descrambler!=NULL) delete r_etr192_descrambler;
if(r_sync!=NULL) delete r_sync;
if(p_mpegbytes!=NULL) delete p_mpegbytes;
if(p_lock!=NULL) delete p_lock;
if(p_locktime!=NULL) delete p_locktime;
if(r_sync_mpeg!=NULL) delete r_sync_mpeg;
// DEINTERLEAVING
if(p_rspackets!=NULL) delete p_rspackets;
if(r_deinter!=NULL) delete r_deinter;
if(p_vbitcount!=NULL) delete p_vbitcount;
if(p_verrcount!=NULL) delete p_verrcount;
if(p_rtspackets!=NULL) delete p_rtspackets;
if(r_rsdec!=NULL) delete r_rsdec;
//BER ESTIMATION
if(p_vber!=NULL) delete p_vber;
if(r_vber!=NULL) delete r_vber;
// DERANDOMIZATION
if(p_tspackets!=NULL) delete p_tspackets;
if(r_derand!=NULL) delete r_derand;
//OUTPUT : To remove
if(r_stdout!=NULL) delete r_stdout;
if(r_videoplayer!=NULL) delete r_videoplayer;
//CONSTELLATION
if(r_scope_symbols!=NULL) delete r_scope_symbols;
}
m_objScheduler=NULL;
// INPUT // INPUT
p_rawiq = NULL; p_rawiq = 0;
p_rawiq_writer = NULL; p_rawiq_writer = 0;
p_preprocessed = NULL; p_preprocessed = 0;
// NOTCH FILTER // NOTCH FILTER
r_auto_notch = NULL; r_auto_notch = 0;
p_autonotched = NULL; p_autonotched = 0;
// FREQUENCY CORRECTION : DEROTATOR // FREQUENCY CORRECTION : DEROTATOR
p_derot = NULL; p_derot = 0;
r_derot=NULL; r_derot = 0;
// CNR ESTIMATION // CNR ESTIMATION
p_cnr = NULL; p_cnr = 0;
r_cnr = NULL; r_cnr = 0;
//FILTERING //FILTERING
r_resample = NULL; r_resample = 0;
p_resampled = NULL; p_resampled = 0;
coeffs = NULL; coeffs = 0;
ncoeffs = 0; ncoeffs = 0;
// OUTPUT PREPROCESSED DATA // OUTPUT PREPROCESSED DATA
sampler = NULL; sampler = 0;
coeffs_sampler=NULL; coeffs_sampler = 0;
ncoeffs_sampler = 0; ncoeffs_sampler = 0;
p_symbols = NULL; p_symbols = 0;
p_freq = NULL; p_freq = 0;
p_ss = NULL; p_ss = 0;
p_mer = NULL; p_mer = 0;
p_sampled = NULL; p_sampled = 0;
//DECIMATION //DECIMATION
p_decimated = NULL; p_decimated = 0;
p_decim = NULL; p_decim = 0;
r_ppout = NULL; r_ppout = 0;
//GENERIC CONSTELLATION RECEIVER //GENERIC CONSTELLATION RECEIVER
m_objDemodulator = NULL; m_objDemodulator = 0;
//DECONVOLUTION AND SYNCHRONIZATION //DECONVOLUTION AND SYNCHRONIZATION
p_bytes=NULL; p_bytes = 0;
r_deconv=NULL; r_deconv = 0;
r = NULL; r = 0;
p_descrambled = NULL; p_descrambled = 0;
p_frames = NULL; p_frames = 0;
r_etr192_descrambler = NULL; r_etr192_descrambler = 0;
r_sync = NULL; r_sync = 0;
p_mpegbytes = NULL; p_mpegbytes = 0;
p_lock = NULL; p_lock = 0;
p_locktime = NULL; p_locktime = 0;
r_sync_mpeg = NULL; r_sync_mpeg = 0;
// DEINTERLEAVING // DEINTERLEAVING
p_rspackets = NULL; p_rspackets = 0;
r_deinter = NULL; r_deinter = 0;
p_vbitcount = NULL; p_vbitcount = 0;
p_verrcount = NULL; p_verrcount = 0;
p_rtspackets = NULL; p_rtspackets = 0;
r_rsdec = NULL; r_rsdec = 0;
//BER ESTIMATION //BER ESTIMATION
p_vber = NULL; p_vber = 0;
r_vber = NULL; r_vber = 0;
// DERANDOMIZATION // DERANDOMIZATION
p_tspackets = NULL; p_tspackets = 0;
r_derand = NULL; r_derand = 0;
//OUTPUT : To remove //OUTPUT : To remove
r_stdout = NULL; r_stdout = 0;
r_videoplayer = NULL; r_videoplayer = 0;
//CONSTELLATION //CONSTELLATION
r_scope_symbols = NULL; r_scope_symbols = 0;
} }
void DATVDemod::InitDATVFramework() void DATVDemod::InitDATVFramework()
@ -516,7 +518,7 @@ void DATVDemod::InitDATVFramework()
m_lngExpectedReadIQ = BUF_BASEBAND; m_lngExpectedReadIQ = BUF_BASEBAND;
CleanUpDATVFramework(true); CleanUpDATVFramework();
m_objScheduler = new scheduler(); m_objScheduler = new scheduler();
@ -819,7 +821,7 @@ void DATVDemod::InitDATVFramework()
m_blnDVBInitialized=true; m_blnDVBInitialized=true;
} }
void DATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst) void DATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused)))
{ {
float fltI; float fltI;
float fltQ; float fltQ;
@ -964,12 +966,12 @@ bool DATVDemod::handleMessage(const Message& cmd)
m_channelizer->configure(m_channelizer->getInputMessageQueue(), m_channelizer->configure(m_channelizer->getInputMessageQueue(),
m_channelizer->getInputSampleRate(), m_channelizer->getInputSampleRate(),
m_objRunning.intCenterFrequency); cfg.getCenterFrequency());
//m_objRunning.intCenterFrequency);
qDebug() << "DATVDemod::handleMessage: MsgConfigureChannelizer: sampleRate: " << m_channelizer->getInputSampleRate()
<< " centerFrequency: " << cfg.getCenterFrequency();
qDebug() << "ATVDemod::handleMessage: MsgConfigureChannelizer: sampleRate: " << m_channelizer->getInputSampleRate() //<< " centerFrequency: " << m_objRunning.intCenterFrequency;
<< " centerFrequency: " << m_objRunning.intCenterFrequency;
return true; return true;
} }

View File

@ -43,8 +43,6 @@ class DownChannelizer;
#endif #endif
#include "datvconstellation.h" #include "datvconstellation.h"
#include "datvvideoplayer.h" #include "datvvideoplayer.h"
@ -70,11 +68,24 @@ class DownChannelizer;
using namespace leansdr; using namespace leansdr;
enum DATVModulation { BPSK, QPSK, PSK8, APSK16, APSK32, APSK64E, QAM16, QAM64, QAM256 }; enum DATVModulation
enum dvb_version { DVB_S, DVB_S2 }; {
enum dvb_sampler { SAMP_NEAREST, SAMP_LINEAR, SAMP_RRC }; BPSK, QPSK, PSK8, APSK16, APSK32, APSK64E, QAM16, QAM64, QAM256
};
enum dvb_version
{
DVB_S, DVB_S2
};
enum dvb_sampler
{
SAMP_NEAREST, SAMP_LINEAR, SAMP_RRC
};
inline int decimation(float Fin, float Fout) { int d = Fin / Fout; return max(d, 1); } inline int decimation(float Fin, float Fout)
{
int d = Fin / Fout;
return max(d, 1);
}
struct config struct config
{ {
@ -104,14 +115,16 @@ struct config
bool packetized; // Output frames with 16-bit BE length bool packetized; // Output frames with 16-bit BE length
float Finfo; // Desired refresh rate on fd_info (Hz) float Finfo; // Desired refresh rate on fd_info (Hz)
config() : buf_factor(4), config() :
standard(DVB_S),
sampler(SAMP_LINEAR),
buf_factor(4),
Fs(2.4e6), Fs(2.4e6),
Fderot(0), Fderot(0),
anf(1), anf(1),
cnr(false), cnr(false),
decim(0), decim(0),
Fm(2e6), Fm(2e6),
standard(DVB_S),
constellation(cstln_lut<256>::QPSK), constellation(cstln_lut<256>::QPSK),
fec(FEC12), fec(FEC12),
Ftune(0), Ftune(0),
@ -121,7 +134,6 @@ struct config
hard_metric(false), hard_metric(false),
resample(false), resample(false),
resample_rej(10), resample_rej(10),
sampler(SAMP_LINEAR),
rrc_steps(0), rrc_steps(0),
rrc_rej(10), rrc_rej(10),
rolloff(0.35), rolloff(0.35),
@ -132,7 +144,6 @@ struct config
} }
}; };
struct DATVConfig struct DATVConfig
{ {
int intMsps; int intMsps;
@ -171,27 +182,66 @@ struct DATVConfig
} }
}; };
class DATVDemod: public BasebandSampleSink, public ChannelSinkAPI class DATVDemod: public BasebandSampleSink, public ChannelSinkAPI
{ {
Q_OBJECT Q_OBJECT
public: public:
class MsgConfigureChannelizer: public Message
{
MESSAGE_CLASS_DECLARATION
public:
int getCenterFrequency() const
{
return m_centerFrequency;
}
static MsgConfigureChannelizer* create(int centerFrequency)
{
return new MsgConfigureChannelizer(centerFrequency);
}
private:
int m_centerFrequency;
MsgConfigureChannelizer(int centerFrequency) :
Message(), m_centerFrequency(centerFrequency)
{
}
};
DATVDemod(DeviceSourceAPI *); DATVDemod(DeviceSourceAPI *);
~DATVDemod(); ~DATVDemod();
virtual void destroy() { delete this; } virtual void destroy()
virtual void getIdentifier(QString& id) { id = objectName(); } {
virtual void getTitle(QString& title) { title = objectName(); } delete this;
virtual qint64 getCenterFrequency() const { return m_objRunning.intCenterFrequency; } }
virtual void getIdentifier(QString& id)
{
id = objectName();
}
virtual void getTitle(QString& title)
{
title = objectName();
}
virtual qint64 getCenterFrequency() const
{
return m_objRunning.intCenterFrequency;
}
virtual QByteArray serialize() const { return QByteArray(); } virtual QByteArray serialize() const
virtual bool deserialize(const QByteArray& data __attribute__((unused))) { return false; } {
return QByteArray();
}
virtual bool deserialize(const QByteArray& data __attribute__((unused)))
{
return false;
}
void configure(
MessageQueue* objMessageQueue,
void configure(MessageQueue* objMessageQueue,
int intRFBandwidth, int intRFBandwidth,
int intCenterFrequency, int intCenterFrequency,
dvb_version enmStandard, dvb_version enmStandard,
@ -206,7 +256,8 @@ public:
bool blnResample, bool blnResample,
bool blnViterbi); bool blnViterbi);
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po); virtual void feed(const SampleVector::const_iterator& begin,
const SampleVector::const_iterator& end, bool po);
virtual void start(); virtual void start();
virtual void stop(); virtual void stop();
virtual bool handleMessage(const Message& cmd); virtual bool handleMessage(const Message& cmd);
@ -216,7 +267,8 @@ public:
bool PlayVideo(bool blnStartStop); bool PlayVideo(bool blnStartStop);
void InitDATVParameters(int intMsps, void InitDATVParameters(
int intMsps,
int intRFBandwidth, int intRFBandwidth,
int intCenterFrequency, int intCenterFrequency,
dvb_version enmStandard, dvb_version enmStandard,
@ -232,39 +284,85 @@ public:
bool blnResample, bool blnResample,
bool blnViterbi); bool blnViterbi);
void CleanUpDATVFramework(bool blnRelease); void CleanUpDATVFramework();
int GetSampleRate(); int GetSampleRate();
void InitDATVFramework(); void InitDATVFramework();
static const QString m_channelIdURI; static const QString m_channelIdURI;
static const QString m_channelId; static const QString m_channelId;
private:
class MsgConfigureChannelizer : public Message class MsgConfigureDATVDemod: public Message
{ {
MESSAGE_CLASS_DECLARATION MESSAGE_CLASS_DECLARATION
public: public:
int getCenterFrequency() const { return m_centerFrequency; } static MsgConfigureDATVDemod* create(
int intRFBandwidth,
static MsgConfigureChannelizer* create(int centerFrequency) int intCenterFrequency,
dvb_version enmStandard,
DATVModulation enmModulation,
code_rate enmFEC,
int intSymbolRate,
int intNotchFilters,
bool blnAllowDrift,
bool blnFastLock,
bool blnHDLC,
bool blnHardMetric,
bool blnResample,
bool blnViterbi)
{ {
return new MsgConfigureChannelizer(centerFrequency); return new MsgConfigureDATVDemod(
intRFBandwidth,
intCenterFrequency,
enmStandard,
enmModulation,
enmFEC,
intSymbolRate,
intNotchFilters,
blnAllowDrift,
blnFastLock,
blnHDLC,
blnHardMetric,
blnResample,
blnViterbi);
} }
private: DATVConfig m_objMsgConfig;
int m_centerFrequency;
MsgConfigureChannelizer(int centerFrequency) : private:
Message(), MsgConfigureDATVDemod(
m_centerFrequency(centerFrequency) int intRFBandwidth,
{ } int intCenterFrequency,
dvb_version enmStandard,
DATVModulation enmModulation,
code_rate enmFEC,
int intSymbolRate,
int intNotchFilters,
bool blnAllowDrift,
bool blnFastLock,
bool blnHDLC,
bool blnHardMetric,
bool blnResample,
bool blnViterbi) :
Message()
{
m_objMsgConfig.intRFBandwidth = intRFBandwidth;
m_objMsgConfig.intCenterFrequency = intCenterFrequency;
m_objMsgConfig.enmStandard = enmStandard;
m_objMsgConfig.enmModulation = enmModulation;
m_objMsgConfig.enmFEC = enmFEC;
m_objMsgConfig.intSymbolRate = intSymbolRate;
m_objMsgConfig.intNotchFilters = intNotchFilters;
m_objMsgConfig.blnAllowDrift = blnAllowDrift;
m_objMsgConfig.blnFastLock = blnFastLock;
m_objMsgConfig.blnHDLC = blnHDLC;
m_objMsgConfig.blnHardMetric = blnHardMetric;
m_objMsgConfig.blnResample = blnResample;
m_objMsgConfig.blnViterbi = blnViterbi;
}
}; };
private:
unsigned long m_lngExpectedReadIQ; unsigned long m_lngExpectedReadIQ;
unsigned long m_lngReadIQ; unsigned long m_lngReadIQ;
@ -346,7 +444,6 @@ private:
pipebuf<u32> *p_locktime; pipebuf<u32> *p_locktime;
mpeg_sync<u8, 0> *r_sync_mpeg; mpeg_sync<u8, 0> *r_sync_mpeg;
// DEINTERLEAVING // DEINTERLEAVING
pipebuf<rspacket<u8> > *p_rspackets; pipebuf<rspacket<u8> > *p_rspackets;
deinterleaver<u8> *r_deinter; deinterleaver<u8> *r_deinter;
@ -365,7 +462,6 @@ private:
pipebuf<tspacket> *p_tspackets; pipebuf<tspacket> *p_tspackets;
derandomizer *r_derand; derandomizer *r_derand;
//OUTPUT //OUTPUT
file_writer<tspacket> *r_stdout; file_writer<tspacket> *r_stdout;
datvvideoplayer<tspacket> *r_videoplayer; datvvideoplayer<tspacket> *r_videoplayer;
@ -373,9 +469,6 @@ private:
//CONSTELLATION //CONSTELLATION
datvconstellation<f32> *r_scope_symbols; datvconstellation<f32> *r_scope_symbols;
private:
DeviceSourceAPI* m_deviceAPI; DeviceSourceAPI* m_deviceAPI;
ThreadedBasebandSampleSink* m_threadedChannelizer; ThreadedBasebandSampleSink* m_threadedChannelizer;
@ -396,64 +489,6 @@ private:
DATVModulation m_enmModulation; DATVModulation m_enmModulation;
//QElapsedTimer m_objTimer; //QElapsedTimer m_objTimer;
private:
class MsgConfigureDATVDemod : public Message
{
MESSAGE_CLASS_DECLARATION
public:
static MsgConfigureDATVDemod* create(int intRFBandwidth,
int intCenterFrequency,
dvb_version enmStandard,
DATVModulation enmModulation,
code_rate enmFEC,
int intSymbolRate,
int intNotchFilters,
bool blnAllowDrift,
bool blnFastLock,
bool blnHDLC,
bool blnHardMetric,
bool blnResample,
bool blnViterbi)
{
return new MsgConfigureDATVDemod(intRFBandwidth,intCenterFrequency,enmStandard, enmModulation, enmFEC, intSymbolRate, intNotchFilters, blnAllowDrift,blnFastLock,blnHDLC,blnHardMetric,blnResample, blnViterbi);
}
DATVConfig m_objMsgConfig;
private:
MsgConfigureDATVDemod(int intRFBandwidth,
int intCenterFrequency,
dvb_version enmStandard,
DATVModulation enmModulation,
code_rate enmFEC,
int intSymbolRate,
int intNotchFilters,
bool blnAllowDrift,
bool blnFastLock,
bool blnHDLC,
bool blnHardMetric,
bool blnResample,
bool blnViterbi) :
Message()
{
m_objMsgConfig.intRFBandwidth = intRFBandwidth;
m_objMsgConfig.intCenterFrequency = intCenterFrequency;
m_objMsgConfig.enmStandard = enmStandard;
m_objMsgConfig.enmModulation = enmModulation;
m_objMsgConfig.enmFEC = enmFEC;
m_objMsgConfig.intSymbolRate = intSymbolRate;
m_objMsgConfig.intNotchFilters = intNotchFilters;
m_objMsgConfig.blnAllowDrift = blnAllowDrift;
m_objMsgConfig.blnFastLock = blnFastLock;
m_objMsgConfig.blnHDLC = blnHDLC;
m_objMsgConfig.blnHardMetric = blnHardMetric;
m_objMsgConfig.blnResample = blnResample;
m_objMsgConfig.blnViterbi = blnViterbi;
}
};
DATVConfig m_objRunning; DATVConfig m_objRunning;

View File

@ -208,7 +208,7 @@ bool DATVDemodGUI::deserialize(const QByteArray& arrData)
} }
} }
bool DATVDemodGUI::handleMessage(const Message& objMessage) bool DATVDemodGUI::handleMessage(const Message& objMessage __attribute__((unused)))
{ {
return false; return false;
} }
@ -233,7 +233,7 @@ void DATVDemodGUI::channelSampleRateChanged()
applySettings(); applySettings();
} }
void DATVDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) void DATVDemodGUI::onWidgetRolled(QWidget* widget __attribute__((unused)), bool rollDown __attribute__((unused)))
{ {
} }
@ -506,12 +506,12 @@ void DATVDemodGUI::tick()
return; return;
} }
void DATVDemodGUI::on_cmbStandard_currentIndexChanged(const QString &arg1) void DATVDemodGUI::on_cmbStandard_currentIndexChanged(const QString &arg1 __attribute__((unused)))
{ {
applySettings(); applySettings();
} }
void DATVDemodGUI::on_cmbModulation_currentIndexChanged(const QString &arg1) void DATVDemodGUI::on_cmbModulation_currentIndexChanged(const QString &arg1 __attribute__((unused)))
{ {
QString strModulation; QString strModulation;
QString strFEC; QString strFEC;
@ -563,7 +563,7 @@ void DATVDemodGUI::on_cmbModulation_currentIndexChanged(const QString &arg1)
} }
void DATVDemodGUI::on_cmbFEC_currentIndexChanged(const QString &arg1) void DATVDemodGUI::on_cmbFEC_currentIndexChanged(const QString &arg1 __attribute__((unused)))
{ {
QString strFEC; QString strFEC;
@ -641,12 +641,12 @@ void DATVDemodGUI::on_spiSampleRate_valueChanged(int arg1)
} }
*/ */
void DATVDemodGUI::on_spiSymbolRate_valueChanged(int arg1) void DATVDemodGUI::on_spiSymbolRate_valueChanged(int arg1 __attribute__((unused)))
{ {
applySettings(); applySettings();
} }
void DATVDemodGUI::on_spiNotchFilters_valueChanged(int arg1) void DATVDemodGUI::on_spiNotchFilters_valueChanged(int arg1 __attribute__((unused)))
{ {
applySettings(); applySettings();
} }
@ -701,7 +701,7 @@ void DATVDemodGUI::on_pushButton_4_clicked()
} }
void DATVDemodGUI::on_mouseEvent(QMouseEvent* obj) void DATVDemodGUI::on_mouseEvent(QMouseEvent* obj __attribute__((unused)))
{ {
} }
@ -724,7 +724,7 @@ QString DATVDemodGUI::formatBytes(qint64 intBytes)
} }
void DATVDemodGUI::on_StreamDataAvailable(int *intPackets, int *intBytes, int *intPercent, qint64 *intTotalReceived) void DATVDemodGUI::on_StreamDataAvailable(int *intPackets __attribute__((unused)), int *intBytes, int *intPercent, qint64 *intTotalReceived)
{ {
ui->lblStatus->setText(QString("Decod: %1B").arg(formatBytes(*intTotalReceived))); ui->lblStatus->setText(QString("Decod: %1B").arg(formatBytes(*intTotalReceived)));
m_intLastDecodedData = *intTotalReceived; m_intLastDecodedData = *intTotalReceived;
@ -742,7 +742,7 @@ void DATVDemodGUI::on_StreamDataAvailable(int *intPackets, int *intBytes, int *i
} }
void DATVDemodGUI::on_spiBandwidth_valueChanged(int arg1) void DATVDemodGUI::on_spiBandwidth_valueChanged(int arg1 __attribute__((unused)))
{ {
applySettings(); applySettings();
} }

View File

@ -5,7 +5,8 @@
#include "leansdr/framework.h" #include "leansdr/framework.h"
#include "leansdr/math.h" #include "leansdr/math.h"
namespace leansdr { namespace leansdr
{
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// DSP blocks // DSP blocks
@ -14,64 +15,88 @@ namespace leansdr {
// [cconverter] converts complex streams between numric types, // [cconverter] converts complex streams between numric types,
// with optional ofsetting and rational scaling. // with optional ofsetting and rational scaling.
template<typename Tin, int Zin, typename Tout, int Zout, int Gn, int Gd> template<typename Tin, int Zin, typename Tout, int Zout, int Gn, int Gd>
struct cconverter : runnable { struct cconverter: runnable
{
cconverter(scheduler *sch, pipebuf<complex<Tin> > &_in, cconverter(scheduler *sch, pipebuf<complex<Tin> > &_in,
pipebuf< complex<Tout> > &_out) pipebuf<complex<Tout> > &_out) :
: runnable(sch, "cconverter"), runnable(sch, "cconverter"), in(_in), out(_out)
in(_in), out(_out) { {
} }
void run() {
void run()
{
unsigned long count = min(in.readable(), out.writable()); unsigned long count = min(in.readable(), out.writable());
complex<Tin> *pin = in.rd(), *pend = pin + count; complex<Tin> *pin = in.rd(), *pend = pin + count;
complex<Tout> *pout = out.wr(); complex<Tout> *pout = out.wr();
for ( ; pin<pend; ++pin,++pout ) { for (; pin < pend; ++pin, ++pout)
{
pout->re = Zout + (pin->re - (Tin) Zin) * Gn / Gd; pout->re = Zout + (pin->re - (Tin) Zin) * Gn / Gd;
pout->im = Zout + (pin->im - (Tin) Zin) * Gn / Gd; pout->im = Zout + (pin->im - (Tin) Zin) * Gn / Gd;
} }
in.read(count); in.read(count);
out.written(count); out.written(count);
} }
private: private:
pipereader<complex<Tin> > in; pipereader<complex<Tin> > in;
pipewriter<complex<Tout> > out; pipewriter<complex<Tout> > out;
}; };
template<typename T> template<typename T>
struct cfft_engine { struct cfft_engine
const int n; {
cfft_engine(int _n) : n(_n), invsqrtn(1.0/sqrt(n)) { const unsigned int n;
cfft_engine(unsigned int _n) :
n(_n), invsqrtn(1.0 / sqrt(n))
{
// Compute log2(n) // Compute log2(n)
logn = 0; logn = 0;
for ( int t=n; t>1; t>>=1 ) ++logn; for (int t = n; t > 1; t >>= 1)
++logn;
// Bit reversal // Bit reversal
bitrev = new int[n]; bitrev = new int[n];
for ( int i=0; i<n; ++i ) { for (unsigned int i = 0; i < n; ++i)
{
bitrev[i] = 0; bitrev[i] = 0;
for ( int b=0; b<logn; ++b ) bitrev[i] = (bitrev[i]<<1) | ((i>>b)&1); for (int b = 0; b < logn; ++b)
bitrev[i] = (bitrev[i] << 1) | ((i >> b) & 1);
} }
// Float constants // Float constants
omega = new complex<T> [n]; omega = new complex<T> [n];
omega_rev = new complex<T> [n]; omega_rev = new complex<T> [n];
for ( int i=0; i<n; ++i ) { for (unsigned int i = 0; i < n; ++i)
{
float a = 2.0 * M_PI * i / n; float a = 2.0 * M_PI * i / n;
omega_rev[i].re = (omega[i].re = cosf(a)); omega_rev[i].re = (omega[i].re = cosf(a));
omega_rev[i].im = -(omega[i].im = sinf(a)); omega_rev[i].im = -(omega[i].im = sinf(a));
} }
} }
void inplace(complex<T> *data, bool reverse=false) {
void inplace(complex<T> *data, bool reverse = false)
{
// Bit-reversal permutation // Bit-reversal permutation
for ( int i=0; i<n; ++i ) { for (unsigned int i = 0; i < n; ++i)
int r = bitrev[i]; {
if ( r < i ) { complex<T> tmp=data[i]; data[i]=data[r]; data[r]=tmp; } unsigned int r = bitrev[i];
if (r < i)
{
complex<T> tmp = data[i];
data[i] = data[r];
data[r] = tmp;
}
} }
complex<T> *om = reverse ? omega_rev : omega; complex<T> *om = reverse ? omega_rev : omega;
// Danielson-Lanczos // Danielson-Lanczos
for ( int i=0; i<logn; ++i ) { for (int i = 0; i < logn; ++i)
{
int hbs = 1 << i; int hbs = 1 << i;
int dom = 1 << (logn - 1 - i); int dom = 1 << (logn - 1 - i);
for ( int j=0; j<dom; ++j ) { for (int j = 0; j < dom; ++j)
{
int p = j * hbs * 2, q = p + hbs; int p = j * hbs * 2, q = p + hbs;
for ( int k=0; k<hbs; ++k ) { for (int k = 0; k < hbs; ++k)
{
complex<T> &w = om[k * dom]; complex<T> &w = om[k * dom];
complex<T> &dqk = data[q + k]; complex<T> &dqk = data[q + k];
complex<T> x(w.re * dqk.re - w.im * dqk.im, complex<T> x(w.re * dqk.re - w.im * dqk.im,
@ -83,14 +108,17 @@ namespace leansdr {
} }
} }
} }
if ( reverse ) { if (reverse)
{
float invn = 1.0 / n; float invn = 1.0 / n;
for ( int i=0; i<n; ++i ) { for (unsigned int i = 0; i < n; ++i)
{
data[i].re *= invn; data[i].re *= invn;
data[i].im *= invn; data[i].im *= invn;
} }
} }
} }
private: private:
int logn; int logn;
int *bitrev; int *bitrev;
@ -99,44 +127,61 @@ namespace leansdr {
}; };
template<typename T> template<typename T>
struct adder : runnable { struct adder: runnable
adder(scheduler *sch, {
pipebuf<T> &_in1, pipebuf<T> &_in2, pipebuf<T> &_out) adder(scheduler *sch, pipebuf<T> &_in1, pipebuf<T> &_in2, pipebuf<T> &_out) :
: runnable(sch, "adder"), runnable(sch, "adder"),
in1(_in1), in2(_in2), out(_out) { in1(_in1),
in2(_in2),
out(_out)
{
} }
void run() {
void run()
{
int n = out.writable(); int n = out.writable();
if ( in1.readable() < n ) n = in1.readable(); if (in1.readable() < n)
if ( in2.readable() < n ) n = in2.readable(); n = in1.readable();
T *pin1=in1.rd(), *pin2=in2.rd(), *pout=out.wr(), *pend=pout+n; if (in2.readable() < n)
while ( pout < pend ) *pout++ = *pin1++ + *pin2++; n = in2.readable();
T *pin1 = in1.rd(), *pin2 = in2.rd(), *pout = out.wr(), *pend = pout
+ n;
while (pout < pend)
*pout++ = *pin1++ + *pin2++;
in1.read(n); in1.read(n);
in2.read(n); in2.read(n);
out.written(n); out.written(n);
} }
private: private:
pipereader<T> in1, in2; pipereader<T> in1, in2;
pipewriter<T> out; pipewriter<T> out;
}; };
template<typename Tscale, typename Tin, typename Tout> template<typename Tscale, typename Tin, typename Tout>
struct scaler : runnable { struct scaler: runnable
{
Tscale scale; Tscale scale;
scaler(scheduler *sch, Tscale _scale,
pipebuf<Tin> &_in, pipebuf<Tout> &_out) scaler(scheduler *sch, Tscale _scale, pipebuf<Tin> &_in, pipebuf<Tout> &_out) :
: runnable(sch, "scaler"), runnable(sch, "scaler"),
scale(_scale), scale(_scale),
in(_in), out(_out) { in(_in),
out(_out)
{
} }
void run() {
void run()
{
unsigned long count = min(in.readable(), out.writable()); unsigned long count = min(in.readable(), out.writable());
Tin *pin = in.rd(), *pend = pin + count; Tin *pin = in.rd(), *pend = pin + count;
Tout *pout = out.wr(); Tout *pout = out.wr();
for ( ; pin<pend; ++pin,++pout ) *pout = *pin * scale; for (; pin < pend; ++pin, ++pout)
*pout = *pin * scale;
in.read(count); in.read(count);
out.written(count); out.written(count);
} }
private: private:
pipereader<Tin> in; pipereader<Tin> in;
pipewriter<Tout> out; pipewriter<Tout> out;
@ -145,17 +190,25 @@ namespace leansdr {
// [awgb_c] generates complex white gaussian noise. // [awgb_c] generates complex white gaussian noise.
template<typename T> template<typename T>
struct wgn_c : runnable { struct wgn_c: runnable
wgn_c(scheduler *sch, pipebuf< complex<T> > &_out) {
: runnable(sch, "awgn"), stddev(1.0), out(_out) { wgn_c(scheduler *sch, pipebuf<complex<T> > &_out) :
runnable(sch, "awgn"),
stddev(1.0),
out(_out)
{
} }
void run() {
void run()
{
int n = out.writable(); int n = out.writable();
complex<T> *pout = out.wr(), *pend = pout + n; complex<T> *pout = out.wr(), *pend = pout + n;
while ( pout < pend ) { while (pout < pend)
{
// TAOCP // TAOCP
float x, y, r2; float x, y, r2;
do { do
{
x = 2 * drand48() - 1; x = 2 * drand48() - 1;
y = 2 * drand48() - 1; y = 2 * drand48() - 1;
r2 = x * x + y * y; r2 = x * x + y * y;
@ -167,26 +220,37 @@ namespace leansdr {
} }
out.written(n); out.written(n);
} }
float stddev; float stddev;
private: private:
pipewriter<complex<T> > out; pipewriter<complex<T> > out;
}; };
template<typename T> template<typename T>
struct naive_lowpass : runnable { struct naive_lowpass: runnable
naive_lowpass(scheduler *sch, pipebuf<T> &_in, pipebuf<T> &_out, int _w) {
: runnable(sch, "lowpass"), in(_in), out(_out), w(_w) { naive_lowpass(scheduler *sch, pipebuf<T> &_in, pipebuf<T> &_out, int _w) :
runnable(sch, "lowpass"),
in(_in),
out(_out),
w(_w)
{
} }
void run() { void run()
if ( in.readable() < w ) return; {
if (in.readable() < w)
return;
unsigned long count = min(in.readable() - w, out.writable()); unsigned long count = min(in.readable() - w, out.writable());
T *pin = in.rd(), *pend = pin + count; T *pin = in.rd(), *pend = pin + count;
T *pout = out.wr(); T *pout = out.wr();
float k = 1.0 / w; float k = 1.0 / w;
for ( ; pin<pend; ++pin,++pout ) { for (; pin < pend; ++pin, ++pout)
{
T x = 0.0; T x = 0.0;
for ( int i=0; i<w; ++i ) x = x + pin[i]; for (int i = 0; i < w; ++i)
x = x + pin[i];
*pout = x * k; *pout = x * k;
} }
in.read(count); in.read(count);
@ -200,37 +264,47 @@ namespace leansdr {
}; };
template<typename T, typename Tc> template<typename T, typename Tc>
struct fir_filter : runnable { struct fir_filter: runnable
fir_filter(scheduler *sch, int _ncoeffs, Tc *_coeffs, {
pipebuf<T> &_in, pipebuf<T> &_out, fir_filter(scheduler *sch, int _ncoeffs, Tc *_coeffs, pipebuf<T> &_in, pipebuf<T> &_out, unsigned int _decim = 1) :
unsigned int _decim=1) runnable(sch, "fir_filter"),
: runnable(sch, "fir_filter"), freq_tap(NULL),
ncoeffs(_ncoeffs), coeffs(_coeffs), tap_multiplier(1),
in(_in), out(_out), freq_tol(0.1),
decim(_decim), ncoeffs(_ncoeffs),
freq_tap(NULL), tap_multiplier(1), freq_tol(0.1) { coeffs(_coeffs),
in(_in),
out(_out),
decim(_decim)
{
shifted_coeffs = new T[ncoeffs]; shifted_coeffs = new T[ncoeffs];
set_freq(0); set_freq(0);
} }
void run() { void run()
if ( in.readable() < ncoeffs ) return; {
if (in.readable() < ncoeffs)
return;
if ( freq_tap ) { if (freq_tap)
{
float new_freq = *freq_tap * tap_multiplier; float new_freq = *freq_tap * tap_multiplier;
if ( fabs(current_freq-new_freq) > freq_tol ) { if (fabs(current_freq - new_freq) > freq_tol)
{
if (sch->verbose) if (sch->verbose)
fprintf(stderr, "Shifting filter %f -> %f\n", fprintf(stderr, "Shifting filter %f -> %f\n", current_freq,
current_freq, new_freq); new_freq);
set_freq(new_freq); set_freq(new_freq);
} }
} }
unsigned long count = min((in.readable() - ncoeffs) / decim, unsigned long count = min((in.readable() - ncoeffs) / decim,
out.writable()); out.writable());
T *pin=in.rd()+ncoeffs, *pend=pin+count*decim, *pout=out.wr(); T *pin = in.rd() + ncoeffs, *pend = pin + count * decim, *pout =
out.wr();
// TBD use coeffs when current_freq=0 (fewer mults if float) // TBD use coeffs when current_freq=0 (fewer mults if float)
for ( ; pin<pend; pin+=decim,++pout ) { for (; pin < pend; pin += decim, ++pout)
{
T *pc = shifted_coeffs; T *pc = shifted_coeffs;
T *pi = pin; T *pi = pin;
T x = 0; T x = 0;
@ -242,17 +316,24 @@ namespace leansdr {
out.written(count); out.written(count);
} }
public:
float *freq_tap;
float tap_multiplier;
float freq_tol;
private: private:
unsigned int ncoeffs; unsigned int ncoeffs;
Tc *coeffs; Tc *coeffs;
pipereader<T> in; pipereader<T> in;
pipewriter<T> out; pipewriter<T> out;
unsigned int decim; unsigned int decim;
T *shifted_coeffs; T *shifted_coeffs;
float current_freq; float current_freq;
void set_freq(float f) {
for ( int i=0; i<ncoeffs; ++i ) { void set_freq(float f)
{
for (unsigned int i = 0; i < ncoeffs; ++i)
{
float a = 2 * M_PI * f * (i - ncoeffs / 2); float a = 2 * M_PI * f * (i - ncoeffs / 2);
float c = cosf(a), s = sinf(a); float c = cosf(a), s = sinf(a);
// TBD Support T=complex // TBD Support T=complex
@ -261,52 +342,60 @@ namespace leansdr {
} }
current_freq = f; current_freq = f;
} }
public: };
float *freq_tap; // fir_filter
float tap_multiplier;
float freq_tol;
}; // fir_filter
// FIR FILTER WITH INTERPOLATION AND DECIMATION // FIR FILTER WITH INTERPOLATION AND DECIMATION
template<typename T, typename Tc> template<typename T, typename Tc>
struct fir_resampler : runnable { struct fir_resampler: runnable
fir_resampler(scheduler *sch, int _ncoeffs, Tc *_coeffs,
pipebuf<T> &_in, pipebuf<T> &_out,
int _interp=1, int _decim=1)
: runnable(sch, "fir_resampler"),
ncoeffs(_ncoeffs), coeffs(_coeffs),
interp(_interp), decim(_decim),
in(_in), out(_out,interp),
freq_tap(NULL), tap_multiplier(1), freq_tol(0.1)
{ {
if ( decim != 1 ) fail("fir_resampler: decim not implemented"); // TBD fir_resampler(scheduler *sch, int _ncoeffs, Tc *_coeffs, pipebuf<T> &_in, pipebuf<T> &_out, int _interp = 1, int _decim = 1) :
runnable(sch, "fir_resampler"),
ncoeffs(_ncoeffs),
coeffs(_coeffs),
interp(_interp),
decim(_decim),
in(_in),
out(_out, interp),
freq_tap(NULL),
tap_multiplier(1),
freq_tol(0.1)
{
if (decim != 1)
fail("fir_resampler: decim not implemented"); // TBD
shifted_coeffs = new T[ncoeffs]; shifted_coeffs = new T[ncoeffs];
set_freq(0); set_freq(0);
} }
void run() { void run()
if ( in.readable() < ncoeffs ) return; {
if (in.readable() < ncoeffs)
return;
if ( freq_tap ) { if (freq_tap)
{
float new_freq = *freq_tap * tap_multiplier; float new_freq = *freq_tap * tap_multiplier;
if ( fabs(current_freq-new_freq) > freq_tol ) { if (fabs(current_freq - new_freq) > freq_tol)
{
if (sch->verbose) if (sch->verbose)
fprintf(stderr, "Shifting filter %f -> %f\n", fprintf(stderr, "Shifting filter %f -> %f\n", current_freq,
current_freq, new_freq); new_freq);
set_freq(new_freq); set_freq(new_freq);
} }
} }
if ( in.readable()*interp < ncoeffs ) return; if (in.readable() * interp < ncoeffs)
return;
unsigned long count = min((in.readable() * interp - ncoeffs) / interp, unsigned long count = min((in.readable() * interp - ncoeffs) / interp,
out.writable() / interp); out.writable() / interp);
int latency = (ncoeffs + interp) / interp; int latency = (ncoeffs + interp) / interp;
T *pin = in.rd() + latency, *pend = pin + count, *pout = out.wr(); T *pin = in.rd() + latency, *pend = pin + count, *pout = out.wr();
// TBD use coeffs when current_freq=0 (fewer mults if float) // TBD use coeffs when current_freq=0 (fewer mults if float)
for ( ; pin<pend; ++pin ) { for (; pin < pend; ++pin)
for ( int i=0; i<interp; ++i,++pout ) { {
for (int i = 0; i < interp; ++i, ++pout)
{
T *pi = pin; T *pi = pin;
T *pc = shifted_coeffs + i, *pcend = shifted_coeffs + ncoeffs; T *pc = shifted_coeffs + i, *pcend = shifted_coeffs + ncoeffs;
T x = 0; T x = 0;
@ -319,23 +408,24 @@ namespace leansdr {
out.written(count * interp); out.written(count * interp);
} }
private:
unsigned int ncoeffs;
Tc *coeffs;
int interp, decim;
pipereader<T> in;
pipewriter<T> out;
public: public:
float *freq_tap; float *freq_tap;
float tap_multiplier; float tap_multiplier;
float freq_tol; float freq_tol;
private: private:
unsigned int ncoeffs;
Tc *coeffs;
int interp, decim;
pipereader<T> in;
pipewriter<T> out;
T *shifted_coeffs; T *shifted_coeffs;
float current_freq; float current_freq;
void set_freq(float f) {
for ( int i=0; i<ncoeffs; ++i ) { void set_freq(float f)
{
for (int i = 0; i < ncoeffs; ++i)
{
float a = 2 * M_PI * f * i; float a = 2 * M_PI * f * i;
float c = cosf(a), s = sinf(a); float c = cosf(a), s = sinf(a);
// TBD Support T=complex // TBD Support T=complex
@ -344,7 +434,8 @@ namespace leansdr {
} }
current_freq = f; current_freq = f;
} }
}; // fir_resampler };
// fir_resampler
}// namespace }// namespace

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,26 @@
#ifndef LEANSDR_FRAMEWORK_H #ifndef LEANSDR_FRAMEWORK_H
#define LEANSDR_FRAMEWORK_H #define LEANSDR_FRAMEWORK_H
#include <cstddef>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
namespace leansdr { namespace leansdr
{
inline void fatal(const char *s) { perror(s); exit(1); } inline void fatal(const char *s)
inline void fail(const char *s) { fprintf(stderr, "** %s\n", s); exit(1); } {
perror(s);
exit(1);
}
inline void fail(const char *s)
{
fprintf(stderr, "leansdr::fail: %s\n", s);
exit(1);
}
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// DSP framework // DSP framework
@ -25,30 +36,69 @@ namespace leansdr {
static const int MAX_RUNNABLES = 64; static const int MAX_RUNNABLES = 64;
static const int MAX_READERS = 8; static const int MAX_READERS = 8;
struct pipebuf_common { struct pipebuf_common
virtual int sizeofT() { return 0; } {
virtual long long hash() { return 0; } virtual int sizeofT()
virtual void dump(size_t *total_bufs) { } {
return 0;
}
virtual long long hash()
{
return 0;
}
virtual void dump(std::size_t *total_bufs __attribute__((unused)))
{
}
pipebuf_common(const char *_name) :
name(_name)
{
}
virtual ~pipebuf_common()
{
}
const char *name; const char *name;
pipebuf_common(const char *_name) : name(_name) { }
}; };
struct runnable_common { struct runnable_common
const char *name; {
runnable_common(const char *_name) : name(_name) { } runnable_common(const char *_name) :
virtual void run() { } name(_name)
virtual void shutdown() { } {
}
virtual ~runnable_common()
{
}
virtual void run()
{
}
virtual void shutdown()
{
}
#ifdef DEBUG #ifdef DEBUG
~runnable_common() { fprintf(stderr, "Deallocating %s !\n", name); } ~runnable_common()
{ fprintf(stderr, "Deallocating %s !\n", name);}
#endif #endif
const char *name;
}; };
struct window_placement { struct window_placement
{
const char *name; // NULL to terminate const char *name; // NULL to terminate
int x, y, w, h; int x, y, w, h;
}; };
struct scheduler { struct scheduler
{
pipebuf_common *pipes[MAX_PIPES]; pipebuf_common *pipes[MAX_PIPES];
int npipes; int npipes;
runnable_common *runnables[MAX_RUNNABLES]; runnable_common *runnables[MAX_RUNNABLES];
@ -56,53 +106,82 @@ namespace leansdr {
window_placement *windows; window_placement *windows;
bool verbose, debug; bool verbose, debug;
scheduler() scheduler() :
: npipes(0), nrunnables(0), windows(NULL), npipes(0), nrunnables(0), windows(NULL), verbose(false), debug(
verbose(false), debug(false) { false)
{
}
void add_pipe(pipebuf_common *p)
{
if (npipes == MAX_PIPES) {
fail("MAX_PIPES");
} }
void add_pipe(pipebuf_common *p) {
if ( npipes == MAX_PIPES ) fail("MAX_PIPES");
pipes[npipes++] = p; pipes[npipes++] = p;
} }
void add_runnable(runnable_common *r) {
if ( nrunnables == MAX_RUNNABLES ) fail("MAX_RUNNABLES"); void add_runnable(runnable_common *r)
{
if (nrunnables == MAX_RUNNABLES) {
fail("MAX_RUNNABLES");
}
runnables[nrunnables++] = r; runnables[nrunnables++] = r;
} }
void step() {
for ( int i=0; i<nrunnables; ++i ) void step()
{
for (int i = 0; i < nrunnables; ++i) {
runnables[i]->run(); runnables[i]->run();
} }
void run() { }
void run()
{
unsigned long long prev_hash = 0; unsigned long long prev_hash = 0;
while ( 1 ) {
while (1)
{
step(); step();
unsigned long long h = hash(); unsigned long long h = hash();
if ( h == prev_hash ) break; if (h == prev_hash) {
break;
}
prev_hash = h; prev_hash = h;
} }
} }
void shutdown() {
for ( int i=0; i<nrunnables; ++i ) void shutdown()
{
for (int i = 0; i < nrunnables; ++i) {
runnables[i]->shutdown(); runnables[i]->shutdown();
} }
unsigned long long hash() { }
unsigned long long hash()
{
unsigned long long h = 0; unsigned long long h = 0;
for ( int i=0; i<npipes; ++i ) h += (1+i)*pipes[i]->hash(); for (int i = 0; i < npipes; ++i) {
h += (1 + i) * pipes[i]->hash();
}
return h; return h;
} }
void dump() { void dump()
{
fprintf(stderr, "\n"); fprintf(stderr, "\n");
size_t total_bufs = 0; std::size_t total_bufs = 0;
for ( int i=0; i<npipes; ++i ) pipes[i]->dump(&total_bufs); for (int i = 0; i < npipes; ++i) {
fprintf(stderr, "Total buffer memory: %ld KiB\n", pipes[i]->dump(&total_bufs);
(unsigned long)total_bufs/1024); }
fprintf(stderr, "leansdr::scheduler::dump Total buffer memory: %ld KiB\n", (unsigned long) total_bufs / 1024);
} }
}; };
struct runnable : runnable_common { struct runnable: runnable_common
runnable(scheduler *_sch, const char *name) {
: runnable_common(name), sch(_sch) { runnable(scheduler *_sch, const char *name) :
runnable_common(name), sch(_sch)
{
sch->add_runnable(this); sch->add_runnable(this);
} }
protected: protected:
@ -110,84 +189,143 @@ namespace leansdr {
}; };
template<typename T> template<typename T>
struct pipebuf : pipebuf_common { struct pipebuf: pipebuf_common
{
T *buf; T *buf;
T *rds[MAX_READERS]; T *rds[MAX_READERS];
int nrd; int nrd;
T *wr; T *wr;
T *end; T *end;
int sizeofT() { return sizeof(T); }
pipebuf(scheduler *sch, const char *name, unsigned long size) int sizeofT()
: pipebuf_common(name), {
buf(new T[size]), nrd(0), wr(buf), end(buf+size), return sizeof(T);
min_write(1), }
total_written(0), total_read(0) {
pipebuf(scheduler *sch, const char *name, unsigned long size) :
pipebuf_common(name), buf(new T[size]), nrd(0), wr(buf), end(
buf + size), min_write(1), total_written(0), total_read(0)
{
sch->add_pipe(this); sch->add_pipe(this);
} }
int add_reader() {
if ( nrd == MAX_READERS ) fail("too many readers"); int add_reader()
{
if (nrd == MAX_READERS) {
fail("too many readers");
}
rds[nrd] = wr; rds[nrd] = wr;
return nrd++; return nrd++;
} }
void pack() {
void pack()
{
T *rd = wr; T *rd = wr;
for ( int i=0; i<nrd; ++i ) if ( rds[i] < rd ) rd = rds[i]; for (int i = 0; i < nrd; ++i)
{
if (rds[i] < rd) {
rd = rds[i];
}
}
memmove(buf, rd, (wr - rd) * sizeof(T)); memmove(buf, rd, (wr - rd) * sizeof(T));
wr -= rd - buf; wr -= rd - buf;
for ( int i=0; i<nrd; ++i ) rds[i] -= rd - buf; for (int i = 0; i < nrd; ++i) {
rds[i] -= rd - buf;
} }
long long hash() { }
long long hash()
{
return total_written + total_read; return total_written + total_read;
} }
void dump(size_t *total_bufs) {
if ( total_written < 10000 ) void dump(std::size_t *total_bufs)
fprintf(stderr, ".%-16s : %4ld/%4ld", name, {
total_read, total_written); if (total_written < 10000) {
else if ( total_written < 1000000 ) fprintf(stderr, "leansdr::pipebuf::dump: .%-16s : %4ld/%4ld", name, total_read, total_written);
fprintf(stderr, ".%-16s : %3ldk/%3ldk", name, } else if (total_written < 1000000) {
total_read/1000, total_written/1000); fprintf(stderr, "leansdr::pipebuf::dump: .%-16s : %3ldk/%3ldk", name, total_read / 1000, total_written / 1000);
else } else {
fprintf(stderr, ".%-16s : %3ldM/%3ldM", name, fprintf(stderr, "leansdr::pipebuf::dump: .%-16s : %3ldM/%3ldM", name, total_read / 1000000, total_written / 1000000);
total_read/1000000, total_written/1000000); }
*total_bufs += (end - buf) * sizeof(T); *total_bufs += (end - buf) * sizeof(T);
unsigned long nw = end - wr; unsigned long nw = end - wr;
fprintf(stderr, " %6ld writable %c,", nw, (nw<min_write)?'!':' '); fprintf(stderr, "leansdr::pipebuf: %6ld writable %c,", nw, (nw < min_write) ? '!' : ' ');
T *rd = wr; T *rd = wr;
for ( int j=0; j<nrd; ++j ) if ( rds[j] < rd ) rd = rds[j];
fprintf(stderr, " %6d unread (", (int)(wr-rd));
for (int j = 0; j < nrd; ++j) for (int j = 0; j < nrd; ++j)
fprintf(stderr, " %d", (int)(wr-rds[j])); {
fprintf(stderr, " )\n"); if (rds[j] < rd) {
rd = rds[j];
}
}
fprintf(stderr, "leansdr::pipebuf::dump: %6d unread (", (int) (wr - rd));
for (int j = 0; j < nrd; ++j) {
fprintf(stderr, "leansdr::pipebuf: %d", (int) (wr - rds[j]));
}
fprintf(stderr, "leansdr::pipebuf::dump: )\n");
} }
unsigned long min_write; unsigned long min_write;
unsigned long total_written, total_read; unsigned long total_written, total_read;
#ifdef DEBUG #ifdef DEBUG
~pipebuf() { fprintf(stderr, "Deallocating %s !\n", name); } ~pipebuf()
{ fprintf(stderr, "Deallocating %s !\n", name);}
#endif #endif
}; };
template<typename T> template<typename T>
struct pipewriter { struct pipewriter
{
pipebuf<T> &buf; pipebuf<T> &buf;
pipewriter(pipebuf<T> &_buf, unsigned long min_write=1)
: buf(_buf) { pipewriter(pipebuf<T> &_buf, unsigned long min_write = 1) :
if ( min_write > buf.min_write ) buf.min_write = min_write; buf(_buf)
{
if (min_write > buf.min_write) {
buf.min_write = min_write;
} }
// Return number of items writable at this->wr, 0 if full.
unsigned long writable() {
if ( buf.end-buf.wr < buf.min_write ) buf.pack();
return buf.end - buf.wr;
} }
T *wr() { return buf.wr; }
void written(unsigned long n) { /** Return number of items writable at this->wr, 0 if full. */
if ( buf.wr+n > buf.end ) { unsigned long writable()
fprintf(stderr, "Bug: overflow to %s\n", buf.name); {
if (buf.end < buf.wr)
{
fprintf(stderr, "leansdr::pipewriter::writable: Bug: overflow to %s\n", buf.name);
exit(1);
}
unsigned long delta = buf.end - buf.wr;
if (delta < buf.min_write) {
buf.pack();
}
return delta;
}
T *wr()
{
return buf.wr;
}
void written(unsigned long n)
{
if (buf.wr + n > buf.end)
{
fprintf(stderr, "leansdr::pipewriter::written: Bug: overflow to %s\n", buf.name);
exit(1); exit(1);
} }
buf.wr += n; buf.wr += n;
buf.total_written += n; buf.total_written += n;
} }
void write(const T &e) {
void write(const T &e)
{
*wr() = e; *wr() = e;
written(1); written(1);
} }
@ -196,30 +334,51 @@ namespace leansdr {
// Convenience functions for working with optional pipes // Convenience functions for working with optional pipes
template<typename T> template<typename T>
pipewriter<T> *opt_writer(pipebuf<T> *buf) { pipewriter<T> *opt_writer(pipebuf<T> *buf)
{
return buf ? new pipewriter<T>(*buf) : NULL; return buf ? new pipewriter<T>(*buf) : NULL;
} }
template<typename T> template<typename T>
bool opt_writable(pipewriter<T> *p, int n=1) { bool opt_writable(pipewriter<T> *p, unsigned int n = 1)
{
return (p == NULL) || p->writable() >= n; return (p == NULL) || p->writable() >= n;
} }
template<typename T> template<typename T>
void opt_write(pipewriter<T> *p, T val) { void opt_write(pipewriter<T> *p, T val)
if ( p ) p->write(val); {
if (p) {
p->write(val);
}
} }
template<typename T> template<typename T>
struct pipereader { struct pipereader
{
pipebuf<T> &buf; pipebuf<T> &buf;
int id; int id;
pipereader(pipebuf<T> &_buf) : buf(_buf), id(_buf.add_reader()) { }
unsigned long readable() { return buf.wr - buf.rds[id]; } pipereader(pipebuf<T> &_buf) :
T *rd() { return buf.rds[id]; } buf(_buf), id(_buf.add_reader())
void read(unsigned long n) { {
if ( buf.rds[id]+n > buf.wr ) { }
fprintf(stderr, "Bug: underflow from %s\n", buf.name);
unsigned long readable()
{
return buf.wr - buf.rds[id];
}
T *rd()
{
return buf.rds[id];
}
void read(unsigned long n)
{
if (buf.rds[id] + n > buf.wr)
{
fprintf(stderr, "leansdr::pipereader::read: Bug: underflow from %s\n", buf.name);
exit(1); exit(1);
} }
buf.rds[id] += n; buf.rds[id] += n;
@ -230,30 +389,70 @@ namespace leansdr {
// Math functions for templates // Math functions for templates
template<typename T> T gen_sqrt(T x); template<typename T> T gen_sqrt(T x);
inline float gen_sqrt(float x) { return sqrtf(x); } inline float gen_sqrt(float x)
inline unsigned int gen_sqrt(unsigned int x) { return sqrtl(x); } {
inline long double gen_sqrt(long double x) { return sqrtl(x); } return sqrtf(x);
}
inline unsigned int gen_sqrt(unsigned int x)
{
return sqrtl(x);
}
inline long double gen_sqrt(long double x)
{
return sqrtl(x);
}
template<typename T> T gen_abs(T x); template<typename T> T gen_abs(T x);
inline float gen_abs(float x) { return fabsf(x); } inline float gen_abs(float x)
inline int gen_abs(int x) { return abs(x); } {
inline long int gen_abs(long int x) { return labs(x); } return fabsf(x);
}
inline int gen_abs(int x)
{
return abs(x);
}
inline long int gen_abs(long int x)
{
return labs(x);
}
template<typename T> T gen_hypot(T x, T y); template<typename T> T gen_hypot(T x, T y);
inline float gen_hypot(float x, float y) { return hypotf(x,y); } inline float gen_hypot(float x, float y)
{
return hypotf(x, y);
}
inline long double gen_hypot(long double x, long double y) inline long double gen_hypot(long double x, long double y)
{ return hypotl(x,y); } {
return hypotl(x, y);
}
template<typename T> T gen_atan2(T y, T x); template<typename T> T gen_atan2(T y, T x);
inline float gen_atan2(float y, float x) { return atan2f(y,x); } inline float gen_atan2(float y, float x)
{
return atan2f(y, x);
}
inline long double gen_atan2(long double y, long double x) inline long double gen_atan2(long double y, long double x)
{ return atan2l(y,x); } {
return atan2l(y, x);
}
template<typename T> template<typename T>
T min(const T &x, const T &y) { return (x<y) ? x : y; } T min(const T &x, const T &y)
{
return (x < y) ? x : y;
}
template<typename T> template<typename T>
T max(const T &x, const T &y) { return (x<y) ? y : x; } T max(const T &x, const T &y)
{
return (x < y) ? y : x;
}
// Abreviations for integer types // Abreviations for integer types

View File

@ -3,26 +3,34 @@
#include "leansdr/framework.h" #include "leansdr/framework.h"
namespace leansdr { namespace leansdr
{
// HDLC deframer // HDLC deframer
struct hdlc_dec { struct hdlc_dec
{
hdlc_dec(int _minframesize, // Including CRC, excluding HDLC flags. hdlc_dec(int _minframesize, // Including CRC, excluding HDLC flags.
int _maxframesize, int _maxframesize, bool _invert) :
bool _invert) minframesize(_minframesize), maxframesize(_maxframesize), invertmask(
: minframesize(_minframesize), maxframesize(_maxframesize), _invert ? 0xff : 0), framebuf(new u8[maxframesize]), debug(
invertmask(_invert?0xff:0), false)
framebuf(new u8[maxframesize]),
debug(false)
{ {
reset(); reset();
} }
void reset() { shiftreg=0; inframe=false; } void reset()
{
shiftreg = 0;
inframe = false;
}
void begin_frame() { framesize=0; crc16=crc16_init; } void begin_frame()
{
framesize = 0;
crc16 = crc16_init;
}
// Decode (*ppin)[count] as MSB-packed HDLC bitstream. // Decode (*ppin)[count] as MSB-packed HDLC bitstream.
// Return pointer to buffer[*pdatasize], or NULL if no valid frame. // Return pointer to buffer[*pdatasize], or NULL if no valid frame.
@ -30,42 +38,62 @@ namespace leansdr {
// Return number of checksum errors in *fcs_errors. // Return number of checksum errors in *fcs_errors.
// *ppin will have increased by at least 1 (unless count==0). // *ppin will have increased by at least 1 (unless count==0).
u8 *decode(u8 **ppin, int count, u8 *decode(u8 **ppin, int count, int *pdatasize, int *hdlc_errors,
int *pdatasize, int *hdlc_errors, int *fcs_errors) { int *fcs_errors)
{
*hdlc_errors = 0; *hdlc_errors = 0;
*fcs_errors = 0; *fcs_errors = 0;
*pdatasize = -1; *pdatasize = -1;
u8 *pin = *ppin, *pend = pin + count; u8 *pin = *ppin, *pend = pin + count;
for ( ; pin<pend; ++pin ) { for (; pin < pend; ++pin)
{
u8 byte_in = (*pin) ^ invertmask; u8 byte_in = (*pin) ^ invertmask;
for ( int bits=8; bits--; byte_in<<=1 ) { for (int bits = 8; bits--; byte_in <<= 1)
{
u8 bit_in = byte_in & 128; u8 bit_in = byte_in & 128;
shiftreg = (shiftreg >> 1) | bit_in; shiftreg = (shiftreg >> 1) | bit_in;
if ( ! inframe ) { if (!inframe)
if ( shiftreg == 0x7e ) { // HDLC flag 01111110 {
if (shiftreg == 0x7e)
{ // HDLC flag 01111110
inframe = true; inframe = true;
nbits_out = 0; nbits_out = 0;
begin_frame(); begin_frame();
} }
} else { }
if ( (shiftreg&0xfe) == 0x7c ) { // 0111110x HDLC stuffing else
{
if ((shiftreg & 0xfe) == 0x7c)
{ // 0111110x HDLC stuffing
// Unstuff this 0 // Unstuff this 0
} else if ( shiftreg == 0x7e ) { // 01111110 HDLC flag }
if ( nbits_out != 7 ) { else if (shiftreg == 0x7e)
{ // 01111110 HDLC flag
if (nbits_out != 7)
{
// Not at byte boundary // Not at byte boundary
if ( debug ) fprintf(stderr, "^"); if (debug)
fprintf(stderr, "^");
++*hdlc_errors; ++*hdlc_errors;
} else { }
else
{
// Checksum // Checksum
crc16 ^= 0xffff; crc16 ^= 0xffff;
if ( framesize<2 || framesize<minframesize || if (framesize < 2 || framesize < minframesize
crc16!=crc16_check ) { || crc16 != crc16_check)
if ( debug ) fprintf(stderr, "!"); {
if (debug)
fprintf(stderr, "!");
++*hdlc_errors; ++*hdlc_errors;
// Do not report random noise as FCS errors // Do not report random noise as FCS errors
if ( framesize >= minframesize ) ++*fcs_errors; if (framesize >= minframesize)
} else { ++*fcs_errors;
if ( debug ) fprintf(stderr, "_"); }
else
{
if (debug)
fprintf(stderr, "_");
// This will trigger output, but we finish the byte first. // This will trigger output, but we finish the byte first.
*pdatasize = framesize - 2; *pdatasize = framesize - 2;
} }
@ -74,17 +102,25 @@ namespace leansdr {
begin_frame(); begin_frame();
// Keep processing up to 7 remaining bits from byte_in. // Keep processing up to 7 remaining bits from byte_in.
// Special cases 0111111 and 1111111 cannot affect *pdatasize. // Special cases 0111111 and 1111111 cannot affect *pdatasize.
} else if ( shiftreg == 0xfe ) { // 11111110 HDLC invalid }
if ( framesize ) { else if (shiftreg == 0xfe)
if ( debug ) fprintf(stderr, "^"); { // 11111110 HDLC invalid
if (framesize)
{
if (debug)
fprintf(stderr, "^");
++*hdlc_errors; ++*hdlc_errors;
} }
inframe = false; inframe = false;
} else { // Data bit }
else
{ // Data bit
byte_out = (byte_out >> 1) | bit_in; // HDLC is LSB first byte_out = (byte_out >> 1) | bit_in; // HDLC is LSB first
++nbits_out; ++nbits_out;
if ( nbits_out == 8 ) { if (nbits_out == 8)
if ( framesize < maxframesize ) { {
if (framesize < maxframesize)
{
framebuf[framesize++] = byte_out; framebuf[framesize++] = byte_out;
crc16_byte(byte_out); crc16_byte(byte_out);
} }
@ -93,7 +129,8 @@ namespace leansdr {
} }
} // inframe } // inframe
} // bits } // bits
if ( *pdatasize != -1 ) { if (*pdatasize != -1)
{
// Found a complete frame // Found a complete frame
*ppin = pin + 1; *ppin = pin + 1;
return framebuf; return framebuf;
@ -119,7 +156,8 @@ namespace leansdr {
static const u16 crc16_init = 0xffff; static const u16 crc16_init = 0xffff;
static const u16 crc16_poly = 0x8408; // 0x1021 MSB-first static const u16 crc16_poly = 0x8408; // 0x1021 MSB-first
static const u16 crc16_check = 0x0f47; static const u16 crc16_check = 0x0f47;
void crc16_byte(u8 data) { void crc16_byte(u8 data)
{
crc16 ^= data; crc16 ^= data;
for (int bit = 8; bit--;) for (int bit = 8; bit--;)
crc16 = (crc16 & 1) ? (crc16 >> 1) ^ crc16_poly : (crc16 >> 1); crc16 = (crc16 & 1) ? (crc16 >> 1) ^ crc16_poly : (crc16 >> 1);
@ -127,12 +165,13 @@ namespace leansdr {
public: public:
bool debug; bool debug;
}; // hdlc_dec };
// hdlc_dec
// HDLC synchronizer with polarity detection // HDLC synchronizer with polarity detection
struct hdlc_sync : runnable { struct hdlc_sync: runnable
{
hdlc_sync(scheduler *sch, hdlc_sync(scheduler *sch,
pipebuf<u8> &_in, // Packed bits pipebuf<u8> &_in, // Packed bits
pipebuf<u8> &_out, // Bytes pipebuf<u8> &_out, // Bytes
@ -143,56 +182,62 @@ namespace leansdr {
pipebuf<int> *_framecount_out = NULL, pipebuf<int> *_framecount_out = NULL,
pipebuf<int> *_fcserrcount_out = NULL, pipebuf<int> *_fcserrcount_out = NULL,
pipebuf<int> *_hdlcbytecount_out = NULL, pipebuf<int> *_hdlcbytecount_out = NULL,
pipebuf<int> *_databytecount_out=NULL) pipebuf<int> *_databytecount_out = NULL) :
: runnable(sch, "hdlc_sync"), runnable(sch, "hdlc_sync"), minframesize(_minframesize), maxframesize(
minframesize(_minframesize), _maxframesize), chunk_size(maxframesize + 2), in(_in), out(
maxframesize(_maxframesize), _out, _maxframesize + chunk_size), lock_out(
chunk_size(maxframesize+2), opt_writer(_lock_out)), framecount_out(
in(_in), out(_out, _maxframesize+chunk_size), opt_writer(_framecount_out)), fcserrcount_out(
lock_out(opt_writer(_lock_out)), opt_writer(_fcserrcount_out)), hdlcbytecount_out(
framecount_out(opt_writer(_framecount_out)), opt_writer(_hdlcbytecount_out)), databytecount_out(
fcserrcount_out(opt_writer(_fcserrcount_out)), opt_writer(_databytecount_out)), cur_sync(0), resync_phase(
hdlcbytecount_out(opt_writer(_hdlcbytecount_out)), 0), lock_state(false), resync_period(32), header16(false)
databytecount_out(opt_writer(_databytecount_out)), {
cur_sync(0), resync_phase(0), for (int s = 0; s < NSYNCS; ++s)
lock_state(false),
resync_period(32),
header16(false)
{ {
for ( int s=0; s<NSYNCS; ++s ) {
syncs[s].dec = new hdlc_dec(minframesize, maxframesize, s != 0); syncs[s].dec = new hdlc_dec(minframesize, maxframesize, s != 0);
for ( int h=0; h<NERRHIST; ++h ) syncs[s].errhist[h] = 0; for (int h = 0; h < NERRHIST; ++h)
syncs[s].errhist[h] = 0;
} }
syncs[cur_sync].dec->debug = sch->debug; syncs[cur_sync].dec->debug = sch->debug;
errslot = 0; errslot = 0;
} }
void run() { void run()
if ( ! opt_writable(lock_out) || {
! opt_writable(framecount_out) || if (!opt_writable(lock_out) || !opt_writable(framecount_out)
! opt_writable(fcserrcount_out) || || !opt_writable(fcserrcount_out)
! opt_writable(hdlcbytecount_out) || || !opt_writable(hdlcbytecount_out)
! opt_writable(databytecount_out) ) return; || !opt_writable(databytecount_out))
return;
bool previous_lock_state = lock_state; bool previous_lock_state = lock_state;
int fcserrcount = 0, framecount = 0; int fcserrcount = 0, framecount = 0;
int hdlcbytecount = 0, databytecount = 0; int hdlcbytecount = 0, databytecount = 0;
// Note: hdlc_dec may already hold one frame ready for output. // Note: hdlc_dec may already hold one frame ready for output.
while ( in.readable() >= chunk_size && while ((long) in.readable() >= chunk_size
out.writable() >= maxframesize+chunk_size ) { && (long) out.writable() >= maxframesize + chunk_size)
if ( ! resync_phase ) { {
if (!resync_phase)
{
// Once every resync_phase, try all decoders // Once every resync_phase, try all decoders
for ( int s=0; s<NSYNCS; ++s ) { for (int s = 0; s < NSYNCS; ++s)
if ( s != cur_sync ) syncs[s].dec->reset(); {
if (s != cur_sync)
syncs[s].dec->reset();
syncs[s].errhist[errslot] = 0; syncs[s].errhist[errslot] = 0;
for ( u8 *pin=in.rd(), *pend=pin+chunk_size; pin<pend; ) { for (u8 *pin = in.rd(), *pend = pin + chunk_size;
pin < pend;)
{
int datasize, hdlc_errors, fcs_errors; int datasize, hdlc_errors, fcs_errors;
u8 *f = syncs[s].dec->decode(&pin, pend-pin, &datasize, u8 *f = syncs[s].dec->decode(&pin, pend - pin,
&hdlc_errors, &fcs_errors); &datasize, &hdlc_errors, &fcs_errors);
syncs[s].errhist[errslot] += hdlc_errors; syncs[s].errhist[errslot] += hdlc_errors;
if ( s == cur_sync ) { if (s == cur_sync)
if ( f ) { {
if (f)
{
lock_state = true; lock_state = true;
output_frame(f, datasize); output_frame(f, datasize);
databytecount += datasize; databytecount += datasize;
@ -207,31 +252,39 @@ namespace leansdr {
// Switch to another sync option ? // Switch to another sync option ?
// Compare total error counts over about NERRHIST frames. // Compare total error counts over about NERRHIST frames.
int total_errors[NSYNCS]; int total_errors[NSYNCS];
for ( int s=0; s<NSYNCS; ++s ) { for (int s = 0; s < NSYNCS; ++s)
{
total_errors[s] = 0; total_errors[s] = 0;
for (int h = 0; h < NERRHIST; ++h) for (int h = 0; h < NERRHIST; ++h)
total_errors[s] += syncs[s].errhist[h]; total_errors[s] += syncs[s].errhist[h];
} }
int best = cur_sync; int best = cur_sync;
for (int s = 0; s < NSYNCS; ++s) for (int s = 0; s < NSYNCS; ++s)
if ( total_errors[s] < total_errors[best] ) best = s; if (total_errors[s] < total_errors[best])
if ( best != cur_sync ) { best = s;
if (best != cur_sync)
{
lock_state = false; lock_state = false;
if ( sch->debug ) fprintf(stderr, "[%d:%d->%d:%d]", if (sch->debug)
cur_sync, total_errors[cur_sync], fprintf(stderr, "[%d:%d->%d:%d]", cur_sync,
best, total_errors[best]); total_errors[cur_sync], best,
total_errors[best]);
// No verbose messages on candidate syncs // No verbose messages on candidate syncs
syncs[cur_sync].dec->debug = false; syncs[cur_sync].dec->debug = false;
cur_sync = best; cur_sync = best;
syncs[cur_sync].dec->debug = sch->debug; syncs[cur_sync].dec->debug = sch->debug;
} }
} else { }
else
{
// Use only the currently selected decoder // Use only the currently selected decoder
for ( u8 *pin=in.rd(), *pend=pin+chunk_size; pin<pend; ) { for (u8 *pin = in.rd(), *pend = pin + chunk_size; pin < pend;)
{
int datasize, hdlc_errors, fcs_errors; int datasize, hdlc_errors, fcs_errors;
u8 *f = syncs[cur_sync].dec->decode(&pin, pend-pin, &datasize, u8 *f = syncs[cur_sync].dec->decode(&pin, pend - pin,
&hdlc_errors, &fcs_errors); &datasize, &hdlc_errors, &fcs_errors);
if ( f ) { if (f)
{
lock_state = true; lock_state = true;
output_frame(f, datasize); output_frame(f, datasize);
databytecount += datasize; databytecount += datasize;
@ -243,7 +296,8 @@ namespace leansdr {
} // resync_phase } // resync_phase
in.read(chunk_size); in.read(chunk_size);
hdlcbytecount += chunk_size; hdlcbytecount += chunk_size;
if ( ++resync_phase >= resync_period ) resync_phase = 0; if (++resync_phase >= resync_period)
resync_phase = 0;
} // Work to do } // Work to do
if (lock_state != previous_lock_state) if (lock_state != previous_lock_state)
@ -255,8 +309,10 @@ namespace leansdr {
} }
private: private:
void output_frame(u8 *f, int size) { void output_frame(u8 *f, int size)
if ( header16 ) { {
if (header16)
{
// Removed 16-bit CRC, add 16-bit prefix -> Still <= maxframesize. // Removed 16-bit CRC, add 16-bit prefix -> Still <= maxframesize.
out.write(size >> 8); out.write(size >> 8);
out.write(size & 255); out.write(size & 255);
@ -275,7 +331,8 @@ namespace leansdr {
pipewriter<int> *hdlcbytecount_out, *databytecount_out; pipewriter<int> *hdlcbytecount_out, *databytecount_out;
static const int NSYNCS = 2; // Two possible polarities static const int NSYNCS = 2; // Two possible polarities
static const int NERRHIST = 2; // Compare error counts over two frames static const int NERRHIST = 2; // Compare error counts over two frames
struct { struct
{
hdlc_dec *dec; hdlc_dec *dec;
int errhist[NERRHIST]; int errhist[NERRHIST];
} syncs[NSYNCS]; } syncs[NSYNCS];
@ -286,7 +343,8 @@ namespace leansdr {
public: public:
int resync_period; int resync_period;
bool header16; // Output length prefix bool header16; // Output length prefix
}; // hdlc_sync };
// hdlc_sync
}// namespace }// namespace

File diff suppressed because it is too large Load Diff