1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-15 04:41:55 -05:00

DATV demod: experimental DVB-S2 support

This commit is contained in:
f4exb 2019-07-14 15:35:45 +02:00
parent c00ccf3b64
commit c981d76e6e
10 changed files with 701 additions and 22 deletions

View File

@ -24,7 +24,10 @@ set(datv_HEADERS
datvdemodsettings.h
datvideostream.h
datvideorender.h
datvconstellation.h
datvdvbs2constellation.h
leansdr/dvb.h
leansdr/dvbs2.h
leansdr/filtergen.h
leansdr/framework.h
leansdr/math.h

View File

@ -29,7 +29,7 @@ namespace leansdr {
static const int DEFAULT_GUI_DECIMATION = 64;
static inline cstln_lut<eucl_ss, 256> * make_dvbs2_constellation(cstln_lut<eucl_ss, 256>::predef c,
static inline cstln_lut<eucl_ss, 256> * make_dvbs_constellation(cstln_lut<eucl_ss, 256>::predef c,
code_rate r)
{
float gamma1 = 1, gamma2 = 1, gamma3 = 1;
@ -59,7 +59,7 @@ static inline cstln_lut<eucl_ss, 256> * make_dvbs2_constellation(cstln_lut<eucl_
gamma1 = 2.57;
break;
default:
fail("cstln_lut<256>::make_dvbs2_constellation: Code rate not supported with APSK16");
fail("cstln_lut<256>::make_dvbs_constellation: Code rate not supported with APSK16");
return 0;
}
break;
@ -88,7 +88,7 @@ static inline cstln_lut<eucl_ss, 256> * make_dvbs2_constellation(cstln_lut<eucl_
gamma2 = 4.30;
break;
default:
fail("cstln_lut<eucl_ss, 256>::make_dvbs2_constellation: Code rate not supported with APSK32");
fail("cstln_lut<eucl_ss, 256>::make_dvbs_constellation: Code rate not supported with APSK32");
return 0;
}
break;

View File

@ -19,6 +19,8 @@
#include "datvdemod.h"
#include "leansdr/dvbs2.h"
#include <QTime>
#include <QDebug>
#include <stdio.h>
@ -368,6 +370,63 @@ void DATVDemod::CleanUpDATVFramework(bool blnRelease)
//if(p_rawiq!=nullptr) delete p_rawiq;
//if(p_rawiq_writer!=nullptr) delete p_rawiq_writer;
//if(p_preprocessed!=nullptr) delete p_preprocessed;
//DVB-S2
if(p_slots_dvbs2 != nullptr)
{
delete (leansdr::pipebuf< leansdr::plslot<leansdr::llr_ss> >*) p_slots_dvbs2;
}
if(p_cstln != nullptr)
{
delete p_cstln;
}
if(p_cstln_pls != nullptr)
{
delete p_cstln_pls;
}
if(p_framelock != nullptr)
{
delete p_framelock;
}
if(m_objDemodulatorDVBS2 != nullptr)
{
delete (leansdr::s2_frame_receiver<leansdr::f32, leansdr::llr_ss>*) m_objDemodulatorDVBS2;
}
if(p_fecframes != nullptr)
{
delete (leansdr::pipebuf< leansdr::fecframe<leansdr::hard_sb> >*) p_fecframes;
}
if(p_bbframes != nullptr)
{
delete (leansdr::pipebuf<leansdr::bbframe>*) p_bbframes;
}
if(p_s2_deinterleaver != nullptr)
{
delete (leansdr::s2_deinterleaver<leansdr::llr_ss,leansdr::hard_sb>*) p_s2_deinterleaver;
}
if(r_fecdec != nullptr)
{
delete (leansdr::s2_fecdec<bool, leansdr::hard_sb>*) r_fecdec;
}
if(p_deframer != nullptr)
{
delete (leansdr::s2_deframer*) p_deframer;
}
if(r_scope_symbols_dvbs2 != nullptr)
{
delete r_scope_symbols_dvbs2;
}
}
m_objScheduler=nullptr;
@ -452,13 +511,26 @@ void DATVDemod::CleanUpDATVFramework(bool blnRelease)
r_derand = nullptr;
//OUTPUT : To remove
//OUTPUT : To remove void *
r_stdout = nullptr;
r_videoplayer = nullptr;
//CONSTELLATION
r_scope_symbols = nullptr;
//DVB-S2
p_slots_dvbs2 = nullptr;
p_cstln = nullptr;
p_cstln_pls = nullptr;
p_framelock = nullptr;
m_objDemodulatorDVBS2 = nullptr;
p_fecframes = nullptr;
p_bbframes = nullptr;
p_s2_deinterleaver = nullptr;
r_fecdec = nullptr;
p_deframer = nullptr;
r_scope_symbols_dvbs2 = nullptr;
}
void DATVDemod::InitDATVFramework()
@ -468,6 +540,7 @@ void DATVDemod::InitDATVFramework()
CleanUpDATVFramework(false);
qDebug() << "DATVDemod::InitDATVFramework:"
<< " Standard: " << m_settings.m_standard
<< " Symbol Rate: " << m_settings.m_symbolRate
<< " Modulation: " << m_settings.m_modulation
<< " Notch Filters: " << m_settings.m_notchFilters
@ -477,7 +550,8 @@ void DATVDemod::InitDATVFramework()
<< " HARD METRIC: " << m_settings.m_hardMetric
<< " RollOff: " << m_settings.m_rollOff
<< " Viterbi: " << m_settings.m_viterbi
<< " Excursion: " << m_settings.m_excursion;
<< " Excursion: " << m_settings.m_excursion
<< " Sample rate: " << m_sampleRate;
m_objCfg.standard = m_settings.m_standard;
@ -670,7 +744,7 @@ void DATVDemod::InitDATVFramework()
qDebug("DATVDemod::InitDATVFramework: DVB-S2: Testing symbol sampler only.");
}
m_objDemodulator->cstln = make_dvbs2_constellation(m_objCfg.constellation, m_objCfg.fec);
m_objDemodulator->cstln = make_dvbs_constellation(m_objCfg.constellation, m_objCfg.fec);
if (m_objCfg.hard_metric) {
m_objDemodulator->cstln->harden();
@ -706,6 +780,8 @@ void DATVDemod::InitDATVFramework()
if (m_objRegisteredTVScreen)
{
qDebug("DATVDemod::InitDATVFramework: Register DVBSTVSCREEN");
m_objRegisteredTVScreen->resizeTVScreen(256,256);
r_scope_symbols = new leansdr::datvconstellation<leansdr::f32>(m_objScheduler, *p_sampled, -128,128, nullptr, m_objRegisteredTVScreen);
r_scope_symbols->decimation = 1;
@ -784,6 +860,292 @@ void DATVDemod::InitDATVFramework()
m_blnDVBInitialized = true;
}
//************ DVB-S2 Decoder ************
void DATVDemod::InitDATVS2Framework()
{
leansdr::s2_frame_receiver<leansdr::f32, leansdr::llr_ss> * objDemodulatorDVBS2;
m_blnDVBInitialized = false;
m_lngReadIQ = 0;
CleanUpDATVFramework(false);
qDebug() << "DATVDemod::InitDATVS2Framework:"
<< " Standard: " << m_settings.m_standard
<< " Symbol Rate: " << m_settings.m_symbolRate
<< " Modulation: " << m_settings.m_modulation
<< " Notch Filters: " << m_settings.m_notchFilters
<< " Allow Drift: " << m_settings.m_allowDrift
<< " Fast Lock: " << m_settings.m_fastLock
<< " Filter: " << m_settings.m_filter
<< " HARD METRIC: " << m_settings.m_hardMetric
<< " RollOff: " << m_settings.m_rollOff
<< " Viterbi: " << m_settings.m_viterbi
<< " Excursion: " << m_settings.m_excursion
<< " Sample rate: " << m_sampleRate ;
m_objCfg.standard = m_settings.m_standard;
m_objCfg.fec = m_settings.m_fec;
m_objCfg.Fs = (float) m_sampleRate;
m_objCfg.Fm = (float) m_settings.m_symbolRate;
m_objCfg.fastlock = m_settings.m_fastLock;
m_objCfg.sampler = m_settings.m_filter;
m_objCfg.rolloff = m_settings.m_rollOff; //0...1
m_objCfg.rrc_rej = (float) m_settings.m_excursion; //dB
m_objCfg.rrc_steps = 0; //auto
switch(m_settings.m_modulation)
{
case DATVDemodSettings::BPSK:
m_objCfg.constellation = leansdr::cstln_lut<leansdr::llr_ss, 256>::BPSK;
break;
case DATVDemodSettings::QPSK:
m_objCfg.constellation = leansdr::cstln_lut<leansdr::llr_ss, 256>::QPSK;
break;
case DATVDemodSettings::PSK8:
m_objCfg.constellation = leansdr::cstln_lut<leansdr::llr_ss, 256>::PSK8;
break;
case DATVDemodSettings::APSK16:
m_objCfg.constellation = leansdr::cstln_lut<leansdr::llr_ss, 256>::APSK16;
break;
case DATVDemodSettings::APSK32:
m_objCfg.constellation = leansdr::cstln_lut<leansdr::llr_ss, 256>::APSK32;
break;
case DATVDemodSettings::APSK64E:
m_objCfg.constellation = leansdr::cstln_lut<leansdr::llr_ss, 256>::APSK64E;
break;
case DATVDemodSettings::QAM16:
m_objCfg.constellation = leansdr::cstln_lut<leansdr::llr_ss, 256>::QAM16;
break;
case DATVDemodSettings::QAM64:
m_objCfg.constellation = leansdr::cstln_lut<leansdr::llr_ss, 256>::QAM64;
break;
case DATVDemodSettings::QAM256:
m_objCfg.constellation = leansdr::cstln_lut<leansdr::llr_ss, 256>::QAM256;
break;
default:
m_objCfg.constellation = leansdr::cstln_lut<leansdr::llr_ss, 256>::BPSK;
break;
}
m_objCfg.allow_drift = m_settings.m_allowDrift;
m_objCfg.anf = m_settings.m_notchFilters;
m_objCfg.hard_metric = m_settings.m_hardMetric;
m_objCfg.sampler = m_settings.m_filter;
m_objCfg.viterbi = m_settings.m_viterbi;
// Min buffer size for baseband data
S2_MAX_SYMBOLS = (90*(1+360)+36*((360-1)/16));
BUF_BASEBAND = S2_MAX_SYMBOLS * 2 * (m_objCfg.Fs/m_objCfg.Fm) * m_objCfg.buf_factor;
// Min buffer size for IQ symbols
// cstln_receiver: writes in chunks of 128/omega symbols (margin 128)
// deconv_sync: reads at least 64+32
// A larger buffer improves performance significantly.
BUF_SYMBOLS = 1024 * m_objCfg.buf_factor;
// Min buffer size for misc measurements: 1
BUF_SLOW = m_objCfg.buf_factor;
// dvbs2 : Min buffer size for slots: 4 for deinterleaver
BUF_SLOTS = leansdr::modcod_info::MAX_SLOTS_PER_FRAME * m_objCfg.buf_factor;
BUF_FRAMES = m_objCfg.buf_factor;
// Min buffer size for TS packets: Up to 39 per BBFRAME
BUF_S2PACKETS = (leansdr::fec_info::KBCH_MAX/188/8+1) * m_objCfg.buf_factor;
m_lngExpectedReadIQ = BUF_BASEBAND;
m_objScheduler = new leansdr::scheduler();
//***************
p_rawiq = new leansdr::pipebuf<leansdr::cf32>(m_objScheduler, "rawiq", BUF_BASEBAND);
p_rawiq_writer = new leansdr::pipewriter<leansdr::cf32>(*p_rawiq);
p_preprocessed = p_rawiq;
// NOTCH FILTER
if (m_objCfg.anf>0)
{
p_autonotched = new leansdr::pipebuf<leansdr::cf32>(m_objScheduler, "autonotched", BUF_BASEBAND);
r_auto_notch = new leansdr::auto_notch<leansdr::f32>(m_objScheduler, *p_preprocessed, *p_autonotched, m_objCfg.anf, 0);
p_preprocessed = p_autonotched;
}
// FREQUENCY CORRECTION
//******** -> if ( m_objCfg.Fderot>0 )
// CNR ESTIMATION
/**
p_cnr = new leansdr::pipebuf<leansdr::f32>(m_objScheduler, "cnr", BUF_SLOW);
if (m_objCfg.cnr == true)
{
r_cnr = new leansdr::cnr_fft<leansdr::f32>(m_objScheduler, *p_preprocessed, *p_cnr, m_objCfg.Fm/m_objCfg.Fs);
r_cnr->decimation = decimation(m_objCfg.Fs, 1); // 1 Hz
}
**/
// FILTERING
int decim = 1;
//******** -> if ( m_objCfg.resample )
// DECIMATION
// (Unless already done in resampler)
//******** -> if ( !m_objCfg.resample && m_objCfg.decim>1 )
//Resampling FS
// Generic constellation receiver
p_freq = new leansdr::pipebuf<leansdr::f32> (m_objScheduler, "freq", BUF_SLOW);
p_ss = new leansdr::pipebuf<leansdr::f32> (m_objScheduler, "SS", BUF_SLOW);
p_mer = new leansdr::pipebuf<leansdr::f32> (m_objScheduler, "MER", BUF_SLOW);
switch (m_objCfg.sampler)
{
case DATVDemodSettings::SAMP_NEAREST:
sampler = new leansdr::nearest_sampler<float>();
break;
case DATVDemodSettings::SAMP_LINEAR:
sampler = new leansdr::linear_sampler<float>();
break;
case DATVDemodSettings::SAMP_RRC:
{
if (m_objCfg.rrc_steps == 0)
{
// At least 64 discrete sampling points between symbols
m_objCfg.rrc_steps = std::max(1, (int)(64*m_objCfg.Fm / m_objCfg.Fs));
}
float Frrc = m_objCfg.Fs * m_objCfg.rrc_steps; // Sample freq of the RRC filter
float transition = (m_objCfg.Fm/2) * m_objCfg.rolloff;
int order = m_objCfg.rrc_rej * Frrc / (22*transition);
ncoeffs_sampler = leansdr::filtergen::root_raised_cosine(order, m_objCfg.Fm/Frrc, m_objCfg.rolloff, &coeffs_sampler);
sampler = new leansdr::fir_sampler<float,float>(ncoeffs_sampler, coeffs_sampler, m_objCfg.rrc_steps);
break;
}
default:
qCritical("DATVDemod::InitDATVS2Framework: Interpolator not implemented");
return;
}
p_slots_dvbs2 = new leansdr::pipebuf< leansdr::plslot<leansdr::llr_ss> > (m_objScheduler, "PL slots", BUF_SLOTS);
p_cstln = new leansdr::pipebuf<leansdr::cf32>(m_objScheduler, "cstln", BUF_BASEBAND);
p_cstln_pls = new leansdr::pipebuf<leansdr::cf32>(m_objScheduler, "PLS cstln", BUF_BASEBAND);
p_framelock = new leansdr::pipebuf<int>(m_objScheduler, "frame lock", BUF_SLOW);
m_objDemodulatorDVBS2 = new leansdr::s2_frame_receiver<leansdr::f32, leansdr::llr_ss>(
m_objScheduler,
sampler,
*p_preprocessed,
*(leansdr::pipebuf< leansdr::plslot<leansdr::llr_ss> > *) p_slots_dvbs2,
/* p_freq */ nullptr,
/* p_ss */ nullptr,
/* p_mer */ nullptr,
p_cstln,
/* p_cstln_pls */ nullptr,
/*p_iqsymbols*/ nullptr,
/* p_framelock */nullptr);
objDemodulatorDVBS2 = (leansdr::s2_frame_receiver<leansdr::f32, leansdr::llr_ss> *) m_objDemodulatorDVBS2;
objDemodulatorDVBS2->omega = m_objCfg.Fs/m_objCfg.Fm;
//objDemodulatorDVBS2->mu=1;
m_objCfg.Ftune=0.0f;
objDemodulatorDVBS2->Ftune = m_objCfg.Ftune / m_objCfg.Fm;
/*
demod.strongpls = cfg.strongpls;
*/
objDemodulatorDVBS2->Fm = m_objCfg.Fm;
objDemodulatorDVBS2->meas_decimation = decimation(m_objCfg.Fs, m_objCfg.Finfo);
objDemodulatorDVBS2->strongpls = false;
objDemodulatorDVBS2->cstln = make_dvbs2_constellation(m_objCfg.constellation, m_objCfg.fec);
//constellation
if (m_objRegisteredTVScreen)
{
qDebug("DATVDemod::InitDATVS2Framework: Register DVBS 2 TVSCREEN");
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->decimation = 1;
r_scope_symbols_dvbs2->cstln = (leansdr::cstln_base**) &objDemodulatorDVBS2->cstln;
r_scope_symbols_dvbs2->calculate_cstln_points();
}
// Bit-flipping mode.
// Deinterleave into hard bits.
p_bbframes = new leansdr::pipebuf<leansdr::bbframe>(m_objScheduler, "BB frames", BUF_FRAMES);
p_fecframes = new leansdr::pipebuf< leansdr::fecframe<leansdr::hard_sb> >(m_objScheduler, "FEC frames", BUF_FRAMES);
p_s2_deinterleaver = new leansdr::s2_deinterleaver<leansdr::llr_ss,leansdr::hard_sb>(
m_objScheduler,
*(leansdr::pipebuf< leansdr::plslot<leansdr::llr_ss> > *) p_slots_dvbs2,
*(leansdr::pipebuf< leansdr::fecframe<leansdr::hard_sb> > * ) p_fecframes
);
p_vbitcount= new leansdr::pipebuf<int>(m_objScheduler, "Bits processed", BUF_S2PACKETS);
p_verrcount = new leansdr::pipebuf<int>(m_objScheduler, "Bits corrected", BUF_S2PACKETS);
r_fecdec = new leansdr::s2_fecdec<bool, leansdr::hard_sb>(
m_objScheduler, *(leansdr::pipebuf< leansdr::fecframe<leansdr::hard_sb> > * ) p_fecframes,
*(leansdr::pipebuf<leansdr::bbframe> *) p_bbframes,
p_vbitcount,
p_verrcount
);
leansdr::s2_fecdec<bool, leansdr::hard_sb> *fecdec = (leansdr::s2_fecdec<bool, leansdr::hard_sb> * ) r_fecdec;
fecdec->bitflips=0;
/*
fecdec->bitflips = cfg.ldpc_bf; //int TODO
if ( ! cfg.ldpc_bf )
fprintf(stderr, "Warning: No LDPC error correction selected.\n")
*/
// Deframe BB frames to TS packets
p_lock = new leansdr::pipebuf<int> (m_objScheduler, "lock", BUF_SLOW);
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_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;
*/
//**********************************************
// OUTPUT
r_videoplayer = new leansdr::datvvideoplayer<leansdr::tspacket>(m_objScheduler, *p_tspackets, m_objVideoStream);
m_blnDVBInitialized = true;
}
void DATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst)
{
(void) firstOfBurst;
@ -795,6 +1157,8 @@ void DATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVect
int intRFOut;
double magSq;
int lngWritable=0;
//********** Bis repetita : Let's rock and roll buddy ! **********
#ifdef EXTENDED_DIRECT_SAMPLE
@ -832,9 +1196,21 @@ void DATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVect
if (m_blnNeedConfigUpdate)
{
qDebug("DATVDemod::feed: Settings applied. Standard : %d...", m_settings.m_standard);
m_objSettingsMutex.lock();
m_blnNeedConfigUpdate=false;
if(m_settings.m_standard==DATVDemodSettings::DVB_S2)
{
printf("SWITCHING TO DVBS-2\r\n");
InitDATVS2Framework();
}
else
{
printf("SWITCHING TO DVBS\r\n");
InitDATVFramework();
}
m_objSettingsMutex.unlock();
}
@ -863,14 +1239,17 @@ void DATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVect
p_rawiq_writer->write(objIQ);
m_lngReadIQ++;
lngWritable = p_rawiq_writer->writable();
//Leave +1 by safety
if((m_lngReadIQ+1)>=p_rawiq_writer->writable())
if(((m_lngReadIQ+1)>=lngWritable) || (m_lngReadIQ>=768))
//if((m_lngReadIQ+1)>=lngWritable)
{
m_objScheduler->step();
m_lngReadIQ=0;
delete p_rawiq_writer;
p_rawiq_writer = new leansdr::pipewriter<leansdr::cf32>(*p_rawiq);
//delete p_rawiq_writer;
//p_rawiq_writer = new leansdr::pipewriter<leansdr::cf32>(*p_rawiq);
}
}
@ -896,7 +1275,9 @@ bool DATVDemod::handleMessage(const Message& cmd)
qDebug() << "DATVDemod::handleMessage: MsgChannelizerNotification:"
<< " m_intSampleRate: " << objNotif.getSampleRate()
<< " m_intFrequencyOffset: " << objNotif.getFrequencyOffset();
applyChannelSettings(objNotif.getSampleRate(), objNotif.getFrequencyOffset());
m_inputFrequencyOffset = objNotif.getFrequencyOffset();
applyChannelSettings(m_sampleRate /*objNotif.getSampleRate()*/, m_inputFrequencyOffset);
return true;
}
@ -911,6 +1292,9 @@ bool DATVDemod::handleMessage(const Message& cmd)
qDebug() << "DATVDemod::handleMessage: MsgConfigureChannelizer: sampleRate: " << m_channelizer->getInputSampleRate()
<< " centerFrequency: " << cfg.getCenterFrequency();
m_sampleRate = m_channelizer->getInputSampleRate();
applyChannelSettings(m_sampleRate /*objNotif.getSampleRate()*/, m_inputFrequencyOffset);
return true;
}
else if (MsgConfigureDATVDemod::match(cmd))
@ -919,6 +1303,14 @@ bool DATVDemod::handleMessage(const Message& cmd)
qDebug() << "DATVDemod::handleMessage: MsgConfigureDATVDemod";
applySettings(objCfg.getSettings(), objCfg.getForce());
return true;
}
else if(DSPSignalNotification::match(cmd))
{
m_sampleRate = m_channelizer->getInputSampleRate();
qDebug("DATVDemod::handleMessage: DSPSignalNotification: sent sample rate: %d", m_sampleRate);
applyChannelSettings(m_sampleRate /*objNotif.getSampleRate()*/, m_inputFrequencyOffset);
return true;
}
else
@ -937,21 +1329,25 @@ void DATVDemod::applyChannelSettings(int inputSampleRate, int inputFrequencyOffs
(m_sampleRate != inputSampleRate) || force)
{
m_objNCO.setFreq(-(float) inputFrequencyOffset, (float) inputSampleRate);
qDebug("DATVDemod::applyChannelSettings: NCO: IF: %d <> TF: %d ISR: %d",
inputFrequencyOffset, m_settings.m_centerFrequency, inputSampleRate);
}
if ((m_sampleRate != inputSampleRate) || force)
{
m_objSettingsMutex.lock();
//m_objSettingsMutex.lock();
//Bandpass filter shaping
Real fltLowCut = -((float) m_settings.m_rfBandwidth / 2.0) / (float) inputSampleRate;
Real fltHiCut = ((float) m_settings.m_rfBandwidth / 2.0) / (float) inputSampleRate;
m_objRFFilter->create_filter(fltLowCut, fltHiCut);
m_blnNeedConfigUpdate = true;
m_objSettingsMutex.unlock();
//m_blnNeedConfigUpdate = true;
//applySettings(m_settings,true);
//m_objSettingsMutex.unlock();
}
m_sampleRate = inputSampleRate;
m_settings.m_centerFrequency = inputFrequencyOffset;
applySettings(m_settings,true);
}
void DATVDemod::applySettings(const DATVDemodSettings& settings, bool force)
@ -959,6 +1355,8 @@ void DATVDemod::applySettings(const DATVDemodSettings& settings, bool force)
QString msg = tr("DATVDemod::applySettings: force: %1").arg(force);
settings.debug(msg);
qDebug("DATVDemod::applySettings: m_sampleRate: %d", m_sampleRate);
if (m_sampleRate == 0) {
return;
}
@ -998,7 +1396,7 @@ void DATVDemod::applySettings(const DATVDemodSettings& settings, bool force)
if (m_settings.isDifferent(settings) || force)
{
m_objSettingsMutex.lock();
//m_objSettingsMutex.lock();
if ((m_settings.m_rfBandwidth != settings.m_rfBandwidth)
|| force)
@ -1016,7 +1414,7 @@ void DATVDemod::applySettings(const DATVDemodSettings& settings, bool force)
m_objNCO.setFreq(-(float) settings.m_centerFrequency, (float) m_sampleRate);
}
m_objSettingsMutex.unlock();
//m_objSettingsMutex.unlock();
m_blnNeedConfigUpdate = true;
}

