mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-09-03 05:37:50 -04:00
DATV demod: fixed compilation warnings
This commit is contained in:
parent
2e5cfcafee
commit
3354c774fc
@ -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)
|
||||||
|
@ -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}
|
||||||
|
@ -27,72 +27,82 @@
|
|||||||
namespace leansdr
|
namespace leansdr
|
||||||
{
|
{
|
||||||
|
|
||||||
static const int DEFAULT_GUI_DECIMATION = 64;
|
static const int DEFAULT_GUI_DECIMATION = 64;
|
||||||
|
|
||||||
template<typename T> struct datvconstellation : runnable
|
template<typename T> struct datvconstellation: runnable
|
||||||
|
{
|
||||||
|
T xymin;
|
||||||
|
T xymax;
|
||||||
|
unsigned long decimation;
|
||||||
|
unsigned long pixels_per_frame;
|
||||||
|
cstln_lut<256> **cstln; // Optional ptr to optional constellation
|
||||||
|
pipereader<complex<T> > in;
|
||||||
|
unsigned long phase;
|
||||||
|
DATVScreen *m_objDATVScreen;
|
||||||
|
|
||||||
|
datvconstellation(
|
||||||
|
scheduler *sch,
|
||||||
|
pipebuf<complex<T> > &_in,
|
||||||
|
T _xymin,
|
||||||
|
T _xymax,
|
||||||
|
const char *_name = 0,
|
||||||
|
DATVScreen * objDATVScreen = 0) :
|
||||||
|
runnable(sch, _name ? _name : _in.name),
|
||||||
|
xymin(_xymin),
|
||||||
|
xymax(_xymax),
|
||||||
|
decimation(DEFAULT_GUI_DECIMATION),
|
||||||
|
pixels_per_frame(1024),
|
||||||
|
cstln(0),
|
||||||
|
in(_in),
|
||||||
|
phase(0),
|
||||||
|
m_objDATVScreen(objDATVScreen)
|
||||||
{
|
{
|
||||||
T xymin, xymax;
|
}
|
||||||
unsigned long decimation;
|
|
||||||
unsigned long pixels_per_frame;
|
|
||||||
cstln_lut<256> **cstln; // Optional ptr to optional constellation
|
|
||||||
DATVScreen *m_objDATVScreen;
|
|
||||||
|
|
||||||
|
void run()
|
||||||
datvconstellation(scheduler *sch, pipebuf< complex<T> > &_in, T _xymin, T _xymax, const char *_name=NULL, DATVScreen * objDATVScreen=NULL) :
|
{
|
||||||
runnable(sch, _name?_name:_in.name),
|
|
||||||
xymin(_xymin),
|
|
||||||
xymax(_xymax),
|
|
||||||
decimation(DEFAULT_GUI_DECIMATION),
|
|
||||||
pixels_per_frame(1024),
|
|
||||||
cstln(NULL),
|
|
||||||
in(_in),
|
|
||||||
phase(0),
|
|
||||||
m_objDATVScreen(objDATVScreen)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void run()
|
|
||||||
{
|
|
||||||
//Symbols
|
//Symbols
|
||||||
|
|
||||||
while ( in.readable() >= pixels_per_frame )
|
while (in.readable() >= pixels_per_frame)
|
||||||
{
|
{
|
||||||
if ( ! phase )
|
if (!phase)
|
||||||
{
|
{
|
||||||
m_objDATVScreen->resetImage();
|
m_objDATVScreen->resetImage();
|
||||||
|
|
||||||
complex<T> *p = in.rd(), *pend = p+pixels_per_frame;
|
complex<T> *p = in.rd(), *pend = p + pixels_per_frame;
|
||||||
|
|
||||||
for ( ; p<pend; ++p )
|
for (; p < pend; ++p)
|
||||||
{
|
{
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( cstln && (*cstln) )
|
if (cstln && (*cstln))
|
||||||
{
|
{
|
||||||
// Plot constellation points
|
// Plot constellation points
|
||||||
|
|
||||||
for ( int i=0; i<(*cstln)->nsymbols; ++i )
|
for (int i = 0; i < (*cstln)->nsymbols; ++i)
|
||||||
{
|
|
||||||
complex<signed char> *p = &(*cstln)->symbols[i];
|
|
||||||
int x = 256*(p->re-xymin)/(xymax-xymin);
|
|
||||||
int y = 256 - 256*(p->im-xymin)/(xymax-xymin);
|
|
||||||
|
|
||||||
for ( int d=-4; d<=4; ++d )
|
|
||||||
{
|
{
|
||||||
m_objDATVScreen->selectRow(x+d);
|
complex<signed char> *p = &(*cstln)->symbols[i];
|
||||||
m_objDATVScreen->setDataColor(y,5,250,250);
|
int x = 256 * (p->re - xymin) / (xymax - xymin);
|
||||||
m_objDATVScreen->selectRow(x);
|
int y = 256 - 256 * (p->im - xymin) / (xymax - xymin);
|
||||||
m_objDATVScreen->setDataColor(y+d,5,250,250);
|
|
||||||
|
for (int d = -4; d <= 4; ++d)
|
||||||
|
{
|
||||||
|
m_objDATVScreen->selectRow(x + d);
|
||||||
|
m_objDATVScreen->setDataColor(y, 5, 250, 250);
|
||||||
|
m_objDATVScreen->selectRow(x);
|
||||||
|
m_objDATVScreen->setDataColor(y + d, 5, 250, 250);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_objDATVScreen->renderImage(NULL);
|
m_objDATVScreen->renderImage(NULL);
|
||||||
@ -101,27 +111,25 @@ namespace leansdr
|
|||||||
|
|
||||||
in.read(pixels_per_frame);
|
in.read(pixels_per_frame);
|
||||||
|
|
||||||
if ( ++phase >= decimation )
|
if (++phase >= decimation)
|
||||||
{
|
{
|
||||||
phase = 0;
|
phase = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//private:
|
//private:
|
||||||
pipereader< complex<T> > in;
|
//gfx g;
|
||||||
unsigned long phase;
|
|
||||||
//gfx g;
|
|
||||||
|
|
||||||
void draw_begin()
|
void draw_begin()
|
||||||
{
|
{
|
||||||
//g.clear();
|
//g.clear();
|
||||||
//g.setfg(0, 255, 0);
|
//g.setfg(0, 255, 0);
|
||||||
//g.line(g.w/2,0, g.w/2, g.h);
|
//g.line(g.w/2,0, g.w/2, g.h);
|
||||||
//g.line(0,g.h/2, g.w,g.h/2);
|
//g.line(0,g.h/2, g.w,g.h/2);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,6 @@ class DownChannelizer;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "datvconstellation.h"
|
#include "datvconstellation.h"
|
||||||
#include "datvvideoplayer.h"
|
#include "datvvideoplayer.h"
|
||||||
|
|
||||||
@ -70,69 +68,82 @@ 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
|
||||||
{
|
{
|
||||||
dvb_version standard;
|
dvb_version standard;
|
||||||
dvb_sampler sampler;
|
dvb_sampler sampler;
|
||||||
|
|
||||||
int buf_factor; // Buffer sizing
|
int buf_factor; // Buffer sizing
|
||||||
float Fs; // Sampling frequency (Hz)
|
float Fs; // Sampling frequency (Hz)
|
||||||
float Fderot; // Shift the signal (Hz). Note: Ftune is faster
|
float Fderot; // Shift the signal (Hz). Note: Ftune is faster
|
||||||
int anf; // Number of auto notch filters
|
int anf; // Number of auto notch filters
|
||||||
bool cnr; // Measure CNR
|
bool cnr; // Measure CNR
|
||||||
unsigned int decim; // Decimation, 0=auto
|
unsigned int decim; // Decimation, 0=auto
|
||||||
float Fm; // QPSK symbol rate (Hz)
|
float Fm; // QPSK symbol rate (Hz)
|
||||||
cstln_lut<256>::predef constellation;
|
cstln_lut<256>::predef constellation;
|
||||||
code_rate fec;
|
code_rate fec;
|
||||||
float Ftune; // Bias frequency for the QPSK demodulator (Hz)
|
float Ftune; // Bias frequency for the QPSK demodulator (Hz)
|
||||||
bool allow_drift;
|
bool allow_drift;
|
||||||
bool fastlock;
|
bool fastlock;
|
||||||
bool viterbi;
|
bool viterbi;
|
||||||
bool hard_metric;
|
bool hard_metric;
|
||||||
bool resample;
|
bool resample;
|
||||||
float resample_rej; // Approx. filter rejection in dB
|
float resample_rej; // Approx. filter rejection in dB
|
||||||
int rrc_steps; // Discrete steps between symbols, 0=auto
|
int rrc_steps; // Discrete steps between symbols, 0=auto
|
||||||
float rrc_rej; // Approx. RRC filter rejection in dB
|
float rrc_rej; // Approx. RRC filter rejection in dB
|
||||||
float rolloff; // Roll-off 0..1
|
float rolloff; // Roll-off 0..1
|
||||||
bool hdlc; // Expect HDLC frames instead of MPEG packets
|
bool hdlc; // Expect HDLC frames instead of MPEG packets
|
||||||
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() :
|
||||||
Fs(2.4e6),
|
standard(DVB_S),
|
||||||
Fderot(0),
|
sampler(SAMP_LINEAR),
|
||||||
anf(1),
|
buf_factor(4),
|
||||||
cnr(false),
|
Fs(2.4e6),
|
||||||
decim(0),
|
Fderot(0),
|
||||||
Fm(2e6),
|
anf(1),
|
||||||
standard(DVB_S),
|
cnr(false),
|
||||||
constellation(cstln_lut<256>::QPSK),
|
decim(0),
|
||||||
fec(FEC12),
|
Fm(2e6),
|
||||||
Ftune(0),
|
constellation(cstln_lut<256>::QPSK),
|
||||||
allow_drift(false),
|
fec(FEC12),
|
||||||
fastlock(true),
|
Ftune(0),
|
||||||
viterbi(false),
|
allow_drift(false),
|
||||||
hard_metric(false),
|
fastlock(true),
|
||||||
resample(false),
|
viterbi(false),
|
||||||
resample_rej(10),
|
hard_metric(false),
|
||||||
sampler(SAMP_LINEAR),
|
resample(false),
|
||||||
rrc_steps(0),
|
resample_rej(10),
|
||||||
rrc_rej(10),
|
rrc_steps(0),
|
||||||
rolloff(0.35),
|
rrc_rej(10),
|
||||||
hdlc(false),
|
rolloff(0.35),
|
||||||
packetized(false),
|
hdlc(false),
|
||||||
Finfo(5)
|
packetized(false),
|
||||||
{
|
Finfo(5)
|
||||||
}
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct DATVConfig
|
struct DATVConfig
|
||||||
{
|
{
|
||||||
int intMsps;
|
int intMsps;
|
||||||
@ -152,118 +163,205 @@ struct DATVConfig
|
|||||||
bool blnViterbi;
|
bool blnViterbi;
|
||||||
|
|
||||||
DATVConfig() :
|
DATVConfig() :
|
||||||
intMsps(1024000),
|
intMsps(1024000),
|
||||||
intRFBandwidth(1024000),
|
intRFBandwidth(1024000),
|
||||||
intCenterFrequency(0),
|
intCenterFrequency(0),
|
||||||
enmStandard(DVB_S),
|
enmStandard(DVB_S),
|
||||||
enmModulation(BPSK),
|
enmModulation(BPSK),
|
||||||
enmFEC(FEC12),
|
enmFEC(FEC12),
|
||||||
intSampleRate(1024000),
|
intSampleRate(1024000),
|
||||||
intSymbolRate(250000),
|
intSymbolRate(250000),
|
||||||
intNotchFilters(1),
|
intNotchFilters(1),
|
||||||
blnAllowDrift(false),
|
blnAllowDrift(false),
|
||||||
blnFastLock(false),
|
blnFastLock(false),
|
||||||
blnHDLC(false),
|
blnHDLC(false),
|
||||||
blnHardMetric(false),
|
blnHardMetric(false),
|
||||||
blnResample(false),
|
blnResample(false),
|
||||||
blnViterbi(false)
|
blnViterbi(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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,
|
||||||
|
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);
|
||||||
|
|
||||||
|
virtual void feed(const SampleVector::const_iterator& begin,
|
||||||
void configure(MessageQueue* objMessageQueue,
|
const SampleVector::const_iterator& end, bool po);
|
||||||
int intRFBandwidth,
|
virtual void start();
|
||||||
int intCenterFrequency,
|
virtual void stop();
|
||||||
dvb_version enmStandard,
|
virtual bool handleMessage(const Message& cmd);
|
||||||
DATVModulation enmModulation,
|
|
||||||
code_rate enmFEC,
|
|
||||||
int intSymbolRate,
|
|
||||||
int intNotchFilters,
|
|
||||||
bool blnAllowDrift,
|
|
||||||
bool blnFastLock,
|
|
||||||
bool blnHDLC,
|
|
||||||
bool blnHardMetric,
|
|
||||||
bool blnResample,
|
|
||||||
bool blnViterbi);
|
|
||||||
|
|
||||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po);
|
|
||||||
virtual void start();
|
|
||||||
virtual void stop();
|
|
||||||
virtual bool handleMessage(const Message& cmd);
|
|
||||||
|
|
||||||
bool SetDATVScreen(DATVScreen *objScreen);
|
bool SetDATVScreen(DATVScreen *objScreen);
|
||||||
DATVideostream * SetVideoRender(DATVideoRender *objScreen);
|
DATVideostream * SetVideoRender(DATVideoRender *objScreen);
|
||||||
|
|
||||||
bool PlayVideo(bool blnStartStop);
|
bool PlayVideo(bool blnStartStop);
|
||||||
|
|
||||||
void InitDATVParameters(int intMsps,
|
void InitDATVParameters(
|
||||||
int intRFBandwidth,
|
int intMsps,
|
||||||
int intCenterFrequency,
|
int intRFBandwidth,
|
||||||
dvb_version enmStandard,
|
int intCenterFrequency,
|
||||||
DATVModulation enmModulation,
|
dvb_version enmStandard,
|
||||||
code_rate enmFEC,
|
DATVModulation enmModulation,
|
||||||
int intSampleRate,
|
code_rate enmFEC,
|
||||||
int intSymbolRate,
|
int intSampleRate,
|
||||||
int intNotchFilters,
|
int intSymbolRate,
|
||||||
bool blnAllowDrift,
|
int intNotchFilters,
|
||||||
bool blnFastLock,
|
bool blnAllowDrift,
|
||||||
bool blnHDLC,
|
bool blnFastLock,
|
||||||
bool blnHardMetric,
|
bool blnHDLC,
|
||||||
bool blnResample,
|
bool blnHardMetric,
|
||||||
bool blnViterbi);
|
bool blnResample,
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
unsigned long m_lngExpectedReadIQ;
|
unsigned long m_lngExpectedReadIQ;
|
||||||
unsigned long m_lngReadIQ;
|
unsigned long m_lngReadIQ;
|
||||||
@ -305,7 +403,7 @@ private:
|
|||||||
cnr_fft<f32> *r_cnr;
|
cnr_fft<f32> *r_cnr;
|
||||||
|
|
||||||
//FILTERING
|
//FILTERING
|
||||||
fir_filter<cf32,float> *r_resample;
|
fir_filter<cf32, float> *r_resample;
|
||||||
pipebuf<cf32> *p_resampled;
|
pipebuf<cf32> *p_resampled;
|
||||||
float *coeffs;
|
float *coeffs;
|
||||||
int ncoeffs;
|
int ncoeffs;
|
||||||
@ -344,18 +442,17 @@ private:
|
|||||||
pipebuf<u8> *p_mpegbytes;
|
pipebuf<u8> *p_mpegbytes;
|
||||||
pipebuf<int> *p_lock;
|
pipebuf<int> *p_lock;
|
||||||
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;
|
||||||
|
|
||||||
// REED-SOLOMON
|
// REED-SOLOMON
|
||||||
pipebuf<int> *p_vbitcount;
|
pipebuf<int> *p_vbitcount;
|
||||||
pipebuf<int> *p_verrcount;
|
pipebuf<int> *p_verrcount;
|
||||||
pipebuf<tspacket> *p_rtspackets;
|
pipebuf<tspacket> *p_rtspackets;
|
||||||
rs_decoder<u8,0> *r_rsdec;
|
rs_decoder<u8, 0> *r_rsdec;
|
||||||
|
|
||||||
// BER ESTIMATION
|
// BER ESTIMATION
|
||||||
pipebuf<float> *p_vber;
|
pipebuf<float> *p_vber;
|
||||||
@ -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,87 +469,26 @@ private:
|
|||||||
//CONSTELLATION
|
//CONSTELLATION
|
||||||
datvconstellation<f32> *r_scope_symbols;
|
datvconstellation<f32> *r_scope_symbols;
|
||||||
|
|
||||||
|
DeviceSourceAPI* m_deviceAPI;
|
||||||
|
|
||||||
private:
|
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||||
|
DownChannelizer* m_channelizer;
|
||||||
|
|
||||||
DeviceSourceAPI* m_deviceAPI;
|
//*************** DATV PARAMETERS ***************
|
||||||
|
DATVScreen * m_objRegisteredDATVScreen;
|
||||||
|
DATVideoRender * m_objRegisteredVideoRender;
|
||||||
|
DATVideostream * m_objVideoStream;
|
||||||
|
DATVideoRenderThread * m_objRenderThread;
|
||||||
|
|
||||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
fftfilt * m_objRFFilter;
|
||||||
DownChannelizer* m_channelizer;
|
NCO m_objNCO;
|
||||||
|
|
||||||
//*************** DATV PARAMETERS ***************
|
bool m_blnInitialized;
|
||||||
DATVScreen * m_objRegisteredDATVScreen;
|
bool m_blnRenderingVideo;
|
||||||
DATVideoRender * m_objRegisteredVideoRender;
|
|
||||||
DATVideostream * m_objVideoStream;
|
|
||||||
DATVideoRenderThread * m_objRenderThread;
|
|
||||||
|
|
||||||
fftfilt * m_objRFFilter;
|
DATVModulation m_enmModulation;
|
||||||
NCO m_objNCO;
|
|
||||||
|
|
||||||
bool m_blnInitialized;
|
|
||||||
bool m_blnRenderingVideo;
|
|
||||||
|
|
||||||
DATVModulation m_enmModulation;
|
|
||||||
|
|
||||||
//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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
//QElapsedTimer m_objTimer;
|
||||||
|
|
||||||
DATVConfig m_objRunning;
|
DATVConfig m_objRunning;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -5,347 +5,438 @@
|
|||||||
#include "leansdr/framework.h"
|
#include "leansdr/framework.h"
|
||||||
#include "leansdr/math.h"
|
#include "leansdr/math.h"
|
||||||
|
|
||||||
namespace leansdr {
|
namespace leansdr
|
||||||
|
{
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// DSP blocks
|
// DSP blocks
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// [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,
|
{
|
||||||
pipebuf< complex<Tout> > &_out)
|
cconverter(scheduler *sch, pipebuf<complex<Tin> > &_in,
|
||||||
: runnable(sch, "cconverter"),
|
pipebuf<complex<Tout> > &_out) :
|
||||||
in(_in), out(_out) {
|
runnable(sch, "cconverter"), in(_in), out(_out)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
void run() {
|
|
||||||
unsigned long count = min(in.readable(), out.writable());
|
|
||||||
complex<Tin> *pin=in.rd(), *pend=pin+count;
|
|
||||||
complex<Tout> *pout = out.wr();
|
|
||||||
for ( ; pin<pend; ++pin,++pout ) {
|
|
||||||
pout->re = Zout + (pin->re-(Tin)Zin)*Gn/Gd;
|
|
||||||
pout->im = Zout + (pin->im-(Tin)Zin)*Gn/Gd;
|
|
||||||
}
|
|
||||||
in.read(count);
|
|
||||||
out.written(count);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
pipereader< complex<Tin> > in;
|
|
||||||
pipewriter< complex<Tout> > out;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
void run()
|
||||||
struct cfft_engine {
|
{
|
||||||
const int n;
|
unsigned long count = min(in.readable(), out.writable());
|
||||||
cfft_engine(int _n) : n(_n), invsqrtn(1.0/sqrt(n)) {
|
complex<Tin> *pin = in.rd(), *pend = pin + count;
|
||||||
// Compute log2(n)
|
complex<Tout> *pout = out.wr();
|
||||||
logn = 0;
|
for (; pin < pend; ++pin, ++pout)
|
||||||
for ( int t=n; t>1; t>>=1 ) ++logn;
|
{
|
||||||
// Bit reversal
|
pout->re = Zout + (pin->re - (Tin) Zin) * Gn / Gd;
|
||||||
bitrev = new int[n];
|
pout->im = Zout + (pin->im - (Tin) Zin) * Gn / Gd;
|
||||||
for ( int i=0; i<n; ++i ) {
|
}
|
||||||
bitrev[i] = 0;
|
in.read(count);
|
||||||
for ( int b=0; b<logn; ++b ) bitrev[i] = (bitrev[i]<<1) | ((i>>b)&1);
|
out.written(count);
|
||||||
}
|
|
||||||
// Float constants
|
|
||||||
omega = new complex<T>[n];
|
|
||||||
omega_rev = new complex<T>[n];
|
|
||||||
for ( int i=0; i<n; ++i ) {
|
|
||||||
float a = 2.0*M_PI * i / n;
|
|
||||||
omega_rev[i].re = (omega[i].re = cosf(a));
|
|
||||||
omega_rev[i].im = - (omega[i].im = sinf(a));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void inplace(complex<T> *data, bool reverse=false) {
|
|
||||||
// Bit-reversal permutation
|
private:
|
||||||
for ( int i=0; i<n; ++i ) {
|
pipereader<complex<Tin> > in;
|
||||||
int r = bitrev[i];
|
pipewriter<complex<Tout> > out;
|
||||||
if ( r < i ) { complex<T> tmp=data[i]; data[i]=data[r]; data[r]=tmp; }
|
};
|
||||||
}
|
|
||||||
complex<T> *om = reverse ? omega_rev : omega;
|
template<typename T>
|
||||||
// Danielson-Lanczos
|
struct cfft_engine
|
||||||
for ( int i=0; i<logn; ++i ) {
|
{
|
||||||
int hbs = 1 << i;
|
const unsigned int n;
|
||||||
int dom = 1 << (logn-1-i);
|
|
||||||
for ( int j=0; j<dom; ++j ) {
|
cfft_engine(unsigned int _n) :
|
||||||
int p = j*hbs*2, q = p+hbs;
|
n(_n), invsqrtn(1.0 / sqrt(n))
|
||||||
for ( int k=0; k<hbs; ++k ) {
|
{
|
||||||
complex<T> &w = om[k*dom];
|
// Compute log2(n)
|
||||||
complex<T> &dqk = data[q+k];
|
logn = 0;
|
||||||
complex<T> x(w.re*dqk.re - w.im*dqk.im,
|
for (int t = n; t > 1; t >>= 1)
|
||||||
w.re*dqk.im + w.im*dqk.re);
|
++logn;
|
||||||
data[q+k].re = data[p+k].re - x.re;
|
// Bit reversal
|
||||||
data[q+k].im = data[p+k].im - x.im;
|
bitrev = new int[n];
|
||||||
data[p+k].re = data[p+k].re + x.re;
|
for (unsigned int i = 0; i < n; ++i)
|
||||||
data[p+k].im = data[p+k].im + x.im;
|
{
|
||||||
}
|
bitrev[i] = 0;
|
||||||
}
|
for (int b = 0; b < logn; ++b)
|
||||||
}
|
bitrev[i] = (bitrev[i] << 1) | ((i >> b) & 1);
|
||||||
if ( reverse ) {
|
}
|
||||||
float invn = 1.0 / n;
|
// Float constants
|
||||||
for ( int i=0; i<n; ++i ) {
|
omega = new complex<T> [n];
|
||||||
data[i].re *= invn;
|
omega_rev = new complex<T> [n];
|
||||||
data[i].im *= invn;
|
for (unsigned int i = 0; i < n; ++i)
|
||||||
}
|
{
|
||||||
}
|
float a = 2.0 * M_PI * i / n;
|
||||||
|
omega_rev[i].re = (omega[i].re = cosf(a));
|
||||||
|
omega_rev[i].im = -(omega[i].im = sinf(a));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
|
void inplace(complex<T> *data, bool reverse = false)
|
||||||
|
{
|
||||||
|
// Bit-reversal permutation
|
||||||
|
for (unsigned int i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
// Danielson-Lanczos
|
||||||
|
for (int i = 0; i < logn; ++i)
|
||||||
|
{
|
||||||
|
int hbs = 1 << i;
|
||||||
|
int dom = 1 << (logn - 1 - i);
|
||||||
|
for (int j = 0; j < dom; ++j)
|
||||||
|
{
|
||||||
|
int p = j * hbs * 2, q = p + hbs;
|
||||||
|
for (int k = 0; k < hbs; ++k)
|
||||||
|
{
|
||||||
|
complex<T> &w = om[k * dom];
|
||||||
|
complex<T> &dqk = data[q + k];
|
||||||
|
complex<T> x(w.re * dqk.re - w.im * dqk.im,
|
||||||
|
w.re * dqk.im + w.im * dqk.re);
|
||||||
|
data[q + k].re = data[p + k].re - x.re;
|
||||||
|
data[q + k].im = data[p + k].im - x.im;
|
||||||
|
data[p + k].re = data[p + k].re + x.re;
|
||||||
|
data[p + k].im = data[p + k].im + x.im;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (reverse)
|
||||||
|
{
|
||||||
|
float invn = 1.0 / n;
|
||||||
|
for (unsigned int i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
data[i].re *= invn;
|
||||||
|
data[i].im *= invn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
int logn;
|
int logn;
|
||||||
int *bitrev;
|
int *bitrev;
|
||||||
complex<T> *omega, *omega_rev;
|
complex<T> *omega, *omega_rev;
|
||||||
float invsqrtn;
|
float invsqrtn;
|
||||||
};
|
};
|
||||||
|
|
||||||
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() {
|
|
||||||
int n = out.writable();
|
void run()
|
||||||
if ( in1.readable() < n ) n = in1.readable();
|
{
|
||||||
if ( in2.readable() < n ) n = in2.readable();
|
int n = out.writable();
|
||||||
T *pin1=in1.rd(), *pin2=in2.rd(), *pout=out.wr(), *pend=pout+n;
|
if (in1.readable() < n)
|
||||||
while ( pout < pend ) *pout++ = *pin1++ + *pin2++;
|
n = in1.readable();
|
||||||
in1.read(n);
|
if (in2.readable() < n)
|
||||||
in2.read(n);
|
n = in2.readable();
|
||||||
out.written(n);
|
T *pin1 = in1.rd(), *pin2 = in2.rd(), *pout = out.wr(), *pend = pout
|
||||||
|
+ n;
|
||||||
|
while (pout < pend)
|
||||||
|
*pout++ = *pin1++ + *pin2++;
|
||||||
|
in1.read(n);
|
||||||
|
in2.read(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() {
|
|
||||||
unsigned long count = min(in.readable(), out.writable());
|
void run()
|
||||||
Tin *pin=in.rd(), *pend=pin+count;
|
{
|
||||||
Tout *pout = out.wr();
|
unsigned long count = min(in.readable(), out.writable());
|
||||||
for ( ; pin<pend; ++pin,++pout ) *pout = *pin * scale;
|
Tin *pin = in.rd(), *pend = pin + count;
|
||||||
in.read(count);
|
Tout *pout = out.wr();
|
||||||
out.written(count);
|
for (; pin < pend; ++pin, ++pout)
|
||||||
|
*pout = *pin * scale;
|
||||||
|
in.read(count);
|
||||||
|
out.written(count);
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
|
private:
|
||||||
pipereader<Tin> in;
|
pipereader<Tin> in;
|
||||||
pipewriter<Tout> out;
|
pipewriter<Tout> out;
|
||||||
};
|
};
|
||||||
|
|
||||||
// [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() {
|
|
||||||
int n = out.writable();
|
void run()
|
||||||
complex<T> *pout=out.wr(), *pend=pout+n;
|
{
|
||||||
while ( pout < pend ) {
|
int n = out.writable();
|
||||||
// TAOCP
|
complex<T> *pout = out.wr(), *pend = pout + n;
|
||||||
float x, y, r2;
|
while (pout < pend)
|
||||||
do {
|
{
|
||||||
x = 2*drand48() - 1;
|
// TAOCP
|
||||||
y = 2*drand48() - 1;
|
float x, y, r2;
|
||||||
r2 = x*x + y*y;
|
do
|
||||||
} while ( r2==0 || r2>=1 );
|
{
|
||||||
float k = sqrtf(-logf(r2)/r2) * stddev;
|
x = 2 * drand48() - 1;
|
||||||
pout->re = k*x;
|
y = 2 * drand48() - 1;
|
||||||
pout->im = k*y;
|
r2 = x * x + y * y;
|
||||||
++pout;
|
} while (r2 == 0 || r2 >= 1);
|
||||||
}
|
float k = sqrtf(-logf(r2) / r2) * stddev;
|
||||||
out.written(n);
|
pout->re = k * x;
|
||||||
|
pout->im = k * y;
|
||||||
|
++pout;
|
||||||
|
}
|
||||||
|
out.written(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
float stddev;
|
float stddev;
|
||||||
private:
|
|
||||||
pipewriter< complex<T> > out;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
private:
|
||||||
struct naive_lowpass : runnable {
|
pipewriter<complex<T> > out;
|
||||||
naive_lowpass(scheduler *sch, pipebuf<T> &_in, pipebuf<T> &_out, int _w)
|
};
|
||||||
: runnable(sch, "lowpass"), in(_in), out(_out), w(_w) {
|
|
||||||
|
template<typename T>
|
||||||
|
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)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void run() {
|
void run()
|
||||||
if ( in.readable() < w ) return;
|
{
|
||||||
unsigned long count = min(in.readable()-w, out.writable());
|
if (in.readable() < w)
|
||||||
T *pin=in.rd(), *pend=pin+count;
|
return;
|
||||||
T *pout = out.wr();
|
unsigned long count = min(in.readable() - w, out.writable());
|
||||||
float k = 1.0 / w;
|
T *pin = in.rd(), *pend = pin + count;
|
||||||
for ( ; pin<pend; ++pin,++pout ) {
|
T *pout = out.wr();
|
||||||
T x = 0.0;
|
float k = 1.0 / w;
|
||||||
for ( int i=0; i<w; ++i ) x = x + pin[i];
|
for (; pin < pend; ++pin, ++pout)
|
||||||
*pout = x * k;
|
{
|
||||||
}
|
T x = 0.0;
|
||||||
in.read(count);
|
for (int i = 0; i < w; ++i)
|
||||||
out.written(count);
|
x = x + pin[i];
|
||||||
|
*pout = x * k;
|
||||||
|
}
|
||||||
|
in.read(count);
|
||||||
|
out.written(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pipereader<T> in;
|
pipereader<T> in;
|
||||||
pipewriter<T> out;
|
pipewriter<T> out;
|
||||||
int w;
|
int w;
|
||||||
};
|
};
|
||||||
|
|
||||||
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),
|
||||||
shifted_coeffs = new T[ncoeffs];
|
in(_in),
|
||||||
set_freq(0);
|
out(_out),
|
||||||
|
decim(_decim)
|
||||||
|
{
|
||||||
|
shifted_coeffs = new T[ncoeffs];
|
||||||
|
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;
|
{
|
||||||
if ( fabs(current_freq-new_freq) > freq_tol ) {
|
float new_freq = *freq_tap * tap_multiplier;
|
||||||
if ( sch->verbose )
|
if (fabs(current_freq - new_freq) > freq_tol)
|
||||||
fprintf(stderr, "Shifting filter %f -> %f\n",
|
{
|
||||||
current_freq, new_freq);
|
if (sch->verbose)
|
||||||
set_freq(new_freq);
|
fprintf(stderr, "Shifting filter %f -> %f\n", current_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 =
|
||||||
// TBD use coeffs when current_freq=0 (fewer mults if float)
|
out.wr();
|
||||||
for ( ; pin<pend; pin+=decim,++pout ) {
|
// TBD use coeffs when current_freq=0 (fewer mults if float)
|
||||||
T *pc = shifted_coeffs;
|
for (; pin < pend; pin += decim, ++pout)
|
||||||
T *pi = pin;
|
{
|
||||||
T x = 0;
|
T *pc = shifted_coeffs;
|
||||||
for ( unsigned int i=ncoeffs; i--; ++pc,--pi )
|
T *pi = pin;
|
||||||
x = x + (*pc)*(*pi);
|
T x = 0;
|
||||||
*pout = x;
|
for (unsigned int i = ncoeffs; i--; ++pc, --pi)
|
||||||
}
|
x = x + (*pc) * (*pi);
|
||||||
in.read(count*decim);
|
*pout = x;
|
||||||
out.written(count);
|
}
|
||||||
|
in.read(count * decim);
|
||||||
|
out.written(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
public:
|
||||||
|
float *freq_tap;
|
||||||
|
float tap_multiplier;
|
||||||
|
float freq_tol;
|
||||||
|
|
||||||
|
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)
|
||||||
float a = 2*M_PI * f * (i-ncoeffs/2);
|
{
|
||||||
float c=cosf(a), s=sinf(a);
|
for (unsigned int i = 0; i < ncoeffs; ++i)
|
||||||
// TBD Support T=complex
|
{
|
||||||
shifted_coeffs[i].re = coeffs[i] * c;
|
float a = 2 * M_PI * f * (i - ncoeffs / 2);
|
||||||
shifted_coeffs[i].im = coeffs[i] * s;
|
float c = cosf(a), s = sinf(a);
|
||||||
}
|
// TBD Support T=complex
|
||||||
current_freq = f;
|
shifted_coeffs[i].re = coeffs[i] * c;
|
||||||
|
shifted_coeffs[i].im = coeffs[i] * s;
|
||||||
|
}
|
||||||
|
current_freq = f;
|
||||||
}
|
}
|
||||||
public:
|
};
|
||||||
|
// fir_filter
|
||||||
|
|
||||||
|
// FIR FILTER WITH INTERPOLATION AND DECIMATION
|
||||||
|
|
||||||
|
template<typename T, typename Tc>
|
||||||
|
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
|
||||||
|
shifted_coeffs = new T[ncoeffs];
|
||||||
|
set_freq(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
if (in.readable() < ncoeffs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (freq_tap)
|
||||||
|
{
|
||||||
|
float new_freq = *freq_tap * tap_multiplier;
|
||||||
|
if (fabs(current_freq - new_freq) > freq_tol)
|
||||||
|
{
|
||||||
|
if (sch->verbose)
|
||||||
|
fprintf(stderr, "Shifting filter %f -> %f\n", current_freq,
|
||||||
|
new_freq);
|
||||||
|
set_freq(new_freq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in.readable() * interp < ncoeffs)
|
||||||
|
return;
|
||||||
|
unsigned long count = min((in.readable() * interp - ncoeffs) / interp,
|
||||||
|
out.writable() / interp);
|
||||||
|
int latency = (ncoeffs + interp) / interp;
|
||||||
|
T *pin = in.rd() + latency, *pend = pin + count, *pout = out.wr();
|
||||||
|
// TBD use coeffs when current_freq=0 (fewer mults if float)
|
||||||
|
for (; pin < pend; ++pin)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < interp; ++i, ++pout)
|
||||||
|
{
|
||||||
|
T *pi = pin;
|
||||||
|
T *pc = shifted_coeffs + i, *pcend = shifted_coeffs + ncoeffs;
|
||||||
|
T x = 0;
|
||||||
|
for (; pc < pcend; pc += interp, --pi)
|
||||||
|
x = x + (*pc) * (*pi);
|
||||||
|
*pout = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.read(count);
|
||||||
|
out.written(count * interp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
float *freq_tap;
|
float *freq_tap;
|
||||||
float tap_multiplier;
|
float tap_multiplier;
|
||||||
float freq_tol;
|
float freq_tol;
|
||||||
}; // fir_filter
|
|
||||||
|
|
||||||
|
private:
|
||||||
// FIR FILTER WITH INTERPOLATION AND DECIMATION
|
|
||||||
|
|
||||||
template<typename T, typename Tc>
|
|
||||||
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
|
|
||||||
shifted_coeffs = new T[ncoeffs];
|
|
||||||
set_freq(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void run() {
|
|
||||||
if ( in.readable() < ncoeffs ) return;
|
|
||||||
|
|
||||||
if ( freq_tap ) {
|
|
||||||
float new_freq = *freq_tap * tap_multiplier;
|
|
||||||
if ( fabs(current_freq-new_freq) > freq_tol ) {
|
|
||||||
if ( sch->verbose )
|
|
||||||
fprintf(stderr, "Shifting filter %f -> %f\n",
|
|
||||||
current_freq, new_freq);
|
|
||||||
set_freq(new_freq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( in.readable()*interp < ncoeffs ) return;
|
|
||||||
unsigned long count = min((in.readable()*interp-ncoeffs)/interp,
|
|
||||||
out.writable()/interp);
|
|
||||||
int latency = (ncoeffs+interp) / interp;
|
|
||||||
T *pin=in.rd()+latency, *pend=pin+count, *pout=out.wr();
|
|
||||||
// TBD use coeffs when current_freq=0 (fewer mults if float)
|
|
||||||
for ( ; pin<pend; ++pin ) {
|
|
||||||
for ( int i=0; i<interp; ++i,++pout ) {
|
|
||||||
T *pi = pin;
|
|
||||||
T *pc = shifted_coeffs+i, *pcend=shifted_coeffs+ncoeffs;
|
|
||||||
T x = 0;
|
|
||||||
for ( ; pc<pcend; pc+=interp,--pi )
|
|
||||||
x = x + (*pc)*(*pi);
|
|
||||||
*pout = x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
in.read(count);
|
|
||||||
out.written(count*interp);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned int ncoeffs;
|
unsigned int ncoeffs;
|
||||||
Tc *coeffs;
|
Tc *coeffs;
|
||||||
int interp, decim;
|
int interp, decim;
|
||||||
pipereader<T> in;
|
pipereader<T> in;
|
||||||
pipewriter<T> out;
|
pipewriter<T> out;
|
||||||
|
|
||||||
public:
|
|
||||||
float *freq_tap;
|
|
||||||
float tap_multiplier;
|
|
||||||
float freq_tol;
|
|
||||||
|
|
||||||
private:
|
|
||||||
T *shifted_coeffs;
|
T *shifted_coeffs;
|
||||||
float current_freq;
|
float current_freq;
|
||||||
void set_freq(float f) {
|
|
||||||
for ( int i=0; i<ncoeffs; ++i ) {
|
|
||||||
float a = 2*M_PI * f * i;
|
|
||||||
float c=cosf(a), s=sinf(a);
|
|
||||||
// TBD Support T=complex
|
|
||||||
shifted_coeffs[i].re = coeffs[i] * c;
|
|
||||||
shifted_coeffs[i].im = coeffs[i] * s;
|
|
||||||
}
|
|
||||||
current_freq = f;
|
|
||||||
}
|
|
||||||
}; // fir_resampler
|
|
||||||
|
|
||||||
} // namespace
|
void set_freq(float f)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ncoeffs; ++i)
|
||||||
|
{
|
||||||
|
float a = 2 * M_PI * f * i;
|
||||||
|
float c = cosf(a), s = sinf(a);
|
||||||
|
// TBD Support T=complex
|
||||||
|
shifted_coeffs[i].re = coeffs[i] * c;
|
||||||
|
shifted_coeffs[i].im = coeffs[i] * s;
|
||||||
|
}
|
||||||
|
current_freq = f;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// fir_resampler
|
||||||
|
|
||||||
|
}// namespace
|
||||||
|
|
||||||
#endif // LEANSDR_DSP_H
|
#endif // LEANSDR_DSP_H
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,54 +1,104 @@
|
|||||||
#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)
|
||||||
// DSP framework
|
{
|
||||||
//////////////////////////////////////////////////////////////////////
|
fprintf(stderr, "leansdr::fail: %s\n", s);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
// [pipebuf] is a FIFO buffer with multiple readers.
|
//////////////////////////////////////////////////////////////////////
|
||||||
// [pipewriter] is a client-side hook for writing into a [pipebuf].
|
// DSP framework
|
||||||
// [pipereader] is a client-side hook reading from a [pipebuf].
|
//////////////////////////////////////////////////////////////////////
|
||||||
// [runnable] is anything that moves data between [pipebufs].
|
|
||||||
// [scheduler] is a global context which invokes [runnables] until fixpoint.
|
|
||||||
|
|
||||||
static const int MAX_PIPES = 64;
|
// [pipebuf] is a FIFO buffer with multiple readers.
|
||||||
static const int MAX_RUNNABLES = 64;
|
// [pipewriter] is a client-side hook for writing into a [pipebuf].
|
||||||
static const int MAX_READERS = 8;
|
// [pipereader] is a client-side hook reading from a [pipebuf].
|
||||||
|
// [runnable] is anything that moves data between [pipebufs].
|
||||||
|
// [scheduler] is a global context which invokes [runnables] until fixpoint.
|
||||||
|
|
||||||
|
static const int MAX_PIPES = 64;
|
||||||
|
static const int MAX_RUNNABLES = 64;
|
||||||
|
static const int MAX_READERS = 8;
|
||||||
|
|
||||||
|
struct pipebuf_common
|
||||||
|
{
|
||||||
|
virtual int sizeofT()
|
||||||
|
{
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
struct pipebuf_common {
|
|
||||||
virtual int sizeofT() { return 0; }
|
|
||||||
virtual long long hash() { return 0; }
|
|
||||||
virtual void dump(size_t *total_bufs) { }
|
|
||||||
const char *name;
|
const char *name;
|
||||||
pipebuf_common(const char *_name) : name(_name) { }
|
};
|
||||||
};
|
|
||||||
|
struct runnable_common
|
||||||
|
{
|
||||||
|
runnable_common(const char *_name) :
|
||||||
|
name(_name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~runnable_common()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void run()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void shutdown()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
struct runnable_common {
|
|
||||||
const char *name;
|
|
||||||
runnable_common(const char *_name) : name(_name) { }
|
|
||||||
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
|
||||||
};
|
|
||||||
|
|
||||||
struct window_placement {
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
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,213 +106,362 @@ 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");
|
|
||||||
pipes[npipes++] = p;
|
|
||||||
}
|
|
||||||
void add_runnable(runnable_common *r) {
|
|
||||||
if ( nrunnables == MAX_RUNNABLES ) fail("MAX_RUNNABLES");
|
|
||||||
runnables[nrunnables++] = r;
|
|
||||||
}
|
|
||||||
void step() {
|
|
||||||
for ( int i=0; i<nrunnables; ++i )
|
|
||||||
runnables[i]->run();
|
|
||||||
}
|
|
||||||
void run() {
|
|
||||||
unsigned long long prev_hash = 0;
|
|
||||||
while ( 1 ) {
|
|
||||||
step();
|
|
||||||
unsigned long long h = hash();
|
|
||||||
if ( h == prev_hash ) break;
|
|
||||||
prev_hash = h;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void shutdown() {
|
|
||||||
for ( int i=0; i<nrunnables; ++i )
|
|
||||||
runnables[i]->shutdown();
|
|
||||||
}
|
|
||||||
unsigned long long hash() {
|
|
||||||
unsigned long long h = 0;
|
|
||||||
for ( int i=0; i<npipes; ++i ) h += (1+i)*pipes[i]->hash();
|
|
||||||
return h;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump() {
|
void add_pipe(pipebuf_common *p)
|
||||||
fprintf(stderr, "\n");
|
{
|
||||||
size_t total_bufs = 0;
|
if (npipes == MAX_PIPES) {
|
||||||
for ( int i=0; i<npipes; ++i ) pipes[i]->dump(&total_bufs);
|
fail("MAX_PIPES");
|
||||||
fprintf(stderr, "Total buffer memory: %ld KiB\n",
|
}
|
||||||
(unsigned long)total_bufs/1024);
|
pipes[npipes++] = p;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
struct runnable : runnable_common {
|
void add_runnable(runnable_common *r)
|
||||||
runnable(scheduler *_sch, const char *name)
|
{
|
||||||
: runnable_common(name), sch(_sch) {
|
if (nrunnables == MAX_RUNNABLES) {
|
||||||
sch->add_runnable(this);
|
fail("MAX_RUNNABLES");
|
||||||
|
}
|
||||||
|
runnables[nrunnables++] = r;
|
||||||
}
|
}
|
||||||
protected:
|
|
||||||
|
void step()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nrunnables; ++i) {
|
||||||
|
runnables[i]->run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
unsigned long long prev_hash = 0;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
step();
|
||||||
|
unsigned long long h = hash();
|
||||||
|
if (h == prev_hash) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prev_hash = h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shutdown()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nrunnables; ++i) {
|
||||||
|
runnables[i]->shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long hash()
|
||||||
|
{
|
||||||
|
unsigned long long h = 0;
|
||||||
|
for (int i = 0; i < npipes; ++i) {
|
||||||
|
h += (1 + i) * pipes[i]->hash();
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump()
|
||||||
|
{
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
std::size_t total_bufs = 0;
|
||||||
|
for (int i = 0; i < npipes; ++i) {
|
||||||
|
pipes[i]->dump(&total_bufs);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "leansdr::scheduler::dump Total buffer memory: %ld KiB\n", (unsigned long) total_bufs / 1024);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct runnable: runnable_common
|
||||||
|
{
|
||||||
|
runnable(scheduler *_sch, const char *name) :
|
||||||
|
runnable_common(name), sch(_sch)
|
||||||
|
{
|
||||||
|
sch->add_runnable(this);
|
||||||
|
}
|
||||||
|
protected:
|
||||||
scheduler *sch;
|
scheduler *sch;
|
||||||
};
|
};
|
||||||
|
|
||||||
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) {
|
|
||||||
sch->add_pipe(this);
|
|
||||||
}
|
}
|
||||||
int add_reader() {
|
|
||||||
if ( nrd == MAX_READERS ) fail("too many readers");
|
pipebuf(scheduler *sch, const char *name, unsigned long size) :
|
||||||
rds[nrd] = wr;
|
pipebuf_common(name), buf(new T[size]), nrd(0), wr(buf), end(
|
||||||
return nrd++;
|
buf + size), min_write(1), total_written(0), total_read(0)
|
||||||
|
{
|
||||||
|
sch->add_pipe(this);
|
||||||
}
|
}
|
||||||
void pack() {
|
|
||||||
T *rd = wr;
|
int add_reader()
|
||||||
for ( int i=0; i<nrd; ++i ) if ( rds[i] < rd ) rd = rds[i];
|
{
|
||||||
memmove(buf, rd, (wr-rd)*sizeof(T));
|
if (nrd == MAX_READERS) {
|
||||||
wr -= rd - buf;
|
fail("too many readers");
|
||||||
for ( int i=0; i<nrd; ++i ) rds[i] -= rd - buf;
|
}
|
||||||
|
rds[nrd] = wr;
|
||||||
|
return nrd++;
|
||||||
}
|
}
|
||||||
long long hash() {
|
|
||||||
return total_written + total_read;
|
void pack()
|
||||||
|
{
|
||||||
|
T *rd = wr;
|
||||||
|
for (int i = 0; i < nrd; ++i)
|
||||||
|
{
|
||||||
|
if (rds[i] < rd) {
|
||||||
|
rd = rds[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memmove(buf, rd, (wr - rd) * sizeof(T));
|
||||||
|
wr -= rd - buf;
|
||||||
|
for (int i = 0; i < nrd; ++i) {
|
||||||
|
rds[i] -= rd - buf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void dump(size_t *total_bufs) {
|
|
||||||
if ( total_written < 10000 )
|
long long hash()
|
||||||
fprintf(stderr, ".%-16s : %4ld/%4ld", name,
|
{
|
||||||
total_read, total_written);
|
return total_written + total_read;
|
||||||
else if ( total_written < 1000000 )
|
}
|
||||||
fprintf(stderr, ".%-16s : %3ldk/%3ldk", name,
|
|
||||||
total_read/1000, total_written/1000);
|
void dump(std::size_t *total_bufs)
|
||||||
else
|
{
|
||||||
fprintf(stderr, ".%-16s : %3ldM/%3ldM", name,
|
if (total_written < 10000) {
|
||||||
total_read/1000000, total_written/1000000);
|
fprintf(stderr, "leansdr::pipebuf::dump: .%-16s : %4ld/%4ld", name, total_read, total_written);
|
||||||
*total_bufs += (end-buf) * sizeof(T);
|
} else if (total_written < 1000000) {
|
||||||
unsigned long nw = end - wr;
|
fprintf(stderr, "leansdr::pipebuf::dump: .%-16s : %3ldk/%3ldk", name, total_read / 1000, total_written / 1000);
|
||||||
fprintf(stderr, " %6ld writable %c,", nw, (nw<min_write)?'!':' ');
|
} else {
|
||||||
T *rd = wr;
|
fprintf(stderr, "leansdr::pipebuf::dump: .%-16s : %3ldM/%3ldM", name, total_read / 1000000, total_written / 1000000);
|
||||||
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 )
|
*total_bufs += (end - buf) * sizeof(T);
|
||||||
fprintf(stderr, " %d", (int)(wr-rds[j]));
|
unsigned long nw = end - wr;
|
||||||
fprintf(stderr, " )\n");
|
fprintf(stderr, "leansdr::pipebuf: %6ld writable %c,", nw, (nw < min_write) ? '!' : ' ');
|
||||||
|
T *rd = wr;
|
||||||
|
|
||||||
|
for (int j = 0; j < nrd; ++j)
|
||||||
|
{
|
||||||
|
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) {
|
|
||||||
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) {
|
|
||||||
if ( buf.wr+n > buf.end ) {
|
|
||||||
fprintf(stderr, "Bug: overflow to %s\n", buf.name);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
buf.wr += n;
|
|
||||||
buf.total_written += n;
|
|
||||||
}
|
|
||||||
void write(const T &e) {
|
|
||||||
*wr() = e;
|
|
||||||
written(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Convenience functions for working with optional pipes
|
pipewriter(pipebuf<T> &_buf, unsigned long min_write = 1) :
|
||||||
|
buf(_buf)
|
||||||
|
{
|
||||||
|
if (min_write > buf.min_write) {
|
||||||
|
buf.min_write = min_write;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
/** Return number of items writable at this->wr, 0 if full. */
|
||||||
pipewriter<T> *opt_writer(pipebuf<T> *buf) {
|
unsigned long writable()
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
buf.wr += n;
|
||||||
|
buf.total_written += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(const T &e)
|
||||||
|
{
|
||||||
|
*wr() = e;
|
||||||
|
written(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convenience functions for working with optional pipes
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
buf.rds[id] += n;
|
|
||||||
buf.total_read += n;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// Math functions for templates
|
unsigned long readable()
|
||||||
|
{
|
||||||
|
return buf.wr - buf.rds[id];
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T> T gen_sqrt(T x);
|
T *rd()
|
||||||
inline float gen_sqrt(float x) { return sqrtf(x); }
|
{
|
||||||
inline unsigned int gen_sqrt(unsigned int x) { return sqrtl(x); }
|
return buf.rds[id];
|
||||||
inline long double gen_sqrt(long double x) { return sqrtl(x); }
|
}
|
||||||
|
|
||||||
template<typename T> T gen_abs(T x);
|
void read(unsigned long n)
|
||||||
inline float gen_abs(float x) { return fabsf(x); }
|
{
|
||||||
inline int gen_abs(int x) { return abs(x); }
|
if (buf.rds[id] + n > buf.wr)
|
||||||
inline long int gen_abs(long int x) { return labs(x); }
|
{
|
||||||
|
fprintf(stderr, "leansdr::pipereader::read: Bug: underflow from %s\n", buf.name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
buf.rds[id] += n;
|
||||||
|
buf.total_read += n;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T> T gen_hypot(T x, T y);
|
// Math functions for templates
|
||||||
inline float gen_hypot(float x, float y) { return hypotf(x,y); }
|
|
||||||
inline long double gen_hypot(long double x, long double y)
|
|
||||||
{ return hypotl(x,y); }
|
|
||||||
|
|
||||||
template<typename T> T gen_atan2(T y, T x);
|
template<typename T> T gen_sqrt(T x);
|
||||||
inline float gen_atan2(float y, float x) { return atan2f(y,x); }
|
inline float gen_sqrt(float x)
|
||||||
inline long double gen_atan2(long double y, long double x)
|
{
|
||||||
{ return atan2l(y,x); }
|
return sqrtf(x);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
inline unsigned int gen_sqrt(unsigned int x)
|
||||||
T min(const T &x, const T &y) { return (x<y) ? x : y; }
|
{
|
||||||
|
return sqrtl(x);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
inline long double gen_sqrt(long double x)
|
||||||
T max(const T &x, const T &y) { return (x<y) ? y : x; }
|
{
|
||||||
|
return sqrtl(x);
|
||||||
|
}
|
||||||
|
|
||||||
// Abreviations for integer types
|
template<typename T> T gen_abs(T x);
|
||||||
|
inline float gen_abs(float x)
|
||||||
|
{
|
||||||
|
return fabsf(x);
|
||||||
|
}
|
||||||
|
|
||||||
typedef unsigned char u8;
|
inline int gen_abs(int x)
|
||||||
typedef unsigned short u16;
|
{
|
||||||
typedef unsigned long u32;
|
return abs(x);
|
||||||
typedef signed char s8;
|
}
|
||||||
typedef signed short s16;
|
|
||||||
typedef signed long s32;
|
inline long int gen_abs(long int x)
|
||||||
|
{
|
||||||
|
return labs(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> T gen_hypot(T x, T y);
|
||||||
|
inline float gen_hypot(float x, float y)
|
||||||
|
{
|
||||||
|
return hypotf(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline long double gen_hypot(long double x, long double y)
|
||||||
|
{
|
||||||
|
return hypotl(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> T gen_atan2(T y, T x);
|
||||||
|
inline float gen_atan2(float y, float x)
|
||||||
|
{
|
||||||
|
return atan2f(y, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline long double gen_atan2(long double y, long double x)
|
||||||
|
{
|
||||||
|
return atan2l(y, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T min(const T &x, const T &y)
|
||||||
|
{
|
||||||
|
return (x < y) ? x : y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T max(const T &x, const T &y)
|
||||||
|
{
|
||||||
|
return (x < y) ? y : x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abreviations for integer types
|
||||||
|
|
||||||
|
typedef unsigned char u8;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
typedef unsigned long u32;
|
||||||
|
typedef signed char s8;
|
||||||
|
typedef signed short s16;
|
||||||
|
typedef signed long s32;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -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,80 +38,109 @@ 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;
|
{
|
||||||
*fcs_errors = 0;
|
*hdlc_errors = 0;
|
||||||
*pdatasize = -1;
|
*fcs_errors = 0;
|
||||||
u8 *pin=*ppin, *pend=pin+count;
|
*pdatasize = -1;
|
||||||
for ( ; pin<pend; ++pin ) {
|
u8 *pin = *ppin, *pend = pin + count;
|
||||||
u8 byte_in = (*pin) ^ invertmask;
|
for (; pin < pend; ++pin)
|
||||||
for ( int bits=8; bits--; byte_in<<=1 ) {
|
{
|
||||||
u8 bit_in = byte_in & 128;
|
u8 byte_in = (*pin) ^ invertmask;
|
||||||
shiftreg = (shiftreg>>1) | bit_in;
|
for (int bits = 8; bits--; byte_in <<= 1)
|
||||||
if ( ! inframe ) {
|
{
|
||||||
if ( shiftreg == 0x7e ) { // HDLC flag 01111110
|
u8 bit_in = byte_in & 128;
|
||||||
inframe = true;
|
shiftreg = (shiftreg >> 1) | bit_in;
|
||||||
nbits_out = 0;
|
if (!inframe)
|
||||||
begin_frame();
|
{
|
||||||
}
|
if (shiftreg == 0x7e)
|
||||||
} else {
|
{ // HDLC flag 01111110
|
||||||
if ( (shiftreg&0xfe) == 0x7c ) { // 0111110x HDLC stuffing
|
inframe = true;
|
||||||
// Unstuff this 0
|
nbits_out = 0;
|
||||||
} else if ( shiftreg == 0x7e ) { // 01111110 HDLC flag
|
begin_frame();
|
||||||
if ( nbits_out != 7 ) {
|
}
|
||||||
// Not at byte boundary
|
}
|
||||||
if ( debug ) fprintf(stderr, "^");
|
else
|
||||||
++*hdlc_errors;
|
{
|
||||||
} else {
|
if ((shiftreg & 0xfe) == 0x7c)
|
||||||
// Checksum
|
{ // 0111110x HDLC stuffing
|
||||||
crc16 ^= 0xffff;
|
// Unstuff this 0
|
||||||
if ( framesize<2 || framesize<minframesize ||
|
}
|
||||||
crc16!=crc16_check ) {
|
else if (shiftreg == 0x7e)
|
||||||
if ( debug ) fprintf(stderr, "!");
|
{ // 01111110 HDLC flag
|
||||||
++*hdlc_errors;
|
if (nbits_out != 7)
|
||||||
// Do not report random noise as FCS errors
|
{
|
||||||
if ( framesize >= minframesize ) ++*fcs_errors;
|
// Not at byte boundary
|
||||||
} else {
|
if (debug)
|
||||||
if ( debug ) fprintf(stderr, "_");
|
fprintf(stderr, "^");
|
||||||
// This will trigger output, but we finish the byte first.
|
++*hdlc_errors;
|
||||||
*pdatasize = framesize-2;
|
}
|
||||||
}
|
else
|
||||||
}
|
{
|
||||||
nbits_out = 0;
|
// Checksum
|
||||||
begin_frame();
|
crc16 ^= 0xffff;
|
||||||
// Keep processing up to 7 remaining bits from byte_in.
|
if (framesize < 2 || framesize < minframesize
|
||||||
// Special cases 0111111 and 1111111 cannot affect *pdatasize.
|
|| crc16 != crc16_check)
|
||||||
} else if ( shiftreg == 0xfe ) { // 11111110 HDLC invalid
|
{
|
||||||
if ( framesize ) {
|
if (debug)
|
||||||
if ( debug ) fprintf(stderr, "^");
|
fprintf(stderr, "!");
|
||||||
++*hdlc_errors;
|
++*hdlc_errors;
|
||||||
}
|
// Do not report random noise as FCS errors
|
||||||
inframe = false;
|
if (framesize >= minframesize)
|
||||||
} else { // Data bit
|
++*fcs_errors;
|
||||||
byte_out = (byte_out>>1) | bit_in; // HDLC is LSB first
|
}
|
||||||
++nbits_out;
|
else
|
||||||
if ( nbits_out == 8 ) {
|
{
|
||||||
if ( framesize < maxframesize ) {
|
if (debug)
|
||||||
framebuf[framesize++] = byte_out;
|
fprintf(stderr, "_");
|
||||||
crc16_byte(byte_out);
|
// This will trigger output, but we finish the byte first.
|
||||||
}
|
*pdatasize = framesize - 2;
|
||||||
nbits_out = 0;
|
}
|
||||||
}
|
}
|
||||||
}
|
nbits_out = 0;
|
||||||
} // inframe
|
begin_frame();
|
||||||
} // bits
|
// Keep processing up to 7 remaining bits from byte_in.
|
||||||
if ( *pdatasize != -1 ) {
|
// Special cases 0111111 and 1111111 cannot affect *pdatasize.
|
||||||
// Found a complete frame
|
}
|
||||||
*ppin = pin+1;
|
else if (shiftreg == 0xfe)
|
||||||
return framebuf;
|
{ // 11111110 HDLC invalid
|
||||||
}
|
if (framesize)
|
||||||
}
|
{
|
||||||
*ppin = pin;
|
if (debug)
|
||||||
return NULL;
|
fprintf(stderr, "^");
|
||||||
|
++*hdlc_errors;
|
||||||
|
}
|
||||||
|
inframe = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Data bit
|
||||||
|
byte_out = (byte_out >> 1) | bit_in; // HDLC is LSB first
|
||||||
|
++nbits_out;
|
||||||
|
if (nbits_out == 8)
|
||||||
|
{
|
||||||
|
if (framesize < maxframesize)
|
||||||
|
{
|
||||||
|
framebuf[framesize++] = byte_out;
|
||||||
|
crc16_byte(byte_out);
|
||||||
|
}
|
||||||
|
nbits_out = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // inframe
|
||||||
|
} // bits
|
||||||
|
if (*pdatasize != -1)
|
||||||
|
{
|
||||||
|
// Found a complete frame
|
||||||
|
*ppin = pin + 1;
|
||||||
|
return framebuf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*ppin = pin;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Config
|
// Config
|
||||||
int minframesize, maxframesize;
|
int minframesize, maxframesize;
|
||||||
u8 invertmask;
|
u8 invertmask;
|
||||||
@ -119,151 +156,170 @@ 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;
|
|
||||||
for ( int bit=8; bit--; )
|
|
||||||
crc16 = (crc16&1) ? (crc16>>1)^crc16_poly : (crc16>>1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool debug;
|
|
||||||
}; // hdlc_dec
|
|
||||||
|
|
||||||
|
|
||||||
// HDLC synchronizer with polarity detection
|
|
||||||
|
|
||||||
struct hdlc_sync : runnable {
|
|
||||||
hdlc_sync(scheduler *sch,
|
|
||||||
pipebuf<u8> &_in, // Packed bits
|
|
||||||
pipebuf<u8> &_out, // Bytes
|
|
||||||
int _minframesize, // Including CRC, excluding HDLC flags.
|
|
||||||
int _maxframesize,
|
|
||||||
// Status
|
|
||||||
pipebuf<int> *_lock_out=NULL,
|
|
||||||
pipebuf<int> *_framecount_out=NULL,
|
|
||||||
pipebuf<int> *_fcserrcount_out=NULL,
|
|
||||||
pipebuf<int> *_hdlcbytecount_out=NULL,
|
|
||||||
pipebuf<int> *_databytecount_out=NULL)
|
|
||||||
: runnable(sch, "hdlc_sync"),
|
|
||||||
minframesize(_minframesize),
|
|
||||||
maxframesize(_maxframesize),
|
|
||||||
chunk_size(maxframesize+2),
|
|
||||||
in(_in), out(_out, _maxframesize+chunk_size),
|
|
||||||
lock_out(opt_writer(_lock_out)),
|
|
||||||
framecount_out(opt_writer(_framecount_out)),
|
|
||||||
fcserrcount_out(opt_writer(_fcserrcount_out)),
|
|
||||||
hdlcbytecount_out(opt_writer(_hdlcbytecount_out)),
|
|
||||||
databytecount_out(opt_writer(_databytecount_out)),
|
|
||||||
cur_sync(0), resync_phase(0),
|
|
||||||
lock_state(false),
|
|
||||||
resync_period(32),
|
|
||||||
header16(false)
|
|
||||||
{
|
{
|
||||||
for ( int s=0; s<NSYNCS; ++s ) {
|
crc16 ^= data;
|
||||||
syncs[s].dec = new hdlc_dec(minframesize, maxframesize, s!=0);
|
for (int bit = 8; bit--;)
|
||||||
for ( int h=0; h<NERRHIST; ++h ) syncs[s].errhist[h] = 0;
|
crc16 = (crc16 & 1) ? (crc16 >> 1) ^ crc16_poly : (crc16 >> 1);
|
||||||
}
|
|
||||||
syncs[cur_sync].dec->debug = sch->debug;
|
|
||||||
errslot = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void run() {
|
public:
|
||||||
if ( ! opt_writable(lock_out) ||
|
bool debug;
|
||||||
! opt_writable(framecount_out) ||
|
};
|
||||||
! opt_writable(fcserrcount_out) ||
|
// hdlc_dec
|
||||||
! opt_writable(hdlcbytecount_out) ||
|
|
||||||
! opt_writable(databytecount_out) ) return;
|
|
||||||
|
|
||||||
bool previous_lock_state = lock_state;
|
// HDLC synchronizer with polarity detection
|
||||||
int fcserrcount=0, framecount=0;
|
|
||||||
int hdlcbytecount=0, databytecount=0;
|
|
||||||
|
|
||||||
// Note: hdlc_dec may already hold one frame ready for output.
|
struct hdlc_sync: runnable
|
||||||
while ( in.readable() >= chunk_size &&
|
{
|
||||||
out.writable() >= maxframesize+chunk_size ) {
|
hdlc_sync(scheduler *sch,
|
||||||
if ( ! resync_phase ) {
|
pipebuf<u8> &_in, // Packed bits
|
||||||
// Once every resync_phase, try all decoders
|
pipebuf<u8> &_out, // Bytes
|
||||||
for ( int s=0; s<NSYNCS; ++s ) {
|
int _minframesize, // Including CRC, excluding HDLC flags.
|
||||||
if ( s != cur_sync ) syncs[s].dec->reset();
|
int _maxframesize,
|
||||||
syncs[s].errhist[errslot] = 0;
|
// Status
|
||||||
for ( u8 *pin=in.rd(), *pend=pin+chunk_size; pin<pend; ) {
|
pipebuf<int> *_lock_out = NULL,
|
||||||
int datasize, hdlc_errors, fcs_errors;
|
pipebuf<int> *_framecount_out = NULL,
|
||||||
u8 *f = syncs[s].dec->decode(&pin, pend-pin, &datasize,
|
pipebuf<int> *_fcserrcount_out = NULL,
|
||||||
&hdlc_errors, &fcs_errors);
|
pipebuf<int> *_hdlcbytecount_out = NULL,
|
||||||
syncs[s].errhist[errslot] += hdlc_errors;
|
pipebuf<int> *_databytecount_out = NULL) :
|
||||||
if ( s == cur_sync ) {
|
runnable(sch, "hdlc_sync"), minframesize(_minframesize), maxframesize(
|
||||||
if ( f ) {
|
_maxframesize), chunk_size(maxframesize + 2), in(_in), out(
|
||||||
lock_state = true;
|
_out, _maxframesize + chunk_size), lock_out(
|
||||||
output_frame(f, datasize);
|
opt_writer(_lock_out)), framecount_out(
|
||||||
databytecount += datasize;
|
opt_writer(_framecount_out)), fcserrcount_out(
|
||||||
++framecount;
|
opt_writer(_fcserrcount_out)), hdlcbytecount_out(
|
||||||
}
|
opt_writer(_hdlcbytecount_out)), databytecount_out(
|
||||||
fcserrcount += fcs_errors;
|
opt_writer(_databytecount_out)), cur_sync(0), resync_phase(
|
||||||
framecount += fcs_errors;
|
0), lock_state(false), resync_period(32), header16(false)
|
||||||
}
|
{
|
||||||
}
|
for (int s = 0; s < NSYNCS; ++s)
|
||||||
}
|
{
|
||||||
errslot = (errslot+1) % NERRHIST;
|
syncs[s].dec = new hdlc_dec(minframesize, maxframesize, s != 0);
|
||||||
// Switch to another sync option ?
|
for (int h = 0; h < NERRHIST; ++h)
|
||||||
// Compare total error counts over about NERRHIST frames.
|
syncs[s].errhist[h] = 0;
|
||||||
int total_errors[NSYNCS];
|
}
|
||||||
for ( int s=0; s<NSYNCS; ++s ) {
|
syncs[cur_sync].dec->debug = sch->debug;
|
||||||
total_errors[s] = 0;
|
errslot = 0;
|
||||||
for ( int h=0; h<NERRHIST; ++h )
|
|
||||||
total_errors[s] += syncs[s].errhist[h];
|
|
||||||
}
|
|
||||||
int best = cur_sync;
|
|
||||||
for ( int s=0; s<NSYNCS; ++s )
|
|
||||||
if ( total_errors[s] < total_errors[best] ) best = s;
|
|
||||||
if ( best != cur_sync ) {
|
|
||||||
lock_state = false;
|
|
||||||
if ( sch->debug ) fprintf(stderr, "[%d:%d->%d:%d]",
|
|
||||||
cur_sync, total_errors[cur_sync],
|
|
||||||
best, total_errors[best]);
|
|
||||||
// No verbose messages on candidate syncs
|
|
||||||
syncs[cur_sync].dec->debug = false;
|
|
||||||
cur_sync = best;
|
|
||||||
syncs[cur_sync].dec->debug = sch->debug;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Use only the currently selected decoder
|
|
||||||
for ( u8 *pin=in.rd(), *pend=pin+chunk_size; pin<pend; ) {
|
|
||||||
int datasize, hdlc_errors, fcs_errors;
|
|
||||||
u8 *f = syncs[cur_sync].dec->decode(&pin, pend-pin, &datasize,
|
|
||||||
&hdlc_errors, &fcs_errors);
|
|
||||||
if ( f ) {
|
|
||||||
lock_state = true;
|
|
||||||
output_frame(f, datasize);
|
|
||||||
databytecount += datasize;
|
|
||||||
++framecount;
|
|
||||||
}
|
|
||||||
fcserrcount += fcs_errors;
|
|
||||||
framecount += fcs_errors;
|
|
||||||
}
|
|
||||||
} // resync_phase
|
|
||||||
in.read(chunk_size);
|
|
||||||
hdlcbytecount += chunk_size;
|
|
||||||
if ( ++resync_phase >= resync_period ) resync_phase = 0;
|
|
||||||
} // Work to do
|
|
||||||
|
|
||||||
if ( lock_state != previous_lock_state )
|
|
||||||
opt_write(lock_out, lock_state?1:0);
|
|
||||||
opt_write(framecount_out, framecount);
|
|
||||||
opt_write(fcserrcount_out, fcserrcount);
|
|
||||||
opt_write(hdlcbytecount_out, hdlcbytecount);
|
|
||||||
opt_write(databytecount_out, databytecount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
void run()
|
||||||
void output_frame(u8 *f, int size) {
|
{
|
||||||
if ( header16 ) {
|
if (!opt_writable(lock_out) || !opt_writable(framecount_out)
|
||||||
// Removed 16-bit CRC, add 16-bit prefix -> Still <= maxframesize.
|
|| !opt_writable(fcserrcount_out)
|
||||||
out.write(size >> 8);
|
|| !opt_writable(hdlcbytecount_out)
|
||||||
out.write(size & 255);
|
|| !opt_writable(databytecount_out))
|
||||||
}
|
return;
|
||||||
memcpy(out.wr(), f, size);
|
|
||||||
out.written(size);
|
bool previous_lock_state = lock_state;
|
||||||
opt_write(framecount_out, 1);
|
int fcserrcount = 0, framecount = 0;
|
||||||
|
int hdlcbytecount = 0, databytecount = 0;
|
||||||
|
|
||||||
|
// Note: hdlc_dec may already hold one frame ready for output.
|
||||||
|
while ((long) in.readable() >= chunk_size
|
||||||
|
&& (long) out.writable() >= maxframesize + chunk_size)
|
||||||
|
{
|
||||||
|
if (!resync_phase)
|
||||||
|
{
|
||||||
|
// Once every resync_phase, try all decoders
|
||||||
|
for (int s = 0; s < NSYNCS; ++s)
|
||||||
|
{
|
||||||
|
if (s != cur_sync)
|
||||||
|
syncs[s].dec->reset();
|
||||||
|
syncs[s].errhist[errslot] = 0;
|
||||||
|
for (u8 *pin = in.rd(), *pend = pin + chunk_size;
|
||||||
|
pin < pend;)
|
||||||
|
{
|
||||||
|
int datasize, hdlc_errors, fcs_errors;
|
||||||
|
u8 *f = syncs[s].dec->decode(&pin, pend - pin,
|
||||||
|
&datasize, &hdlc_errors, &fcs_errors);
|
||||||
|
syncs[s].errhist[errslot] += hdlc_errors;
|
||||||
|
if (s == cur_sync)
|
||||||
|
{
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
lock_state = true;
|
||||||
|
output_frame(f, datasize);
|
||||||
|
databytecount += datasize;
|
||||||
|
++framecount;
|
||||||
|
}
|
||||||
|
fcserrcount += fcs_errors;
|
||||||
|
framecount += fcs_errors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errslot = (errslot + 1) % NERRHIST;
|
||||||
|
// Switch to another sync option ?
|
||||||
|
// Compare total error counts over about NERRHIST frames.
|
||||||
|
int total_errors[NSYNCS];
|
||||||
|
for (int s = 0; s < NSYNCS; ++s)
|
||||||
|
{
|
||||||
|
total_errors[s] = 0;
|
||||||
|
for (int h = 0; h < NERRHIST; ++h)
|
||||||
|
total_errors[s] += syncs[s].errhist[h];
|
||||||
|
}
|
||||||
|
int best = cur_sync;
|
||||||
|
for (int s = 0; s < NSYNCS; ++s)
|
||||||
|
if (total_errors[s] < total_errors[best])
|
||||||
|
best = s;
|
||||||
|
if (best != cur_sync)
|
||||||
|
{
|
||||||
|
lock_state = false;
|
||||||
|
if (sch->debug)
|
||||||
|
fprintf(stderr, "[%d:%d->%d:%d]", cur_sync,
|
||||||
|
total_errors[cur_sync], best,
|
||||||
|
total_errors[best]);
|
||||||
|
// No verbose messages on candidate syncs
|
||||||
|
syncs[cur_sync].dec->debug = false;
|
||||||
|
cur_sync = best;
|
||||||
|
syncs[cur_sync].dec->debug = sch->debug;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use only the currently selected decoder
|
||||||
|
for (u8 *pin = in.rd(), *pend = pin + chunk_size; pin < pend;)
|
||||||
|
{
|
||||||
|
int datasize, hdlc_errors, fcs_errors;
|
||||||
|
u8 *f = syncs[cur_sync].dec->decode(&pin, pend - pin,
|
||||||
|
&datasize, &hdlc_errors, &fcs_errors);
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
lock_state = true;
|
||||||
|
output_frame(f, datasize);
|
||||||
|
databytecount += datasize;
|
||||||
|
++framecount;
|
||||||
|
}
|
||||||
|
fcserrcount += fcs_errors;
|
||||||
|
framecount += fcs_errors;
|
||||||
|
}
|
||||||
|
} // resync_phase
|
||||||
|
in.read(chunk_size);
|
||||||
|
hdlcbytecount += chunk_size;
|
||||||
|
if (++resync_phase >= resync_period)
|
||||||
|
resync_phase = 0;
|
||||||
|
} // Work to do
|
||||||
|
|
||||||
|
if (lock_state != previous_lock_state)
|
||||||
|
opt_write(lock_out, lock_state ? 1 : 0);
|
||||||
|
opt_write(framecount_out, framecount);
|
||||||
|
opt_write(fcserrcount_out, fcserrcount);
|
||||||
|
opt_write(hdlcbytecount_out, hdlcbytecount);
|
||||||
|
opt_write(databytecount_out, databytecount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void output_frame(u8 *f, int size)
|
||||||
|
{
|
||||||
|
if (header16)
|
||||||
|
{
|
||||||
|
// Removed 16-bit CRC, add 16-bit prefix -> Still <= maxframesize.
|
||||||
|
out.write(size >> 8);
|
||||||
|
out.write(size & 255);
|
||||||
|
}
|
||||||
|
memcpy(out.wr(), f, size);
|
||||||
|
out.written(size);
|
||||||
|
opt_write(framecount_out, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int minframesize, maxframesize;
|
int minframesize, maxframesize;
|
||||||
@ -275,19 +331,21 @@ 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;
|
{
|
||||||
int errhist[NERRHIST];
|
hdlc_dec *dec;
|
||||||
|
int errhist[NERRHIST];
|
||||||
} syncs[NSYNCS];
|
} syncs[NSYNCS];
|
||||||
int errslot;
|
int errslot;
|
||||||
int cur_sync;
|
int cur_sync;
|
||||||
int resync_phase;
|
int resync_phase;
|
||||||
bool lock_state;
|
bool lock_state;
|
||||||
public:
|
public:
|
||||||
int resync_period;
|
int resync_period;
|
||||||
bool header16; // Output length prefix
|
bool header16; // Output length prefix
|
||||||
}; // hdlc_sync
|
};
|
||||||
|
// hdlc_sync
|
||||||
|
|
||||||
} // namespace
|
}// namespace
|
||||||
|
|
||||||
#endif // LEANSDR_HDLC_H
|
#endif // LEANSDR_HDLC_H
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user