DATV: various fixes and enhancements to ldpc_tool handling. Implements #804

This commit is contained in:
f4exb 2021-03-13 00:13:00 +01:00
parent 233f512f9c
commit d73f093dab
11 changed files with 856 additions and 693 deletions

View File

@ -54,7 +54,7 @@ DATVDemodSink::DATVDemodSink() :
{ {
//*************** DATV PARAMETERS *************** //*************** DATV PARAMETERS ***************
m_blnInitialized=false; m_blnInitialized=false;
CleanUpDATVFramework(false); ResetDATVFrameworkPointers();
m_objVideoStream = new DATVideostream(); m_objVideoStream = new DATVideostream();
m_objRFFilter = new fftfilt(-256000.0 / 1024000.0, 256000.0 / 1024000.0, m_rfFilterFftLength); m_objRFFilter = new fftfilt(-256000.0 / 1024000.0, 256000.0 / 1024000.0, m_rfFilterFftLength);
} }
@ -81,7 +81,7 @@ DATVDemodSink::~DATVDemodSink()
m_objRenderThread->wait(2000); m_objRenderThread->wait(2000);
} }
CleanUpDATVFramework(true); CleanUpDATVFramework();
delete m_objRFFilter; delete m_objRFFilter;
} }
@ -154,7 +154,6 @@ bool DATVDemodSink::videoDecodeOK()
bool DATVDemodSink::PlayVideo(bool blnStartStop) bool DATVDemodSink::PlayVideo(bool blnStartStop)
{ {
if (m_objVideoStream == nullptr) { if (m_objVideoStream == nullptr) {
return false; return false;
} }
@ -195,10 +194,8 @@ bool DATVDemodSink::PlayVideo(bool blnStartStop)
return true; return true;
} }
void DATVDemodSink::CleanUpDATVFramework(bool blnRelease) void DATVDemodSink::CleanUpDATVFramework()
{ {
if (blnRelease == true)
{
if (m_objScheduler != nullptr) if (m_objScheduler != nullptr)
{ {
m_objScheduler->shutdown(); m_objScheduler->shutdown();
@ -229,6 +226,9 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease)
if (r_cnr != nullptr) { if (r_cnr != nullptr) {
delete r_cnr; delete r_cnr;
} }
if (r_cnrGauge != nullptr) {
delete r_cnrGauge;
}
//FILTERING //FILTERING
if (r_resample != nullptr) { if (r_resample != nullptr) {
@ -260,6 +260,9 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease)
if (p_mer != nullptr) { if (p_mer != nullptr) {
delete p_mer; delete p_mer;
} }
if (r_merGauge != nullptr) {
delete r_merGauge;
}
if (p_sampled != nullptr) { if (p_sampled != nullptr) {
delete p_sampled; delete p_sampled;
} }
@ -351,10 +354,7 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease)
delete r_derand; delete r_derand;
} }
//OUTPUT : To remove //OUTPUT
if (r_stdout != nullptr) {
delete r_stdout;
}
if (r_videoplayer != nullptr) { if (r_videoplayer != nullptr) {
delete r_videoplayer; delete r_videoplayer;
} }
@ -363,12 +363,6 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease)
if (r_scope_symbols != nullptr) { if (r_scope_symbols != nullptr) {
delete r_scope_symbols; delete r_scope_symbols;
} }
if (r_merGauge != nullptr) {
delete r_merGauge;
}
if (r_cnrGauge != nullptr) {
delete r_cnrGauge;
}
// INPUT // INPUT
if (p_rawiq != nullptr) { if (p_rawiq != nullptr) {
@ -381,76 +375,67 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease)
//DVB-S2 //DVB-S2
if(p_slots_dvbs2 != nullptr) if (p_slots_dvbs2 != nullptr) {
{
delete (leansdr::pipebuf< leansdr::plslot<leansdr::llr_ss> >*) p_slots_dvbs2; delete (leansdr::pipebuf< leansdr::plslot<leansdr::llr_ss> >*) p_slots_dvbs2;
} }
if(p_cstln != nullptr) if (p_cstln != nullptr) {
{
delete p_cstln; delete p_cstln;
} }
if(p_cstln_pls != nullptr) if (p_cstln_pls != nullptr) {
{
delete p_cstln_pls; delete p_cstln_pls;
} }
if(p_framelock != nullptr) if (p_framelock != nullptr) {
{
delete p_framelock; delete p_framelock;
} }
if(m_objDemodulatorDVBS2 != nullptr) if (m_objDemodulatorDVBS2 != nullptr) {
{
delete (leansdr::s2_frame_receiver<leansdr::f32, leansdr::llr_ss>*) m_objDemodulatorDVBS2; delete (leansdr::s2_frame_receiver<leansdr::f32, leansdr::llr_ss>*) m_objDemodulatorDVBS2;
} }
if(p_fecframes != nullptr) if (p_fecframes != nullptr) {
{
delete (leansdr::pipebuf< leansdr::fecframe<leansdr::hard_sb> >*) p_fecframes; delete (leansdr::pipebuf< leansdr::fecframe<leansdr::hard_sb> >*) p_fecframes;
} }
if(p_bbframes != nullptr) if (p_bbframes != nullptr) {
{
delete (leansdr::pipebuf<leansdr::bbframe>*) p_bbframes; delete (leansdr::pipebuf<leansdr::bbframe>*) p_bbframes;
} }
if(p_s2_deinterleaver != nullptr) if (p_s2_deinterleaver != nullptr) {
{
delete (leansdr::s2_deinterleaver<leansdr::llr_ss,leansdr::hard_sb>*) p_s2_deinterleaver; delete (leansdr::s2_deinterleaver<leansdr::llr_ss,leansdr::hard_sb>*) p_s2_deinterleaver;
} }
if(r_fecdec != nullptr) if (r_fecdec != nullptr) {
{
delete (leansdr::s2_fecdec<bool, leansdr::hard_sb>*) r_fecdec; delete (leansdr::s2_fecdec<bool, leansdr::hard_sb>*) r_fecdec;
} }
#ifdef LINUX #ifdef LINUX
if(r_fecdecsoft != nullptr) if (r_fecdecsoft != nullptr) {
{
delete (leansdr::s2_fecdec_soft<leansdr::llr_t,leansdr::llr_sb>*) r_fecdecsoft; delete (leansdr::s2_fecdec_soft<leansdr::llr_t,leansdr::llr_sb>*) r_fecdecsoft;
} }
if(r_fecdechelper != nullptr)
{ if (r_fecdechelper != nullptr) {
delete (leansdr::s2_fecdec_helper<leansdr::llr_t,leansdr::llr_sb>*) r_fecdechelper; delete (leansdr::s2_fecdec_helper<leansdr::llr_t,leansdr::llr_sb>*) r_fecdechelper;
} }
#endif #endif
if(p_deframer != nullptr) if (p_deframer != nullptr) {
{
delete (leansdr::s2_deframer*) p_deframer; delete (leansdr::s2_deframer*) p_deframer;
} }
if(r_scope_symbols_dvbs2 != nullptr) if (r_scope_symbols_dvbs2 != nullptr) {
{
delete r_scope_symbols_dvbs2; delete r_scope_symbols_dvbs2;
} }
} // blnRelease
m_objScheduler=nullptr; ResetDATVFrameworkPointers();
}
void DATVDemodSink::ResetDATVFrameworkPointers()
{
// INPUT // INPUT
m_objScheduler = nullptr;
p_rawiq = nullptr; p_rawiq = nullptr;
p_rawiq_writer = nullptr; p_rawiq_writer = nullptr;
@ -468,6 +453,7 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease)
// CNR ESTIMATION // CNR ESTIMATION
p_cnr = nullptr; p_cnr = nullptr;
r_cnr = nullptr; r_cnr = nullptr;
r_cnrGauge = nullptr;
//FILTERING //FILTERING
r_resample = nullptr; r_resample = nullptr;
@ -484,6 +470,7 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease)
p_freq = nullptr; p_freq = nullptr;
p_ss = nullptr; p_ss = nullptr;
p_mer = nullptr; p_mer = nullptr;
r_merGauge = nullptr;
p_sampled = nullptr; p_sampled = nullptr;
//DECIMATION //DECIMATION
@ -509,7 +496,6 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease)
p_locktime = nullptr; p_locktime = nullptr;
r_sync_mpeg = nullptr; r_sync_mpeg = nullptr;
// DEINTERLEAVING // DEINTERLEAVING
p_rspackets = nullptr; p_rspackets = nullptr;
r_deinter = nullptr; r_deinter = nullptr;
@ -519,26 +505,19 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease)
p_rtspackets = nullptr; p_rtspackets = nullptr;
r_rsdec = nullptr; r_rsdec = nullptr;
//BER ESTIMATION //BER ESTIMATION
p_vber = nullptr; p_vber = nullptr;
r_vber = nullptr; r_vber = nullptr;
// DERANDOMIZATION // DERANDOMIZATION
p_tspackets = nullptr; p_tspackets = nullptr;
r_derand = nullptr; r_derand = nullptr;
//OUTPUT : To remove void * //OUTPUT : To remove void *
r_stdout = nullptr;
r_videoplayer = nullptr; r_videoplayer = nullptr;
//CONSTELLATION //CONSTELLATION
r_scope_symbols = nullptr; r_scope_symbols = nullptr;
r_merGauge = nullptr;
r_cnrGauge = nullptr;
//DVB-S2 //DVB-S2
p_slots_dvbs2 = nullptr; p_slots_dvbs2 = nullptr;
@ -550,8 +529,10 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease)
p_bbframes = nullptr; p_bbframes = nullptr;
p_s2_deinterleaver = nullptr; p_s2_deinterleaver = nullptr;
r_fecdec = nullptr; r_fecdec = nullptr;
#ifdef LINUX
r_fecdecsoft = nullptr; r_fecdecsoft = nullptr;
r_fecdechelper = nullptr; r_fecdechelper = nullptr;
#endif
p_deframer = nullptr; p_deframer = nullptr;
r_scope_symbols_dvbs2 = nullptr; r_scope_symbols_dvbs2 = nullptr;
} }
@ -560,7 +541,7 @@ void DATVDemodSink::InitDATVFramework()
{ {
m_blnDVBInitialized = false; m_blnDVBInitialized = false;
m_lngReadIQ = 0; m_lngReadIQ = 0;
CleanUpDATVFramework(false); CleanUpDATVFramework();
qDebug() << "DATVDemodSink::InitDATVFramework:" qDebug() << "DATVDemodSink::InitDATVFramework:"
<< " Standard: " << m_settings.m_standard << " Standard: " << m_settings.m_standard
@ -675,7 +656,6 @@ void DATVDemodSink::InitDATVFramework()
p_preprocessed = p_autonotched; p_preprocessed = p_autonotched;
} }
// FREQUENCY CORRECTION // FREQUENCY CORRECTION
//******** -> if ( m_objCfg.Fderot>0 ) //******** -> if ( m_objCfg.Fderot>0 )
@ -696,7 +676,6 @@ void DATVDemodSink::InitDATVFramework()
//******** -> if ( m_objCfg.resample ) //******** -> if ( m_objCfg.resample )
// DECIMATION // DECIMATION
// (Unless already done in resampler) // (Unless already done in resampler)
@ -704,7 +683,6 @@ void DATVDemodSink::InitDATVFramework()
//Resampling FS //Resampling FS
// Generic constellation receiver // Generic constellation receiver
p_symbols = new leansdr::pipebuf<leansdr::eucl_ss>(m_objScheduler, "PSK soft-symbols", BUF_SYMBOLS); p_symbols = new leansdr::pipebuf<leansdr::eucl_ss>(m_objScheduler, "PSK soft-symbols", BUF_SYMBOLS);
@ -898,7 +876,7 @@ void DATVDemodSink::InitDATVS2Framework()
m_blnDVBInitialized = false; m_blnDVBInitialized = false;
m_lngReadIQ = 0; m_lngReadIQ = 0;
CleanUpDATVFramework(true); CleanUpDATVFramework();
qDebug() << "DATVDemodSink::InitDATVS2Framework:" qDebug() << "DATVDemodSink::InitDATVS2Framework:"
<< " Standard: " << m_settings.m_standard << " Standard: " << m_settings.m_standard
@ -1026,7 +1004,6 @@ void DATVDemodSink::InitDATVS2Framework()
//******** -> if ( m_objCfg.resample ) //******** -> if ( m_objCfg.resample )
// DECIMATION // DECIMATION
// (Unless already done in resampler) // (Unless already done in resampler)
@ -1034,7 +1011,6 @@ void DATVDemodSink::InitDATVS2Framework()
//Resampling FS //Resampling FS
// Generic constellation receiver // Generic constellation receiver
p_freq = new leansdr::pipebuf<leansdr::f32> (m_objScheduler, "freq", BUF_SLOW); p_freq = new leansdr::pipebuf<leansdr::f32> (m_objScheduler, "freq", BUF_SLOW);
@ -1086,14 +1062,12 @@ void DATVDemodSink::InitDATVS2Framework()
p_cstln, p_cstln,
/* p_cstln_pls */ nullptr, /* p_cstln_pls */ nullptr,
/*p_iqsymbols*/ nullptr, /*p_iqsymbols*/ nullptr,
/* p_framelock */nullptr); /* p_framelock */nullptr
);
objDemodulatorDVBS2 = (leansdr::s2_frame_receiver<leansdr::f32, leansdr::llr_ss> *) m_objDemodulatorDVBS2; objDemodulatorDVBS2 = (leansdr::s2_frame_receiver<leansdr::f32, leansdr::llr_ss> *) m_objDemodulatorDVBS2;
objDemodulatorDVBS2->omega0 = m_objCfg.Fs/m_objCfg.Fm; objDemodulatorDVBS2->omega0 = m_objCfg.Fs/m_objCfg.Fm;
//objDemodulatorDVBS2->mu=1; //objDemodulatorDVBS2->mu=1;
m_objCfg.Ftune=0.0f; m_objCfg.Ftune=0.0f;
objDemodulatorDVBS2->Ftune = m_objCfg.Ftune / m_objCfg.Fm; objDemodulatorDVBS2->Ftune = m_objCfg.Ftune / m_objCfg.Fm;
@ -1102,12 +1076,8 @@ void DATVDemodSink::InitDATVS2Framework()
demod.strongpls = cfg.strongpls; demod.strongpls = cfg.strongpls;
*/ */
//objDemodulatorDVBS2->Fm = m_objCfg.Fm; deprecated
objDemodulatorDVBS2->meas_decimation = decimation(m_objCfg.Fs, m_objCfg.Finfo); objDemodulatorDVBS2->meas_decimation = decimation(m_objCfg.Fs, m_objCfg.Finfo);
objDemodulatorDVBS2->strongpls = false; objDemodulatorDVBS2->strongpls = false;
objDemodulatorDVBS2->cstln = make_dvbs2_constellation(m_objCfg.constellation, m_objCfg.fec); objDemodulatorDVBS2->cstln = make_dvbs2_constellation(m_objCfg.constellation, m_objCfg.fec);
m_cstlnSetByModcod = false; m_cstlnSetByModcod = false;
@ -1116,7 +1086,6 @@ void DATVDemodSink::InitDATVS2Framework()
if (m_objRegisteredTVScreen) if (m_objRegisteredTVScreen)
{ {
qDebug("DATVDemodSink::InitDATVS2Framework: Register DVBS 2 TVSCREEN"); qDebug("DATVDemodSink::InitDATVS2Framework: Register DVBS 2 TVSCREEN");
m_objRegisteredTVScreen->resizeTVScreen(256,256); m_objRegisteredTVScreen->resizeTVScreen(256,256);
r_scope_symbols_dvbs2 = new leansdr::datvdvbs2constellation<leansdr::f32>(m_objScheduler, *p_cstln /* *p_sampled */ /* *p_cstln */, -128,128, nullptr, m_objRegisteredTVScreen); r_scope_symbols_dvbs2 = new leansdr::datvdvbs2constellation<leansdr::f32>(m_objScheduler, *p_cstln /* *p_sampled */ /* *p_cstln */, -128,128, nullptr, m_objRegisteredTVScreen);
r_scope_symbols_dvbs2->decimation = 1; r_scope_symbols_dvbs2->decimation = 1;
@ -1249,13 +1218,11 @@ void DATVDemodSink::InitDATVS2Framework()
p_lock = new leansdr::pipebuf<int> (m_objScheduler, "lock", BUF_SLOW); p_lock = new leansdr::pipebuf<int> (m_objScheduler, "lock", BUF_SLOW);
p_locktime = new leansdr::pipebuf<leansdr::u32> (m_objScheduler, "locktime", BUF_S2PACKETS); p_locktime = new leansdr::pipebuf<leansdr::u32> (m_objScheduler, "locktime", BUF_S2PACKETS);
p_tspackets = new leansdr::pipebuf<leansdr::tspacket>(m_objScheduler, "TS packets", BUF_S2PACKETS); p_tspackets = new leansdr::pipebuf<leansdr::tspacket>(m_objScheduler, "TS packets", BUF_S2PACKETS);
p_deframer = new leansdr::s2_deframer(m_objScheduler,*(leansdr::pipebuf<leansdr::bbframe> *) p_bbframes, *p_tspackets, p_lock, p_locktime); p_deframer = new leansdr::s2_deframer(m_objScheduler,*(leansdr::pipebuf<leansdr::bbframe> *) p_bbframes, *p_tspackets, p_lock, p_locktime);
/* /*
if ( cfg.fd_gse >= 0 ) deframer.fd_gse = cfg.fd_gse; if ( cfg.fd_gse >= 0 ) deframer.fd_gse = cfg.fd_gse;
*/ */
//**********************************************
// OUTPUT // OUTPUT
r_videoplayer = new leansdr::datvvideoplayer<leansdr::tspacket>(m_objScheduler, *p_tspackets, m_objVideoStream, &m_udpStream); r_videoplayer = new leansdr::datvvideoplayer<leansdr::tspacket>(m_objScheduler, *p_tspackets, m_objVideoStream, &m_udpStream);
@ -1268,7 +1235,6 @@ void DATVDemodSink::feed(const SampleVector::const_iterator& begin, const Sample
float fltI; float fltI;
float fltQ; float fltQ;
leansdr::cf32 objIQ; leansdr::cf32 objIQ;
//Complex objC;
fftfilt::cmplx *objRF; fftfilt::cmplx *objRF;
int intRFOut; int intRFOut;
double magSq; double magSq;
@ -1276,7 +1242,6 @@ void DATVDemodSink::feed(const SampleVector::const_iterator& begin, const Sample
int lngWritable=0; int lngWritable=0;
//********** Bis repetita : Let's rock and roll buddy ! ********** //********** Bis repetita : Let's rock and roll buddy ! **********
#ifdef EXTENDED_DIRECT_SAMPLE #ifdef EXTENDED_DIRECT_SAMPLE
qint16 * ptrBuffer; qint16 * ptrBuffer;
@ -1306,10 +1271,7 @@ void DATVDemodSink::feed(const SampleVector::const_iterator& begin, const Sample
fltQ = it->imag(); fltQ = it->imag();
#endif #endif
//********** demodulation ********** //********** demodulation **********
if (m_blnNeedConfigUpdate) if (m_blnNeedConfigUpdate)
{ {
qDebug("DATVDemodSink::feed: Settings applied. Standard : %d...", m_settings.m_standard); qDebug("DATVDemodSink::feed: Settings applied. Standard : %d...", m_settings.m_standard);
@ -1327,13 +1289,9 @@ void DATVDemodSink::feed(const SampleVector::const_iterator& begin, const Sample
} }
} }
//********** iq stream **************** //********** iq stream ****************
Complex objC(fltI,fltQ); Complex objC(fltI,fltQ);
objC *= m_objNCO.nextIQ(); objC *= m_objNCO.nextIQ();
intRFOut = m_objRFFilter->runFilt(objC, &objRF); // filter RF before demod intRFOut = m_objRFFilter->runFilt(objC, &objRF); // filter RF before demod
for (int intI = 0 ; intI < intRFOut; intI++) for (int intI = 0 ; intI < intRFOut; intI++)

View File

@ -142,7 +142,8 @@ private:
inline int decimation(float Fin, float Fout) { int d = Fin / Fout; return std::max(d, 1); } inline int decimation(float Fin, float Fout) { int d = Fin / Fout; return std::max(d, 1); }
void CleanUpDATVFramework(bool blnRelease); void CleanUpDATVFramework();
void ResetDATVFrameworkPointers();
void InitDATVFramework(); void InitDATVFramework();
void InitDATVS2Framework(); void InitDATVS2Framework();
@ -274,7 +275,6 @@ private:
//OUTPUT //OUTPUT
leansdr::file_writer<leansdr::tspacket> *r_stdout;
leansdr::datvvideoplayer<leansdr::tspacket> *r_videoplayer; leansdr::datvvideoplayer<leansdr::tspacket> *r_videoplayer;
//CONSTELLATION //CONSTELLATION

View File

@ -255,7 +255,7 @@ bool DATVideoRender::PreprocessStream()
MetaData.Program = ""; MetaData.Program = "";
MetaData.Stream = ""; MetaData.Stream = "";
if (m_formatCtx->programs) if (m_formatCtx->programs && m_formatCtx->programs[m_videoStreamIndex])
{ {
buffer = nullptr; buffer = nullptr;
av_dict_get_string(m_formatCtx->programs[m_videoStreamIndex]->metadata, &buffer, ':', '\n'); av_dict_get_string(m_formatCtx->programs[m_videoStreamIndex]->metadata, &buffer, ':', '\n');

View File

@ -181,8 +181,8 @@ int main(int argc, char **argv)
if (num_decodes == 20) if (num_decodes == 20)
{ {
fprintf(stderr, "ldpc_tool: trials: %d%% max: %d%% at converging to a code word\n", fprintf(stderr, "ldpc_tool: trials: %d%% max: %d%% at converging to a code word (max trials: %d)\n",
(trials_count*100)/(num_decodes*max_trials), (max_count*100)/num_decodes); (trials_count*100)/(num_decodes*max_trials), (max_count*100)/num_decodes, max_trials);
trials_count = 0; trials_count = 0;
max_count = 0; max_count = 0;
num_decodes = 0; num_decodes = 0;

View File

@ -111,13 +111,16 @@ static const int DVBS_G2 = 0133;
template <typename Tbyte, Tbyte BYTE_ERASED> template <typename Tbyte, Tbyte BYTE_ERASED>
struct deconvol_sync : runnable struct deconvol_sync : runnable
{ {
deconvol_sync(scheduler *sch, deconvol_sync(
scheduler *sch,
pipebuf<eucl_ss> &_in, pipebuf<eucl_ss> &_in,
pipebuf<Tbyte> &_out, pipebuf<Tbyte> &_out,
uint32_t gX, uint32_t gX,
uint32_t gY, uint32_t gY,
uint32_t pX, uint32_t pX,
uint32_t pY) : runnable(sch, "deconvol_sync"), uint32_t pY
) :
runnable(sch, "deconvol_sync"),
fastlock(false), fastlock(false),
in(_in), in(_in),
out(_out, SIZE_RSPACKET), out(_out, SIZE_RSPACKET),
@ -151,6 +154,14 @@ struct deconvol_sync : runnable
locked = &syncs[0]; locked = &syncs[0];
} }
~deconvol_sync()
{
delete[] deconv2;
delete[] deconv;
delete[] punct;
delete[] conv;
}
typedef uint64_t signal_t; typedef uint64_t signal_t;
typedef uint64_t iq_t; typedef uint64_t iq_t;
@ -582,7 +593,8 @@ struct deconvol_sync : runnable
typedef deconvol_sync<u8, 0> deconvol_sync_simple; typedef deconvol_sync<u8, 0> deconvol_sync_simple;
deconvol_sync_simple *make_deconvol_sync_simple(scheduler *sch, deconvol_sync_simple *make_deconvol_sync_simple(
scheduler *sch,
pipebuf<eucl_ss> &_in, pipebuf<eucl_ss> &_in,
pipebuf<u8> &_out, pipebuf<u8> &_out,
enum code_rate rate); enum code_rate rate);
@ -665,11 +677,14 @@ struct dvb_convol : runnable
typedef u8 uncoded_byte; typedef u8 uncoded_byte;
typedef u8 hardsymbol; typedef u8 hardsymbol;
dvb_convol(scheduler *sch, dvb_convol(
scheduler *sch,
pipebuf<uncoded_byte> &_in, pipebuf<uncoded_byte> &_in,
pipebuf<hardsymbol> &_out, pipebuf<hardsymbol> &_out,
code_rate fec, code_rate fec,
int bits_per_symbol) : runnable(sch, "dvb_convol"), int bits_per_symbol
) :
runnable(sch, "dvb_convol"),
in(_in), in(_in),
out(_out, 64) // BPSK 7/8: 7 bytes in, 64 symbols out out(_out, 64) // BPSK 7/8: 7 bytes in, 64 symbols out
{ {
@ -719,9 +734,12 @@ struct dvb_deconvol_sync : runnable
int resync_period; int resync_period;
static const int chunk_size = 64; // At least 2*sizeof(Thist)/8 static const int chunk_size = 64; // At least 2*sizeof(Thist)/8
dvb_deconvol_sync(scheduler *sch, dvb_deconvol_sync(
scheduler *sch,
pipebuf<Tin> &_in, pipebuf<Tin> &_in,
pipebuf<decoded_byte> &_out) : runnable(sch, "deconvol_sync_multipoly"), pipebuf<decoded_byte> &_out
) :
runnable(sch, "deconvol_sync_multipoly"),
resync_period(32), resync_period(32),
in(_in), in(_in),
out(_out, chunk_size), out(_out, chunk_size),
@ -736,7 +754,7 @@ struct dvb_deconvol_sync : runnable
while (in.readable() >= chunk_size * 8 && out.writable() >= chunk_size) while (in.readable() >= chunk_size * 8 && out.writable() >= chunk_size)
{ {
int errors_best = 1 << 30; int errors_best = 1 << 30;
sync_t *best = NULL; sync_t *best = nullptr;
for (sync_t *s = syncs; s < syncs + NSYNCS; ++s) for (sync_t *s = syncs; s < syncs + NSYNCS; ++s)
{ {
@ -833,12 +851,15 @@ struct mpeg_sync : runnable
bool fastlock; bool fastlock;
int resync_period; int resync_period;
mpeg_sync(scheduler *sch, mpeg_sync(
scheduler *sch,
pipebuf<Tbyte> &_in, pipebuf<Tbyte> &_in,
pipebuf<Tbyte> &_out, pipebuf<Tbyte> &_out,
deconvol_sync<Tbyte, 0> *_deconv, deconvol_sync<Tbyte, 0> *_deconv,
pipebuf<int> *_state_out = NULL, pipebuf<int> *_state_out = nullptr,
pipebuf<unsigned long> *_locktime_out = NULL) : runnable(sch, "sync_detect"), pipebuf<unsigned long> *_locktime_out = nullptr
) :
runnable(sch, "sync_detect"),
scan_syncs(8), scan_syncs(8),
want_syncs(4), want_syncs(4),
lock_timeout(4), lock_timeout(4),
@ -854,8 +875,18 @@ struct mpeg_sync : runnable
next_sync_count(0), next_sync_count(0),
report_state(true) report_state(true)
{ {
state_out = _state_out ? new pipewriter<int>(*_state_out) : NULL; state_out = _state_out ? new pipewriter<int>(*_state_out) : nullptr;
locktime_out = _locktime_out ? new pipewriter<unsigned long>(*_locktime_out) : NULL; locktime_out = _locktime_out ? new pipewriter<unsigned long>(*_locktime_out) : nullptr;
}
~mpeg_sync()
{
if (state_out) {
delete state_out;
}
if (locktime_out) {
delete locktime_out;
}
} }
void run() void run()
@ -1096,9 +1127,12 @@ struct rspacket
struct interleaver : runnable struct interleaver : runnable
{ {
interleaver(scheduler *sch, interleaver(
scheduler *sch,
pipebuf<rspacket<u8>> &_in, pipebuf<rspacket<u8>> &_in,
pipebuf<u8> &_out) : runnable(sch, "interleaver"), pipebuf<u8> &_out
) :
runnable(sch, "interleaver"),
in(_in), in(_in),
out(_out, SIZE_RSPACKET) out(_out, SIZE_RSPACKET)
{ {
@ -1112,8 +1146,7 @@ struct interleaver : runnable
u8 *pout = out.wr(); u8 *pout = out.wr();
int delay = 0; int delay = 0;
for (int i = 0; i < SIZE_RSPACKET; ++i, ++pout, delay = (delay + 1) % 12) for (int i = 0; i < SIZE_RSPACKET; ++i, ++pout, delay = (delay + 1) % 12) {
{
*pout = pin[11 - delay].data[i]; *pout = pin[11 - delay].data[i];
} }
@ -1133,9 +1166,12 @@ struct interleaver : runnable
template <typename Tbyte> template <typename Tbyte>
struct deinterleaver : runnable struct deinterleaver : runnable
{ {
deinterleaver(scheduler *sch, deinterleaver(
scheduler *sch,
pipebuf<Tbyte> &_in, pipebuf<Tbyte> &_in,
pipebuf<rspacket<Tbyte>> &_out) : runnable(sch, "deinterleaver"), pipebuf<rspacket<Tbyte>> &_out
) :
runnable(sch, "deinterleaver"),
in(_in), in(_in),
out(_out) out(_out)
{ {
@ -1148,8 +1184,7 @@ struct deinterleaver : runnable
Tbyte *pin = in.rd() + 17 * 11 * 12, *pend = pin + SIZE_RSPACKET; Tbyte *pin = in.rd() + 17 * 11 * 12, *pend = pin + SIZE_RSPACKET;
Tbyte *pout = out.wr()->data; Tbyte *pout = out.wr()->data;
for (int delay = 17 * 11; pin < pend; ++pin, ++pout, delay = (delay - 17 + 17 * 12) % (17 * 12)) for (int delay = 17 * 11; pin < pend; ++pin, ++pout, delay = (delay - 17 + 17 * 12) % (17 * 12)) {
{
*pout = pin[-delay * 12]; *pout = pin[-delay * 12];
} }
@ -1175,9 +1210,12 @@ struct tspacket
struct rs_encoder : runnable struct rs_encoder : runnable
{ {
rs_encoder(scheduler *sch, rs_encoder(
scheduler *sch,
pipebuf<tspacket> &_in, pipebuf<tspacket> &_in,
pipebuf<rspacket<u8>> &_out) : runnable(sch, "RS encoder"), pipebuf<rspacket<u8>> &_out
) :
runnable(sch, "RS encoder"),
in(_in), in(_in),
out(_out) out(_out)
{ {
@ -1213,16 +1251,29 @@ struct rs_decoder : runnable
{ {
rs_engine rs; rs_engine rs;
rs_decoder(scheduler *sch, rs_decoder(
scheduler *sch,
pipebuf<rspacket<Tbyte>> &_in, pipebuf<rspacket<Tbyte>> &_in,
pipebuf<tspacket> &_out, pipebuf<tspacket> &_out,
pipebuf<int> *_bitcount = NULL, pipebuf<int> *_bitcount = nullptr,
pipebuf<int> *_errcount = NULL) : runnable(sch, "RS decoder"), pipebuf<int> *_errcount = nullptr
) :
runnable(sch, "RS decoder"),
in(_in), in(_in),
out(_out) out(_out)
{ {
bitcount = _bitcount ? new pipewriter<int>(*_bitcount) : NULL; bitcount = _bitcount ? new pipewriter<int>(*_bitcount) : nullptr;
errcount = _errcount ? new pipewriter<int>(*_errcount) : NULL; errcount = _errcount ? new pipewriter<int>(*_errcount) : nullptr;
}
~rs_decoder()
{
if (bitcount) {
delete bitcount;
}
if (errcount) {
delete errcount;
}
} }
void run() void run()
@ -1307,9 +1358,12 @@ struct rs_decoder : runnable
struct randomizer : runnable struct randomizer : runnable
{ {
randomizer(scheduler *sch, randomizer(
scheduler *sch,
pipebuf<tspacket> &_in, pipebuf<tspacket> &_in,
pipebuf<tspacket> &_out) : runnable(sch, "derandomizer"), pipebuf<tspacket> &_out
) :
runnable(sch, "derandomizer"),
in(_in), in(_in),
out(_out) out(_out)
{ {
@ -1367,9 +1421,12 @@ struct randomizer : runnable
struct derandomizer : runnable struct derandomizer : runnable
{ {
derandomizer(scheduler *sch, derandomizer(
scheduler *sch,
pipebuf<tspacket> &_in, pipebuf<tspacket> &_in,
pipebuf<tspacket> &_out) : runnable(sch, "derandomizer"), pipebuf<tspacket> &_out
) :
runnable(sch, "derandomizer"),
in(_in), in(_in),
out(_out) out(_out)
{ {
@ -1525,11 +1582,14 @@ struct viterbi_sync : runnable
public: public:
int resync_period; int resync_period;
viterbi_sync(scheduler *sch, viterbi_sync(
scheduler *sch,
pipebuf<eucl_ss> &_in, pipebuf<eucl_ss> &_in,
pipebuf<unsigned char> &_out, pipebuf<unsigned char> &_out,
cstln_lut<eucl_ss, 256> *_cstln, cstln_lut<eucl_ss, 256> *_cstln,
code_rate cr) : runnable(sch, "viterbi_sync"), code_rate cr
) :
runnable(sch, "viterbi_sync"),
in(_in), in(_in),
out(_out, chunk_size), out(_out, chunk_size),
cstln(_cstln), cstln(_cstln),
@ -1659,6 +1719,11 @@ struct viterbi_sync : runnable
} }
} }
~viterbi_sync()
{
delete syncs;
}
TCS *init_map(bool conj, float angle) TCS *init_map(bool conj, float angle)
{ {
// Each constellation has its own pattern for labels. // Each constellation has its own pattern for labels.

View File

@ -299,11 +299,14 @@ const modcod_info *check_modcod(int m)
template <typename T> template <typename T>
struct s2_frame_transmitter : runnable struct s2_frame_transmitter : runnable
{ {
s2_frame_transmitter(scheduler *sch, s2_frame_transmitter(
scheduler *sch,
pipebuf<plslot<hard_ss>> &_in, pipebuf<plslot<hard_ss>> &_in,
pipebuf<complex<T>> &_out) pipebuf<complex<T>> &_out
: runnable(sch, "S2 frame transmitter"), ) :
in(_in), out(_out, modcod_info::MAX_SYMBOLS_PER_FRAME) runnable(sch, "S2 frame transmitter"),
in(_in),
out(_out, modcod_info::MAX_SYMBOLS_PER_FRAME)
{ {
float amp = cstln_amp / sqrtf(2); float amp = cstln_amp / sqrtf(2);
qsymbols[0].re = +amp; qsymbols[0].re = +amp;
@ -437,15 +440,36 @@ static int pl_errors = 0, pl_symbols = 0;
template <typename T, typename SOFTSYMB> template <typename T, typename SOFTSYMB>
struct s2_frame_receiver : runnable struct s2_frame_receiver : runnable
{ {
enum {
COARSE_FREQ,
FRAME_SEARCH,
FRAME_LOCKED,
} state;
sampler_interface<T> *sampler; sampler_interface<T> *sampler;
int meas_decimation; int meas_decimation;
float Ftune; // Tuning bias in cycles per symbol float Ftune; // Tuning bias in cycles per symbol
float Fm; // Baud rate in Hz, for debug messages only. TBD remove. float Fm; // Baud rate in Hz, for debug messages only. TBD remove.
bool strongpls; bool strongpls;
float min_freqw16, max_freqw16;
// State during COARSE_FREQ
complex<float> diffcorr;
int coarse_count;
// State during FRAME_SEARCH and FRAME_LOCKED
float freqw16; // Carrier frequency initialized by COARSE_FREQ
float phase16; // Estimated phase of carrier at next symbol
float mu; // Time to next symbol, in samples
float omega0; // Samples per symbol
static const int MAX_SYMBOLS_PER_FRAME = static const int MAX_SYMBOLS_PER_FRAME =
(1 + modcod_info::MAX_SLOTS_PER_FRAME) * plslot<hard_ss>::LENGTH + (1 + modcod_info::MAX_SLOTS_PER_FRAME) * plslot<hard_ss>::LENGTH +
((modcod_info::MAX_SLOTS_PER_FRAME - 1) / 16) * pilot_length; ((modcod_info::MAX_SLOTS_PER_FRAME - 1) / 16) * pilot_length;
s2_frame_receiver(scheduler *sch,
s2_frame_receiver(
scheduler *sch,
sampler_interface<T> *_sampler, sampler_interface<T> *_sampler,
pipebuf<complex<T>> &_in, pipebuf<complex<T>> &_in,
pipebuf<plslot<SOFTSYMB>> &_out, pipebuf<plslot<SOFTSYMB>> &_out,
@ -455,8 +479,9 @@ struct s2_frame_receiver : runnable
pipebuf<complex<float>> *_cstln_out = nullptr, pipebuf<complex<float>> *_cstln_out = nullptr,
pipebuf<complex<float>> *_cstln_pls_out = nullptr, pipebuf<complex<float>> *_cstln_pls_out = nullptr,
pipebuf<complex<float>> *_symbols_out = nullptr, pipebuf<complex<float>> *_symbols_out = nullptr,
pipebuf<int> *_state_out = nullptr) pipebuf<int> *_state_out = nullptr
: runnable(sch, "S2 frame receiver"), ) :
runnable(sch, "S2 frame receiver"),
sampler(_sampler), sampler(_sampler),
meas_decimation(1048576), meas_decimation(1048576),
Ftune(0), Fm(0), Ftune(0), Fm(0),
@ -489,25 +514,10 @@ struct s2_frame_receiver : runnable
#endif #endif
} }
enum ~s2_frame_receiver()
{ {
COARSE_FREQ, delete qpsk;
FRAME_SEARCH, }
FRAME_LOCKED,
} state;
float min_freqw16, max_freqw16;
// State during COARSE_FREQ
complex<float> diffcorr;
int coarse_count;
// State during FRAME_SEARCH and FRAME_LOCKED
float freqw16; // Carrier frequency initialized by COARSE_FREQ
float phase16; // Estimated phase of carrier at next symbol
float mu; // Time to next symbol, in samples
float omega0; // Samples per symbol
void run() void run()
{ {
@ -1237,11 +1247,14 @@ struct fecframe
struct s2_interleaver : runnable struct s2_interleaver : runnable
{ {
s2_interleaver(scheduler *sch, s2_interleaver(
scheduler *sch,
pipebuf<fecframe<hard_sb>> &_in, pipebuf<fecframe<hard_sb>> &_in,
pipebuf<plslot<hard_ss>> &_out) pipebuf<plslot<hard_ss>> &_out
: runnable(sch, "S2 interleaver"), ) :
in(_in), out(_out, 1 + 360) runnable(sch, "S2 interleaver"),
in(_in),
out(_out, 1 + 360)
{ {
} }
void run() void run()
@ -1566,13 +1579,17 @@ struct s2_interleaver : runnable
template <typename SOFTSYMB, typename SOFTBYTE> template <typename SOFTSYMB, typename SOFTBYTE>
struct s2_deinterleaver : runnable struct s2_deinterleaver : runnable
{ {
s2_deinterleaver(scheduler *sch, s2_deinterleaver(
scheduler *sch,
pipebuf<plslot<SOFTSYMB>> &_in, pipebuf<plslot<SOFTSYMB>> &_in,
pipebuf<fecframe<SOFTBYTE>> &_out) pipebuf<fecframe<SOFTBYTE>> &_out
: runnable(sch, "S2 deinterleaver"), ) :
in(_in), out(_out) runnable(sch, "S2 deinterleaver"),
in(_in),
out(_out)
{ {
} }
void run() void run()
{ {
while (in.readable() >= 1 && out.writable() >= 1) while (in.readable() >= 1 && out.writable() >= 1)
@ -2044,10 +2061,14 @@ struct s2_bch_engines
struct s2_fecenc : runnable struct s2_fecenc : runnable
{ {
typedef ldpc_engine<bool, hard_sb, 8, uint16_t> s2_ldpc_engine; typedef ldpc_engine<bool, hard_sb, 8, uint16_t> s2_ldpc_engine;
s2_fecenc(scheduler *sch, s2_fecenc(
pipebuf<bbframe> &_in, pipebuf<fecframe<hard_sb>> &_out) scheduler *sch,
: runnable(sch, "S2 fecenc"), pipebuf<bbframe> &_in,
in(_in), out(_out) pipebuf<fecframe<hard_sb>> &_out
) :
runnable(sch, "S2 fecenc"),
in(_in),
out(_out)
{ {
if (sch->debug) if (sch->debug)
s2ldpc.print_node_stats(); s2ldpc.print_node_stats();
@ -2097,13 +2118,16 @@ template <typename SOFTBIT, typename SOFTBYTE>
struct s2_fecdec : runnable struct s2_fecdec : runnable
{ {
int bitflips; int bitflips;
s2_fecdec(scheduler *sch, s2_fecdec(
scheduler *sch,
pipebuf<fecframe<SOFTBYTE>> &_in, pipebuf<bbframe> &_out, pipebuf<fecframe<SOFTBYTE>> &_in, pipebuf<bbframe> &_out,
pipebuf<int> *_bitcount = nullptr, pipebuf<int> *_bitcount = nullptr,
pipebuf<int> *_errcount = nullptr) pipebuf<int> *_errcount = nullptr
: runnable(sch, "S2 fecdec"), ) :
runnable(sch, "S2 fecdec"),
bitflips(0), bitflips(0),
in(_in), out(_out), in(_in),
out(_out),
bitcount(opt_writer(_bitcount, 1)), bitcount(opt_writer(_bitcount, 1)),
errcount(opt_writer(_errcount, 1)) errcount(opt_writer(_errcount, 1))
{ {
@ -2186,16 +2210,19 @@ struct s2_fecdec : runnable
template <typename SOFTBIT, typename SOFTBYTE> template <typename SOFTBIT, typename SOFTBYTE>
struct s2_fecdec_soft : runnable struct s2_fecdec_soft : runnable
{ {
s2_fecdec_soft(scheduler *sch, s2_fecdec_soft(
scheduler *sch,
pipebuf<fecframe<SOFTBYTE>> &_in, pipebuf<fecframe<SOFTBYTE>> &_in,
pipebuf<bbframe> &_out, pipebuf<bbframe> &_out,
int _modcod, int _modcod,
bool _shortframes = true, bool _shortframes = true,
int _max_trials = 25, int _max_trials = 25,
pipebuf<int> *_bitcount = nullptr, pipebuf<int> *_bitcount = nullptr,
pipebuf<int> *_errcount = nullptr) pipebuf<int> *_errcount = nullptr
: runnable(sch, "S2 fecdec soft"), ) :
in(_in), out(_out), runnable(sch, "S2 fecdec soft"),
in(_in),
out(_out),
modcod(_modcod < 0 ? 0 : _modcod > 31 ? 31 : _modcod), modcod(_modcod < 0 ? 0 : _modcod > 31 ? 31 : _modcod),
shortframes(_shortframes ? 1 : 0), shortframes(_shortframes ? 1 : 0),
max_trials(_max_trials), max_trials(_max_trials),
@ -2357,18 +2384,21 @@ struct s2_fecdec_helper : runnable
bool must_buffer; bool must_buffer;
int max_trials; int max_trials;
s2_fecdec_helper(scheduler *sch, s2_fecdec_helper(
scheduler *sch,
pipebuf<fecframe<SOFTBYTE>> &_in, pipebuf<fecframe<SOFTBYTE>> &_in,
pipebuf<bbframe> &_out, pipebuf<bbframe> &_out,
const char *_command, const char *_command,
pipebuf<int> *_bitcount = nullptr, pipebuf<int> *_bitcount = nullptr,
pipebuf<int> *_errcount = nullptr) pipebuf<int> *_errcount = nullptr
: runnable(sch, "S2 fecdec io"), ) :
runnable(sch, "S2 fecdec io"),
batch_size(16), batch_size(16),
nhelpers(1), nhelpers(1),
must_buffer(false), must_buffer(false),
max_trials(8), max_trials(8),
in(_in), out(_out), in(_in),
out(_out),
bitcount(opt_writer(_bitcount, 1)), bitcount(opt_writer(_bitcount, 1)),
errcount(opt_writer(_errcount, 1)) errcount(opt_writer(_errcount, 1))
{ {
@ -2459,6 +2489,7 @@ struct s2_fecdec_helper : runnable
lseek(h->fd_tx, 0, SEEK_SET); // allow new writes on this worker lseek(h->fd_tx, 0, SEEK_SET); // allow new writes on this worker
continue; // next worker continue; // next worker
} }
if (nw < 0) if (nw < 0)
fatal("write(LDPC helper"); fatal("write(LDPC helper");
else if (nw != iosize) else if (nw != iosize)
@ -2524,9 +2555,9 @@ struct s2_fecdec_helper : runnable
int cs; int cs;
waitpid(h->pid, &cs, 0); waitpid(h->pid, &cs, 0);
} }
// reset pipes // close pipes
lseek(h->fd_tx, 0, SEEK_SET); close(h->fd_tx);
lseek(h->fd_rx, 0, SEEK_SET); close(h->fd_rx);
} }
delete p->procs; delete p->procs;
@ -2638,7 +2669,7 @@ struct s2_fecdec_helper : runnable
} }
else if (nr != iosize) else if (nr != iosize)
{ {
fprintf(stderr, "s2_fecdec_helper::receive_frame: %d bytes read vs %d", nr, iosize); fprintf(stderr, "s2_fecdec_helper::receive_frame: %d bytes read vs %d\n", nr, iosize);
} }
--job->h->b_out; --job->h->b_out;
@ -2700,9 +2731,15 @@ struct s2_framer : runnable
{ {
uint8_t rolloff_code; // 0=0.35, 1=0.25, 2=0.20, 3=reserved uint8_t rolloff_code; // 0=0.35, 1=0.25, 2=0.20, 3=reserved
s2_pls pls; s2_pls pls;
s2_framer(scheduler *sch, pipebuf<tspacket> &_in, pipebuf<bbframe> &_out)
: runnable(sch, "S2 framer"), s2_framer(
in(_in), out(_out) scheduler *sch,
pipebuf<tspacket> &_in,
pipebuf<bbframe> &_out
) :
runnable(sch, "S2 framer"),
in(_in),
out(_out)
{ {
pls.modcod = 4; pls.modcod = 4;
pls.sf = false; pls.sf = false;
@ -2782,12 +2819,17 @@ struct s2_framer : runnable
struct s2_deframer : runnable struct s2_deframer : runnable
{ {
s2_deframer(scheduler *sch, pipebuf<bbframe> &_in, pipebuf<tspacket> &_out, s2_deframer(
scheduler *sch,
pipebuf<bbframe> &_in,
pipebuf<tspacket> &_out,
pipebuf<int> *_state_out = nullptr, pipebuf<int> *_state_out = nullptr,
pipebuf<unsigned long> *_locktime_out = nullptr) pipebuf<unsigned long> *_locktime_out = nullptr
: runnable(sch, "S2 deframer"), ) :
runnable(sch, "S2 deframer"),
missing(-1), missing(-1),
in(_in), out(_out, MAX_TS_PER_BBFRAME), in(_in),
out(_out, MAX_TS_PER_BBFRAME),
current_state(false), current_state(false),
state_out(opt_writer(_state_out, 2)), state_out(opt_writer(_state_out, 2)),
report_state(true), report_state(true),

View File

@ -107,7 +107,7 @@ struct runnable_common
struct window_placement struct window_placement
{ {
const char *name; // NULL to terminate const char *name; // nullptr to terminate
int x, y, w, h; int x, y, w, h;
}; };
@ -120,9 +120,10 @@ struct scheduler
window_placement *windows; window_placement *windows;
bool verbose, debug, debug2; bool verbose, debug, debug2;
scheduler() : npipes(0), scheduler() :
npipes(0),
nrunnables(0), nrunnables(0),
windows(NULL), windows(nullptr),
verbose(false), verbose(false),
debug(false), debug(false),
debug2(false) debug2(false)
@ -208,22 +209,28 @@ struct pipebuf : pipebuf_common
T *wr; T *wr;
T *end; T *end;
int sizeofT() pipebuf(scheduler *sch, const char *name, unsigned long size) :
{ pipebuf_common(name),
return sizeof(T); nrd(0),
}
pipebuf(scheduler *sch, const char *name, unsigned long size) : pipebuf_common(name),
buf(new T[size]),
nrd(0), wr(buf),
end(buf + size),
min_write(1), min_write(1),
total_written(0), total_written(0),
total_read(0) total_read(0)
{ {
buf = new T[size];
wr = buf;
end = buf + size;
sch->add_pipe(this); sch->add_pipe(this);
} }
~pipebuf()
{
delete[] buf;
}
int sizeofT() {
return sizeof(T);
}
int add_reader() int add_reader()
{ {
if (nrd == MAX_READERS) if (nrd == MAX_READERS)
@ -307,9 +314,8 @@ struct pipewriter
void written(unsigned long n) void written(unsigned long n)
{ {
if (buf.wr + n > buf.end) if (buf.wr + n > buf.end) {
{ fprintf(stderr, "pipewriter::written: bug: overflow to %s\n", buf.name);
fprintf(stderr, "Bug: overflow to %s\n", buf.name);
} }
buf.wr += n; buf.wr += n;
@ -328,13 +334,13 @@ struct pipewriter
template <typename T> template <typename T>
pipewriter<T> *opt_writer(pipebuf<T> *buf, unsigned long min_write = 1) pipewriter<T> *opt_writer(pipebuf<T> *buf, unsigned long min_write = 1)
{ {
return buf ? new pipewriter<T>(*buf, min_write) : NULL; return buf ? new pipewriter<T>(*buf, min_write) : nullptr;
} }
template <typename T> template <typename T>
bool opt_writable(pipewriter<T> *p, int n = 1) bool opt_writable(pipewriter<T> *p, int n = 1)
{ {
return (p == NULL) || p->writable() >= n; return (p == nullptr) || p->writable() >= n;
} }
template <typename T> template <typename T>

View File

@ -48,11 +48,14 @@ struct auto_notch : runnable
int decimation; int decimation;
float k; float k;
auto_notch(scheduler *sch, auto_notch(
scheduler *sch,
pipebuf<complex<T>> &_in, pipebuf<complex<T>> &_in,
pipebuf<complex<T>> &_out, pipebuf<complex<T>> &_out,
int _nslots, int _nslots,
T _agc_rms_setpoint) : runnable(sch, "auto_notch"), T _agc_rms_setpoint
) :
runnable(sch, "auto_notch"),
decimation(1024 * 4096), decimation(1024 * 4096),
k(0.002), // k(0.01) k(0.002), // k(0.01)
fft(4096), fft(4096),
@ -74,6 +77,10 @@ struct auto_notch : runnable
~auto_notch() ~auto_notch()
{ {
for (int s = 0; s < nslots; ++s) {
delete[] __slots[s].expj;
}
delete[] __slots; delete[] __slots;
} }
@ -226,7 +233,11 @@ struct ss_estimator : runnable
unsigned long window_size; // Samples per estimation unsigned long window_size; // Samples per estimation
unsigned long decimation; // Output rate unsigned long decimation; // Output rate
ss_estimator(scheduler *sch, pipebuf<complex<T>> &_in, pipebuf<T> &_out) : runnable(sch, "SS estimator"), ss_estimator(
scheduler *sch,
pipebuf<complex<T>> &_in, pipebuf<T> &_out
) :
runnable(sch, "SS estimator"),
window_size(1024), window_size(1024),
decimation(1024), decimation(1024),
in(_in), in(_in),
@ -268,11 +279,14 @@ struct ss_amp_estimator : runnable
unsigned long window_size; // Samples per estimation unsigned long window_size; // Samples per estimation
unsigned long decimation; // Output rate unsigned long decimation; // Output rate
ss_amp_estimator(scheduler *sch, ss_amp_estimator(
scheduler *sch,
pipebuf<complex<T>> &_in, pipebuf<complex<T>> &_in,
pipebuf<T> &_out_ss, pipebuf<T> &_out_ss,
pipebuf<T> &_out_ampmin, pipebuf<T> &_out_ampmin,
pipebuf<T> &_out_ampmax) : runnable(sch, "SS estimator"), pipebuf<T> &_out_ampmax
) :
runnable(sch, "SS estimator"),
window_size(1024), window_size(1024),
decimation(1024), decimation(1024),
in(_in), in(_in),
@ -332,9 +346,12 @@ struct simple_agc : runnable
float estimated; // Input power float estimated; // Input power
static const int chunk_size = 128; static const int chunk_size = 128;
simple_agc(scheduler *sch, simple_agc(
scheduler *sch,
pipebuf<complex<T>> &_in, pipebuf<complex<T>> &_in,
pipebuf<complex<T>> &_out) : runnable(sch, "AGC"), pipebuf<complex<T>> &_out
) :
runnable(sch, "AGC"),
out_rms(1), out_rms(1),
bw(0.001), bw(0.001),
estimated(0), estimated(0),
@ -484,12 +501,16 @@ struct cstln_base
template <typename SOFTSYMB, int R> template <typename SOFTSYMB, int R>
struct cstln_lut : cstln_base struct cstln_lut : cstln_base
{ {
cstln_lut(cstln_base::predef type, cstln_lut(
cstln_base::predef type,
float mer = 10, float mer = 10,
float gamma1 = 0, float gamma1 = 0,
float gamma2 = 0, float gamma2 = 0,
float gamma3 = 0) float gamma3 = 0
)
{ {
symbols = nullptr;
switch (type) switch (type)
{ {
case BPSK: case BPSK:
@ -679,6 +700,13 @@ struct cstln_lut : cstln_base
} }
} }
~cstln_lut()
{
if (symbols) {
delete[] symbols;
}
}
struct result struct result
{ {
SOFTSYMB ss; SOFTSYMB ss;
@ -958,15 +986,21 @@ struct linear_sampler : sampler_interface<T>
template <typename T, typename Tc> template <typename T, typename Tc>
struct fir_sampler : sampler_interface<T> struct fir_sampler : sampler_interface<T>
{ {
fir_sampler(int _ncoeffs, Tc *_coeffs, int _subsampling = 1) : ncoeffs(_ncoeffs), fir_sampler(int _ncoeffs, Tc *_coeffs, int _subsampling = 1) :
ncoeffs(_ncoeffs),
coeffs(_coeffs), coeffs(_coeffs),
subsampling(_subsampling), subsampling(_subsampling),
shifted_coeffs(new complex<T>[ncoeffs]),
update_freq_phase(0) update_freq_phase(0)
{ {
shifted_coeffs = new complex<T>[ncoeffs];
do_update_freq(0); // In case application never calls update_freq() do_update_freq(0); // In case application never calls update_freq()
} }
~fir_sampler()
{
delete[] shifted_coeffs;
}
int readahead() int readahead()
{ {
return ncoeffs - 1; return ncoeffs - 1;
@ -1050,16 +1084,19 @@ struct cstln_receiver : runnable
static const unsigned int chunk_size = 128; static const unsigned int chunk_size = 128;
float kest; float kest;
cstln_receiver(scheduler *sch, cstln_receiver(
scheduler *sch,
sampler_interface<T> *_sampler, sampler_interface<T> *_sampler,
pipebuf<complex<T>> &_in, pipebuf<complex<T>> &_in,
pipebuf<SOFTSYMB> &_out, pipebuf<SOFTSYMB> &_out,
pipebuf<float> *_freq_out = NULL, pipebuf<float> *_freq_out = nullptr,
pipebuf<float> *_ss_out = NULL, pipebuf<float> *_ss_out = nullptr,
pipebuf<float> *_mer_out = NULL, pipebuf<float> *_mer_out = nullptr,
pipebuf<cf32> *_cstln_out = NULL) : runnable(sch, "Constellation receiver"), pipebuf<cf32> *_cstln_out = nullptr
) :
runnable(sch, "Constellation receiver"),
sampler(_sampler), sampler(_sampler),
cstln(NULL), cstln(nullptr),
meas_decimation(1048576), meas_decimation(1048576),
pll_adjustment(1.0), pll_adjustment(1.0),
allow_drift(false), allow_drift(false),
@ -1076,10 +1113,10 @@ struct cstln_receiver : runnable
{ {
set_omega(1); set_omega(1);
set_freq(0); set_freq(0);
freq_out = _freq_out ? new pipewriter<float>(*_freq_out) : NULL; freq_out = _freq_out ? new pipewriter<float>(*_freq_out) : nullptr;
ss_out = _ss_out ? new pipewriter<float>(*_ss_out) : NULL; ss_out = _ss_out ? new pipewriter<float>(*_ss_out) : nullptr;
mer_out = _mer_out ? new pipewriter<float>(*_mer_out) : NULL; mer_out = _mer_out ? new pipewriter<float>(*_mer_out) : nullptr;
cstln_out = _cstln_out ? new pipewriter<cf32>(*_cstln_out) : NULL; cstln_out = _cstln_out ? new pipewriter<cf32>(*_cstln_out) : nullptr;
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
@ -1088,6 +1125,22 @@ struct cstln_receiver : runnable
} }
} }
~cstln_receiver()
{
if (freq_out) {
delete freq_out;
}
if (ss_out) {
delete ss_out;
}
if (mer_out) {
delete mer_out;
}
if (cstln_out) {
delete cstln_out;
}
}
void set_omega(float _omega, float tol = 10e-6) void set_omega(float _omega, float tol = 10e-6)
{ {
omega = _omega; omega = _omega;
@ -1170,7 +1223,7 @@ struct cstln_receiver : runnable
// These are scoped outside the loop for SS and MER estimation. // These are scoped outside the loop for SS and MER estimation.
complex<float> sg{0.0f, 0.0f}; // Symbol before AGC; complex<float> sg{0.0f, 0.0f}; // Symbol before AGC;
complex<float> s; // For MER estimation and constellation viewer complex<float> s; // For MER estimation and constellation viewer
complex<signed char> *cstln_point = NULL; complex<signed char> *cstln_point = nullptr;
while (pin < pend) while (pin < pend)
{ {
@ -1292,8 +1345,7 @@ struct cstln_receiver : runnable
if (ss_out) if (ss_out)
ss_out->write(sqrtf(est_insp)); ss_out->write(sqrtf(est_insp));
if (mer_out) if (mer_out)
mer_out->write( mer_out->write(est_ep ? 10 * log10f(est_sp / est_ep) : 0);
est_ep ? 10 * logf(est_sp / est_ep) / logf(10) : 0);
} }
} // Work to do } // Work to do
@ -1342,11 +1394,14 @@ struct fast_qpsk_receiver : runnable
bool allow_drift; // Follow carrier beyond safe limits bool allow_drift; // Follow carrier beyond safe limits
static const unsigned int chunk_size = 128; static const unsigned int chunk_size = 128;
fast_qpsk_receiver(scheduler *sch, fast_qpsk_receiver(
scheduler *sch,
pipebuf<complex<T>> &_in, pipebuf<complex<T>> &_in,
pipebuf<hardsymbol> &_out, pipebuf<hardsymbol> &_out,
pipebuf<float> *_freq_out = NULL, pipebuf<float> *_freq_out = nullptr,
pipebuf<complex<T>> *_cstln_out = NULL) : runnable(sch, "Fast QPSK receiver"), pipebuf<complex<T>> *_cstln_out = nullptr
) :
runnable(sch, "Fast QPSK receiver"),
meas_decimation(1048576), meas_decimation(1048576),
pll_adjustment(1.0), pll_adjustment(1.0),
allow_drift(false), allow_drift(false),
@ -1358,12 +1413,22 @@ struct fast_qpsk_receiver : runnable
{ {
set_omega(1); set_omega(1);
set_freq(0); set_freq(0);
freq_out = _freq_out ? new pipewriter<float>(*_freq_out) : NULL; freq_out = _freq_out ? new pipewriter<float>(*_freq_out) : nullptr;
cstln_out = _cstln_out ? new pipewriter<complex<T>>(*_cstln_out) : NULL; cstln_out = _cstln_out ? new pipewriter<complex<T>>(*_cstln_out) : nullptr;
memset(hist, 0, sizeof(hist)); memset(hist, 0, sizeof(hist));
init_lookup_tables(); init_lookup_tables();
} }
~fast_qpsk_receiver()
{
if (freq_out) {
delete freq_out;
}
if (cstln_out) {
delete cstln_out;
}
}
void set_omega(float _omega, float tol = 10e-6) void set_omega(float _omega, float tol = 10e-6)
{ {
omega = _omega; omega = _omega;
@ -1621,12 +1686,15 @@ struct cstln_transmitter : runnable
{ {
cstln_lut<hard_ss, 256> *cstln; cstln_lut<hard_ss, 256> *cstln;
cstln_transmitter(scheduler *sch, cstln_transmitter(
scheduler *sch,
pipebuf<u8> &_in, pipebuf<u8> &_in,
pipebuf<complex<Tout>> &_out) : runnable(sch, "cstln_transmitter"), pipebuf<complex<Tout>> &_out
) :
runnable(sch, "cstln_transmitter"),
in(_in), in(_in),
out(_out), out(_out),
cstln(0) cstln(nullptr)
{ {
} }
@ -1663,10 +1731,13 @@ struct cstln_transmitter : runnable
template <typename T> template <typename T>
struct rotator : runnable struct rotator : runnable
{ {
rotator(scheduler *sch, rotator(
scheduler *sch,
pipebuf<complex<T>> &_in, pipebuf<complex<T>> &_in,
pipebuf<complex<T>> &_out, pipebuf<complex<T>> &_out,
float freq) : runnable(sch, "rotator"), float freq
) :
runnable(sch, "rotator"),
in(_in), in(_in),
out(_out), out(_out),
index(0) index(0)
@ -1721,29 +1792,34 @@ struct rotator : runnable
template <typename T> template <typename T>
struct cnr_fft : runnable struct cnr_fft : runnable
{ {
cnr_fft(scheduler *sch, cnr_fft(
scheduler *sch,
pipebuf<complex<T>> &_in, pipebuf<complex<T>> &_in,
pipebuf<float> &_out, pipebuf<float> &_out,
float _bandwidth, int nfft = 4096) : runnable(sch, "cnr_fft"), float _bandwidth, int nfft = 4096
) :
runnable(sch, "cnr_fft"),
bandwidth(_bandwidth), bandwidth(_bandwidth),
freq_tap(NULL), freq_tap(nullptr),
tap_multiplier(1), tap_multiplier(1),
decimation(1048576), decimation(1048576),
kavg(0.1), kavg(0.1),
in(_in), in(_in),
out(_out), out(_out),
fft(nfft), fft(nfft),
avgpower(NULL), avgpower(nullptr),
phase(0) phase(0)
{ {
if (bandwidth > 0.25) if (bandwidth > 0.25)
fail("CNR estimator requires Fsampling > 4x Fsignal"); fail("CNR estimator requires Fsampling > 4x Fsignal");
} }
float bandwidth; ~cnr_fft()
float *freq_tap, tap_multiplier; {
int decimation; if (avgpower) {
float kavg; delete[] avgpower;
}
}
void run() void run()
{ {
@ -1761,6 +1837,11 @@ struct cnr_fft : runnable
} }
} }
float bandwidth;
float *freq_tap, tap_multiplier;
int decimation;
float kavg;
private: private:
void do_cnr() void do_cnr()
{ {
@ -1826,22 +1907,32 @@ struct cnr_fft : runnable
template <typename T, int NFFT> template <typename T, int NFFT>
struct spectrum : runnable struct spectrum : runnable
{ {
spectrum(scheduler *sch, int decimation;
float kavg;
int decim;
spectrum(
scheduler *sch,
pipebuf<complex<T>> &_in, pipebuf<complex<T>> &_in,
pipebuf<float[NFFT]> &_out) : runnable(sch, "spectrum"), pipebuf<float[NFFT]> &_out
) :
runnable(sch, "spectrum"),
decimation(1048576), decimation(1048576),
kavg(0.1), kavg(0.1),
decim(1), in(_in), decim(1), in(_in),
out(_out), out(_out),
fft(NFFT), fft(NFFT),
avgpower(NULL), avgpower(nullptr),
phase(0) phase(0)
{ {
} }
int decimation; ~spectrum()
float kavg; {
int decim; if (avgpower) {
delete avgpower;
}
}
void run() void run()
{ {

View File

@ -124,6 +124,7 @@ template <typename TUS,
typename TPM> typename TPM>
struct viterbi_dec_interface struct viterbi_dec_interface
{ {
virtual ~viterbi_dec_interface() {}
virtual TUS update(TBM *costs, TPM *quality = NULL) = 0; virtual TUS update(TBM *costs, TPM *quality = NULL) = 0;
virtual TUS update(TCS s, TBM cost, TPM *quality = NULL) = 0; virtual TUS update(TCS s, TBM cost, TPM *quality = NULL) = 0;
}; };