View File

@ -29,16 +29,14 @@ class DownChannelizer;
//LeanSDR
#include "leansdr/framework.h"
#include "leansdr/generic.h"
#include "leansdr/dsp.h"
#include "leansdr/sdr.h"
#include "leansdr/dvb.h"
#include "leansdr/rs.h"
#include "leansdr/filtergen.h"
#include "leansdr/hdlc.h"
#include "leansdr/iess.h"
#include "datvconstellation.h"
#include "datvdvbs2constellation.h"
#include "datvvideoplayer.h"
#include "datvideostream.h"
#include "datvideorender.h"
@ -185,6 +183,7 @@ public:
void CleanUpDATVFramework(bool blnRelease);
int GetSampleRate();
void InitDATVFramework();
void InitDATVS2Framework();
double getMagSq() const { return m_objMagSqAverage; } //!< Beware this is scaled to 2^30
static const QString m_channelIdURI;
@ -246,6 +245,13 @@ private:
unsigned long BUF_PACKETS;
unsigned long BUF_SLOW;
//dvbs2
unsigned long BUF_SLOTS;
unsigned long BUF_FRAMES;
unsigned long BUF_S2PACKETS;
unsigned long S2_MAX_SYMBOLS;
//************** LEANDBV Scheduler ***************
leansdr::scheduler * m_objScheduler;
@ -290,6 +296,18 @@ private:
leansdr::pipebuf<leansdr::f32> *p_mer;
leansdr::pipebuf<leansdr::cf32> *p_sampled;
//dvb-s2
void *p_slots_dvbs2;
leansdr::pipebuf<leansdr::cf32> *p_cstln;
leansdr::pipebuf<leansdr::cf32> *p_cstln_pls;
leansdr::pipebuf<int> *p_framelock;
void *m_objDemodulatorDVBS2;
void *p_fecframes;
void *p_bbframes;
void *p_s2_deinterleaver;
void *r_fecdec;
void *p_deframer;
//DECIMATION
leansdr::pipebuf<leansdr::cf32> *p_decimated;
leansdr::decimator<leansdr::cf32> *p_decim;
@ -341,6 +359,7 @@ private:
//CONSTELLATION
leansdr::datvconstellation<leansdr::f32> *r_scope_symbols;
leansdr::datvdvbs2constellation<leansdr::f32> *r_scope_symbols_dvbs2;
DeviceAPI* m_deviceAPI;
@ -368,6 +387,7 @@ private:
//DATVConfig m_objRunning;
DATVDemodSettings m_settings;
int m_sampleRate;
int m_inputFrequencyOffset;
MovingAverageUtil<double, double, 32> m_objMagSqAverage;
QMutex m_objSettingsMutex;

