diff --git a/plugins/channelrx/demoddatv/CMakeLists.txt b/plugins/channelrx/demoddatv/CMakeLists.txt index edf1815f9..a07395de0 100644 --- a/plugins/channelrx/demoddatv/CMakeLists.txt +++ b/plugins/channelrx/demoddatv/CMakeLists.txt @@ -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 diff --git a/plugins/channelrx/demoddatv/datvconstellation.h b/plugins/channelrx/demoddatv/datvconstellation.h index c88247d98..71234218d 100644 --- a/plugins/channelrx/demoddatv/datvconstellation.h +++ b/plugins/channelrx/demoddatv/datvconstellation.h @@ -29,7 +29,7 @@ namespace leansdr { static const int DEFAULT_GUI_DECIMATION = 64; -static inline cstln_lut * make_dvbs2_constellation(cstln_lut::predef c, +static inline cstln_lut * make_dvbs_constellation(cstln_lut::predef c, code_rate r) { float gamma1 = 1, gamma2 = 1, gamma3 = 1; @@ -59,7 +59,7 @@ static inline cstln_lut * make_dvbs2_constellation(cstln_lut::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 * make_dvbs2_constellation(cstln_lut::make_dvbs2_constellation: Code rate not supported with APSK32"); + fail("cstln_lut::make_dvbs_constellation: Code rate not supported with APSK32"); return 0; } break; diff --git a/plugins/channelrx/demoddatv/datvdemod.cpp b/plugins/channelrx/demoddatv/datvdemod.cpp index 13e7be2a8..e3fe80302 100644 --- a/plugins/channelrx/demoddatv/datvdemod.cpp +++ b/plugins/channelrx/demoddatv/datvdemod.cpp @@ -19,6 +19,8 @@ #include "datvdemod.h" +#include "leansdr/dvbs2.h" + #include #include #include @@ -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 >*) 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*) m_objDemodulatorDVBS2; + } + + if(p_fecframes != nullptr) + { + delete (leansdr::pipebuf< leansdr::fecframe >*) p_fecframes; + } + + if(p_bbframes != nullptr) + { + delete (leansdr::pipebuf*) p_bbframes; + } + + if(p_s2_deinterleaver != nullptr) + { + delete (leansdr::s2_deinterleaver*) p_s2_deinterleaver; + } + + if(r_fecdec != nullptr) + { + delete (leansdr::s2_fecdec*) 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(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 * 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::BPSK; + break; + case DATVDemodSettings::QPSK: + m_objCfg.constellation = leansdr::cstln_lut::QPSK; + break; + case DATVDemodSettings::PSK8: + m_objCfg.constellation = leansdr::cstln_lut::PSK8; + break; + case DATVDemodSettings::APSK16: + m_objCfg.constellation = leansdr::cstln_lut::APSK16; + break; + case DATVDemodSettings::APSK32: + m_objCfg.constellation = leansdr::cstln_lut::APSK32; + break; + case DATVDemodSettings::APSK64E: + m_objCfg.constellation = leansdr::cstln_lut::APSK64E; + break; + case DATVDemodSettings::QAM16: + m_objCfg.constellation = leansdr::cstln_lut::QAM16; + break; + case DATVDemodSettings::QAM64: + m_objCfg.constellation = leansdr::cstln_lut::QAM64; + break; + case DATVDemodSettings::QAM256: + m_objCfg.constellation = leansdr::cstln_lut::QAM256; + break; + default: + m_objCfg.constellation = leansdr::cstln_lut::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(m_objScheduler, "rawiq", BUF_BASEBAND); + p_rawiq_writer = new leansdr::pipewriter(*p_rawiq); + p_preprocessed = p_rawiq; + + // NOTCH FILTER + + if (m_objCfg.anf>0) + { + p_autonotched = new leansdr::pipebuf(m_objScheduler, "autonotched", BUF_BASEBAND); + r_auto_notch = new leansdr::auto_notch(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(m_objScheduler, "cnr", BUF_SLOW); + + if (m_objCfg.cnr == true) + { + r_cnr = new leansdr::cnr_fft(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 (m_objScheduler, "freq", BUF_SLOW); + p_ss = new leansdr::pipebuf (m_objScheduler, "SS", BUF_SLOW); + p_mer = new leansdr::pipebuf (m_objScheduler, "MER", BUF_SLOW); + + switch (m_objCfg.sampler) + { + case DATVDemodSettings::SAMP_NEAREST: + sampler = new leansdr::nearest_sampler(); + break; + case DATVDemodSettings::SAMP_LINEAR: + sampler = new leansdr::linear_sampler(); + 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(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 > (m_objScheduler, "PL slots", BUF_SLOTS); + + p_cstln = new leansdr::pipebuf(m_objScheduler, "cstln", BUF_BASEBAND); + p_cstln_pls = new leansdr::pipebuf(m_objScheduler, "PLS cstln", BUF_BASEBAND); + p_framelock = new leansdr::pipebuf(m_objScheduler, "frame lock", BUF_SLOW); + + m_objDemodulatorDVBS2 = new leansdr::s2_frame_receiver( + m_objScheduler, + sampler, + *p_preprocessed, + *(leansdr::pipebuf< leansdr::plslot > *) 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 *) 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(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(m_objScheduler, "BB frames", BUF_FRAMES); + + p_fecframes = new leansdr::pipebuf< leansdr::fecframe >(m_objScheduler, "FEC frames", BUF_FRAMES); + + p_s2_deinterleaver = new leansdr::s2_deinterleaver( + m_objScheduler, + *(leansdr::pipebuf< leansdr::plslot > *) p_slots_dvbs2, + *(leansdr::pipebuf< leansdr::fecframe > * ) p_fecframes + ); + + p_vbitcount= new leansdr::pipebuf(m_objScheduler, "Bits processed", BUF_S2PACKETS); + p_verrcount = new leansdr::pipebuf(m_objScheduler, "Bits corrected", BUF_S2PACKETS); + + r_fecdec = new leansdr::s2_fecdec( + m_objScheduler, *(leansdr::pipebuf< leansdr::fecframe > * ) p_fecframes, + *(leansdr::pipebuf *) p_bbframes, + p_vbitcount, + p_verrcount + ); + leansdr::s2_fecdec *fecdec = (leansdr::s2_fecdec * ) 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 (m_objScheduler, "lock", BUF_SLOW); + p_locktime = new leansdr::pipebuf (m_objScheduler, "locktime", BUF_S2PACKETS); + p_tspackets = new leansdr::pipebuf(m_objScheduler, "TS packets", BUF_S2PACKETS); + + p_deframer = new leansdr::s2_deframer(m_objScheduler,*(leansdr::pipebuf *) 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(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; - InitDATVFramework(); + + 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(*p_rawiq); + //delete p_rawiq_writer; + //p_rawiq_writer = new leansdr::pipewriter(*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)) @@ -921,6 +1305,14 @@ bool DATVDemod::handleMessage(const Message& cmd) 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 { return false; @@ -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; } diff --git a/plugins/channelrx/demoddatv/datvdemod.h b/plugins/channelrx/demoddatv/datvdemod.h index fa07d30db..0046a9a3b 100644 --- a/plugins/channelrx/demoddatv/datvdemod.h +++ b/plugins/channelrx/demoddatv/datvdemod.h @@ -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 *p_mer; leansdr::pipebuf *p_sampled; + //dvb-s2 + void *p_slots_dvbs2; + leansdr::pipebuf *p_cstln; + leansdr::pipebuf *p_cstln_pls; + leansdr::pipebuf *p_framelock; + void *m_objDemodulatorDVBS2; + void *p_fecframes; + void *p_bbframes; + void *p_s2_deinterleaver; + void *r_fecdec; + void *p_deframer; + //DECIMATION leansdr::pipebuf *p_decimated; leansdr::decimator *p_decim; @@ -341,6 +359,7 @@ private: //CONSTELLATION leansdr::datvconstellation *r_scope_symbols; + leansdr::datvdvbs2constellation *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 m_objMagSqAverage; QMutex m_objSettingsMutex; diff --git a/plugins/channelrx/demoddatv/datvdemodgui.cpp b/plugins/channelrx/demoddatv/datvdemodgui.cpp index 4be864b8b..8e535ac4d 100644 --- a/plugins/channelrx/demoddatv/datvdemodgui.cpp +++ b/plugins/channelrx/demoddatv/datvdemodgui.cpp @@ -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(); } diff --git a/plugins/channelrx/demoddatv/datvdemodgui.ui b/plugins/channelrx/demoddatv/datvdemodgui.ui index aeae3436a..60bcbbf45 100644 --- a/plugins/channelrx/demoddatv/datvdemodgui.ui +++ b/plugins/channelrx/demoddatv/datvdemodgui.ui @@ -312,6 +312,11 @@ DVB-S + + + DVB-S2 + + diff --git a/plugins/channelrx/demoddatv/datvdemodplugin.cpp b/plugins/channelrx/demoddatv/datvdemodplugin.cpp index f752d3c25..b43f6a286 100644 --- a/plugins/channelrx/demoddatv/datvdemodplugin.cpp +++ b/plugins/channelrx/demoddatv/datvdemodplugin.cpp @@ -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, diff --git a/plugins/channelrx/demoddatv/datvdemodsettings.cpp b/plugins/channelrx/demoddatv/datvdemodsettings.cpp index 43e04c2aa..e4a36039a 100644 --- a/plugins/channelrx/demoddatv/datvdemodsettings.cpp +++ b/plugins/channelrx/demoddatv/datvdemodsettings.cpp @@ -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)); } \ No newline at end of file diff --git a/plugins/channelrx/demoddatv/datvdvbs2constellation.h b/plugins/channelrx/demoddatv/datvdvbs2constellation.h new file mode 100644 index 000000000..ff8b6795a --- /dev/null +++ b/plugins/channelrx/demoddatv/datvdvbs2constellation.h @@ -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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef DATVDVBS2CONSTELLATION_H +#define DATVDVBS2CONSTELLATION_H + +#include + +#include "leansdr/framework.h" +#include "gui/tvscreen.h" + +namespace leansdr { + +static const int DEFAULT_GUI_DVBS2_DECIMATION = 64; + +static inline cstln_lut * make_dvbs2_constellation(cstln_lut::predef c, + code_rate r) +{ + float gamma1 = 1, gamma2 = 1, gamma3 = 1; + + + switch (c) + { + case cstln_lut::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::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::make_dvbs2_constellation: Code rate not supported with APSK32"); + return 0; + } + break; + case cstln_lut::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(c, gamma1, gamma2, gamma3); +} + +template struct datvdvbs2constellation: runnable +{ + T xymin, xymax; + unsigned long decimation; + long pixels_per_frame; + /*cstln_lut*/ cstln_base **cstln; // Optional ptr to optional constellation + TVScreen *m_objDATVScreen; + pipereader > in; + unsigned long phase; + std::vector cstln_rows; + std::vector cstln_cols; + + datvdvbs2constellation( + scheduler *sch, + pipebuf > &_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 *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::const_iterator row_it = cstln_rows.begin(); + std::vector::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 *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 diff --git a/plugins/channelrx/demoddatv/leansdr/dvbs2.h b/plugins/channelrx/demoddatv/leansdr/dvbs2.h index c8d0a3e5e..034d47ff6 100644 --- a/plugins/channelrx/demoddatv/leansdr/dvbs2.h +++ b/plugins/channelrx/demoddatv/leansdr/dvbs2.h @@ -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) {