View File

@ -249,6 +249,8 @@ void DATVDemodGUI::applySettings(bool force)
if (m_blnDoApplySettings)
{
qDebug("DATVDemodGUI::applySettings");
//Bandwidth and center frequency
m_objChannelMarker.setCenterFrequency(ui->deltaFrequency->getValueNew());
m_objChannelMarker.setBandwidth(ui->rfBandwidth->getValueNew());
@ -440,6 +442,25 @@ void DATVDemodGUI::tick()
void DATVDemodGUI::on_cmbStandard_currentIndexChanged(const QString &arg1)
{
(void) arg1;
QString strStandard;
strStandard = ui->cmbStandard->currentText();
if(strStandard=="DVB-S2")
{
ui->cmbFEC->addItem("4/5");
ui->cmbFEC->addItem("4/6");
ui->cmbFEC->addItem("8/9");
ui->cmbFEC->addItem("9/10");
}
else
{
ui->cmbFEC->removeItem(8);
ui->cmbFEC->removeItem(7);
ui->cmbFEC->removeItem(6);
ui->cmbFEC->removeItem(5);
}
applySettings();
}

View File

@ -312,6 +312,11 @@
<string>DVB-S</string>
</property>
</item>
<item>
<property name="text">
<string>DVB-S2</string>
</property>
</item>
</widget>
<widget class="QComboBox" name="cmbModulation">
<property name="geometry">

View File

@ -28,7 +28,7 @@
const PluginDescriptor DATVDemodPlugin::m_ptrPluginDescriptor =
{
QString("DATV Demodulator"),
QString("4.5.1"),
QString("4.11.1"),
QString("(c) F4HKW for SDRAngel using LeanSDR framework (c) F4DAV"),
QString("https://github.com/f4exb/sdrangel"),
true,

View File

@ -156,6 +156,7 @@ bool DATVDemodSettings::deserialize(const QByteArray& data)
void DATVDemodSettings::debug(const QString& msg) const
{
qDebug() << msg
<< " m_standard: " << m_standard
<< " m_allowDrift: " << m_allowDrift
<< " m_rfBandwidth: " << m_rfBandwidth
<< " m_centerFrequency: " << m_centerFrequency
@ -191,5 +192,6 @@ bool DATVDemodSettings::isDifferent(const DATVDemodSettings& other)
|| (m_standard != other.m_standard)
|| (m_notchFilters != other.m_notchFilters)
|| (m_symbolRate != other.m_symbolRate)
|| (m_excursion != other.m_excursion));
|| (m_excursion != other.m_excursion)
|| (m_standard != other.m_standard));
}

View File

@ -0,0 +1,219 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 F4HKW //
// for F4EXB / SDRAngel //
// using LeanSDR Framework (C) 2016 F4DAV //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef DATVDVBS2CONSTELLATION_H
#define DATVDVBS2CONSTELLATION_H
#include <vector>
#include "leansdr/framework.h"
#include "gui/tvscreen.h"
namespace leansdr {
static const int DEFAULT_GUI_DVBS2_DECIMATION = 64;
static inline cstln_lut<llr_ss, 256> * make_dvbs2_constellation(cstln_lut<llr_ss, 256>::predef c,
code_rate r)
{
float gamma1 = 1, gamma2 = 1, gamma3 = 1;
switch (c)
{
case cstln_lut<llr_ss, 256>::APSK16:
// EN 302 307, section 5.4.3, Table 9
switch (r)
{
case FEC23:
case FEC46:
gamma1 = 3.15;
break;
case FEC34:
gamma1 = 2.85;
break;
case FEC45:
gamma1 = 2.75;
break;
case FEC56:
gamma1 = 2.70;
break;
case FEC89:
gamma1 = 2.60;
break;
case FEC910:
gamma1 = 2.57;
break;
default:
fail("cstln_lut<256>::make_dvbs2_constellation: Code rate not supported with APSK16");
return 0;
}
break;
case cstln_lut<llr_ss, 256>::APSK32:
// EN 302 307, section 5.4.4, Table 10
switch (r)
{
case FEC34:
gamma1 = 2.84;
gamma2 = 5.27;
break;
case FEC45:
gamma1 = 2.72;
gamma2 = 4.87;
break;
case FEC56:
gamma1 = 2.64;
gamma2 = 4.64;
break;
case FEC89:
gamma1 = 2.54;
gamma2 = 4.33;
break;
case FEC910:
gamma1 = 2.53;
gamma2 = 4.30;
break;
default:
fail("cstln_lut<llr_ss, 256>::make_dvbs2_constellation: Code rate not supported with APSK32");
return 0;
}
break;
case cstln_lut<llr_ss, 256>::APSK64E:
// EN 302 307-2, section 5.4.5, Table 13f
gamma1 = 2.4;
gamma2 = 4.3;
gamma3 = 7;
break;
default:
break;
}
return new cstln_lut<llr_ss, 256>(c, gamma1, gamma2, gamma3);
}
template<typename T> struct datvdvbs2constellation: runnable
{
T xymin, xymax;
unsigned long decimation;
long pixels_per_frame;
/*cstln_lut<llr_ss, 256>*/ cstln_base **cstln; // Optional ptr to optional constellation
TVScreen *m_objDATVScreen;
pipereader<complex<T> > in;
unsigned long phase;
std::vector<int> cstln_rows;
std::vector<int> cstln_cols;
datvdvbs2constellation(
scheduler *sch,
pipebuf<complex<T> > &_in,
T _xymin,
T _xymax,
const char *_name = nullptr,
TVScreen *objDATVScreen = nullptr) :
runnable(sch, _name ? _name : _in.name),
xymin(_xymin),
xymax(_xymax),
decimation(DEFAULT_GUI_DVBS2_DECIMATION),
pixels_per_frame(1024),
cstln(0),
m_objDATVScreen(objDATVScreen),
in(_in),
phase(0)
{
}
void run()
{
phase=0;
//Symbols
while (in.readable() >= pixels_per_frame)
{
if ((!phase) && m_objDATVScreen)
{
m_objDATVScreen->resetImage();
complex<T> *p = in.rd(), *pend = p + pixels_per_frame;
for (; p < pend; ++p)
{
m_objDATVScreen->selectRow(256 * (p->re - xymin) / (xymax - xymin));
m_objDATVScreen->setDataColor(
256 - 256 * ((p->im - xymin) / (xymax - xymin)),
255, 0, 255);
}
if (cstln && (*cstln))
{
// Plot constellation points
std::vector<int>::const_iterator row_it = cstln_rows.begin();
std::vector<int>::const_iterator col_it = cstln_cols.begin();
for (;(row_it != cstln_rows.end()) && (col_it != cstln_cols.end()); ++row_it, ++col_it)
{
m_objDATVScreen->selectRow(*row_it);
m_objDATVScreen->setDataColor(*col_it, 250, 250, 250);
}
}
m_objDATVScreen->renderImage(0);
}
in.read(pixels_per_frame);
if (++phase >= decimation) {
phase = 0;
}
}
}
void draw_begin()
{
}
void calculate_cstln_points()
{
if (!(*cstln)) {
return;
}
cstln_rows.clear();
cstln_cols.clear();
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)
{
cstln_rows.push_back(x + d);
cstln_cols.push_back(y);
cstln_rows.push_back(x);
cstln_cols.push_back(y + d);
}
}
}
};
} // leansdr
#endif // DATVDVBS2CONSTELLATION_H

View File

@ -17,12 +17,23 @@
#ifndef LEANSDR_DVBS2_H
#define LEANSDR_DVBS2_H
/*
#include "leansdr/bch.h"
#include "leansdr/crc.h"
#include "leansdr/dvb.h"
#include "leansdr/ldpc.h"
#include "leansdr/sdr.h"
#include "leansdr/softword.h"
*/
#include "bch.h"
#include "crc.h"
#include "dvb.h"
#include "softword.h"
#include "ldpc.h"
#include "sdr.h"
namespace leansdr
{
@ -819,7 +830,7 @@ struct s2_frame_receiver : runnable
// Slots to skip until next PL slot (pilot or sof)
int till_next_pls = pls.pilots ? 16 : S;
for (int slots = S; slots--; ++pout, --till_next_pls)
for (int leansdr_slots = S; leansdr_slots--; ++pout, --till_next_pls)
{
if (till_next_pls == 0)
{