1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-08-24 08:22:28 -04:00

DATV demod: make sure that when baseband rate changes the channelizer is reconfigured to get all available bandwidth

This commit is contained in:
f4exb 2018-02-25 03:22:30 +01:00
parent 916a284b48
commit e53da4e9a8
3 changed files with 320 additions and 325 deletions

View File

@ -29,7 +29,6 @@
#include "dsp/threadedbasebandsamplesink.h" #include "dsp/threadedbasebandsamplesink.h"
#include "device/devicesourceapi.h" #include "device/devicesourceapi.h"
const QString DATVDemod::m_channelIdURI = "sdrangel.channel.demoddatv"; const QString DATVDemod::m_channelIdURI = "sdrangel.channel.demoddatv";
const QString DATVDemod::m_channelId = "DATVDemod"; const QString DATVDemod::m_channelId = "DATVDemod";
@ -40,10 +39,10 @@ DATVDemod::DATVDemod(DeviceSourceAPI *deviceAPI) :
ChannelSinkAPI(m_channelIdURI), ChannelSinkAPI(m_channelIdURI),
m_blnNeedConfigUpdate(false), m_blnNeedConfigUpdate(false),
m_deviceAPI(deviceAPI), m_deviceAPI(deviceAPI),
m_objRegisteredDATVScreen(NULL), m_objRegisteredDATVScreen(0),
m_objRegisteredVideoRender(NULL), m_objRegisteredVideoRender(0),
m_objVideoStream(NULL), m_objVideoStream(0),
m_objRenderThread(NULL), m_objRenderThread(0),
m_blnRenderingVideo(false), m_blnRenderingVideo(false),
m_enmModulation(BPSK /*DATV_FM1*/), m_enmModulation(BPSK /*DATV_FM1*/),
m_objSettingsMutex(QMutex::NonRecursive) m_objSettingsMutex(QMutex::NonRecursive)
@ -52,7 +51,7 @@ DATVDemod::DATVDemod(DeviceSourceAPI *deviceAPI) :
qDebug("DATVDemod::DATVDemod: sizeof FixReal: %lu: SDR_RX_SAMP_SZ: %u", sizeof(FixReal), (unsigned int) SDR_RX_SAMP_SZ); qDebug("DATVDemod::DATVDemod: sizeof FixReal: %lu: SDR_RX_SAMP_SZ: %u", sizeof(FixReal), (unsigned int) SDR_RX_SAMP_SZ);
//*************** DATV PARAMETERS *************** //*************** DATV PARAMETERS ***************
m_blnInitialized=false; m_blnInitialized = false;
CleanUpDATVFramework(); CleanUpDATVFramework();
m_objVideoStream = new DATVideostream(); m_objVideoStream = new DATVideostream();
@ -65,17 +64,15 @@ DATVDemod::DATVDemod(DeviceSourceAPI *deviceAPI) :
m_deviceAPI->addChannelAPI(this); m_deviceAPI->addChannelAPI(this);
connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelSampleRateChanged())); connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelSampleRateChanged()));
} }
DATVDemod::~DATVDemod() DATVDemod::~DATVDemod()
{ {
m_blnInitialized=false; m_blnInitialized = false;
if (m_objRenderThread != NULL)
if(m_objRenderThread!=NULL)
{ {
if(m_objRenderThread->isRunning()) if (m_objRenderThread->isRunning())
{ {
m_objRenderThread->stopRendering(); m_objRenderThread->stopRendering();
} }
@ -83,12 +80,12 @@ DATVDemod::~DATVDemod()
//CleanUpDATVFramework(true); //CleanUpDATVFramework(true);
if(m_objRFFilter!=NULL) if (m_objRFFilter != NULL)
{ {
//delete m_objRFFilter; //delete m_objRFFilter;
} }
if(m_objVideoStream!=NULL) if (m_objVideoStream != NULL)
{ {
//m_objVideoStream->close(); //m_objVideoStream->close();
//delete m_objVideoStream; //delete m_objVideoStream;
@ -110,33 +107,32 @@ DATVideostream * DATVDemod::SetVideoRender(DATVideoRender *objScreen)
{ {
m_objRegisteredVideoRender = objScreen; m_objRegisteredVideoRender = objScreen;
m_objRenderThread = new DATVideoRenderThread(m_objRegisteredVideoRender,m_objVideoStream); m_objRenderThread = new DATVideoRenderThread(m_objRegisteredVideoRender, m_objVideoStream);
return m_objVideoStream; return m_objVideoStream;
} }
bool DATVDemod::PlayVideo(bool blnStartStop) bool DATVDemod::PlayVideo(bool blnStartStop)
{ {
if(m_objVideoStream==NULL) if (m_objVideoStream == NULL)
{ {
return false; return false;
} }
if(m_objRegisteredVideoRender==NULL) if (m_objRegisteredVideoRender == NULL)
{ {
return false; return false;
} }
if(m_objRenderThread==NULL) if (m_objRenderThread == NULL)
{ {
return false; return false;
} }
if(m_objRenderThread->isRunning()) if (m_objRenderThread->isRunning())
{ {
if(blnStartStop==true) if (blnStartStop == true)
{ {
m_objRenderThread->stopRendering(); m_objRenderThread->stopRendering();
} }
@ -144,8 +140,8 @@ bool DATVDemod::PlayVideo(bool blnStartStop)
return true; return true;
} }
m_objRenderThread->setStreamAndRenderer(m_objRegisteredVideoRender,m_objVideoStream); m_objRenderThread->setStreamAndRenderer(m_objRegisteredVideoRender, m_objVideoStream);
m_objVideoStream->MultiThreaded=true; m_objVideoStream->MultiThreaded = true;
m_objRenderThread->start(); m_objRenderThread->start();
//m_objVideoStream->MultiThreaded=false; //m_objVideoStream->MultiThreaded=false;
@ -154,7 +150,8 @@ bool DATVDemod::PlayVideo(bool blnStartStop)
return true; return true;
} }
void DATVDemod::configure(MessageQueue* objMessageQueue, void DATVDemod::configure(
MessageQueue* objMessageQueue,
int intRFBandwidth, int intRFBandwidth,
int intCenterFrequency, int intCenterFrequency,
dvb_version enmStandard, dvb_version enmStandard,
@ -169,11 +166,25 @@ void DATVDemod::configure(MessageQueue* objMessageQueue,
bool blnResample, bool blnResample,
bool blnViterbi) bool blnViterbi)
{ {
Message* msgCmd = MsgConfigureDATVDemod::create(intRFBandwidth,intCenterFrequency,enmStandard, enmModulation, enmFEC, intSymbolRate, intNotchFilters, blnAllowDrift,blnFastLock,blnHDLC,blnHardMetric,blnResample, blnViterbi); Message* msgCmd = MsgConfigureDATVDemod::create(
intRFBandwidth,
intCenterFrequency,
enmStandard,
enmModulation,
enmFEC,
intSymbolRate,
intNotchFilters,
blnAllowDrift,
blnFastLock,
blnHDLC,
blnHardMetric,
blnResample,
blnViterbi);
objMessageQueue->push(msgCmd); objMessageQueue->push(msgCmd);
} }
void DATVDemod::InitDATVParameters(int intMsps, void DATVDemod::InitDATVParameters(
int intMsps,
int intRFBandwidth, int intRFBandwidth,
int intCenterFrequency, int intCenterFrequency,
dvb_version enmStandard, dvb_version enmStandard,
@ -192,16 +203,16 @@ void DATVDemod::InitDATVParameters(int intMsps,
Real fltLowCut; Real fltLowCut;
Real fltHiCut; Real fltHiCut;
m_blnInitialized=false; m_blnInitialized = false;
m_objSettingsMutex.lock(); m_objSettingsMutex.lock();
//Recalibrage du filtre passe bande //Recalibrage du filtre passe bande
fltLowCut = -((float)intRFBandwidth / 2.0) / (float)intMsps; fltLowCut = -((float) intRFBandwidth / 2.0) / (float) intMsps;
fltHiCut = ((float)intRFBandwidth / 2.0) / (float)intMsps; fltHiCut = ((float) intRFBandwidth / 2.0) / (float) intMsps;
m_objRFFilter->create_filter(fltLowCut, fltHiCut); m_objRFFilter->create_filter(fltLowCut, fltHiCut);
m_objNCO.setFreq(-(float)intCenterFrequency,(float)intMsps); m_objNCO.setFreq(-(float) intCenterFrequency, (float) intMsps);
//Mise à jour de la config //Mise à jour de la config
@ -234,12 +245,11 @@ void DATVDemod::InitDATVParameters(int intMsps,
<< " - Resample: " << blnResample << " - Resample: " << blnResample
<< " - Viterbi: " << blnViterbi; << " - Viterbi: " << blnViterbi;
m_objSettingsMutex.unlock(); m_objSettingsMutex.unlock();
m_blnNeedConfigUpdate=true; m_blnNeedConfigUpdate = true;
m_blnInitialized=true; m_blnInitialized = true;
} }
void DATVDemod::CleanUpDATVFramework() void DATVDemod::CleanUpDATVFramework()
@ -393,7 +403,6 @@ void DATVDemod::CleanUpDATVFramework()
p_locktime = 0; p_locktime = 0;
r_sync_mpeg = 0; r_sync_mpeg = 0;
// DEINTERLEAVING // DEINTERLEAVING
p_rspackets = 0; p_rspackets = 0;
r_deinter = 0; r_deinter = 0;
@ -403,30 +412,26 @@ void DATVDemod::CleanUpDATVFramework()
p_rtspackets = 0; p_rtspackets = 0;
r_rsdec = 0; r_rsdec = 0;
//BER ESTIMATION //BER ESTIMATION
p_vber = 0; p_vber = 0;
r_vber = 0; r_vber = 0;
// DERANDOMIZATION // DERANDOMIZATION
p_tspackets = 0; p_tspackets = 0;
r_derand = 0; r_derand = 0;
//OUTPUT : To remove //OUTPUT : To remove
r_stdout = 0; r_stdout = 0;
r_videoplayer = 0; r_videoplayer = 0;
//CONSTELLATION //CONSTELLATION
r_scope_symbols = 0; r_scope_symbols = 0;
} }
void DATVDemod::InitDATVFramework() void DATVDemod::InitDATVFramework()
{ {
m_blnDVBInitialized=false; m_blnDVBInitialized = false;
m_lngReadIQ=0; m_lngReadIQ = 0;
m_objCfg.standard = m_objRunning.enmStandard; m_objCfg.standard = m_objRunning.enmStandard;
@ -435,7 +440,7 @@ void DATVDemod::InitDATVFramework()
m_objCfg.Fm = (float) m_objRunning.intSymbolRate; m_objCfg.Fm = (float) m_objRunning.intSymbolRate;
m_objCfg.fastlock = m_objRunning.blnFastLock; m_objCfg.fastlock = m_objRunning.blnFastLock;
switch(m_objRunning.enmModulation) switch (m_objRunning.enmModulation)
{ {
case BPSK: case BPSK:
m_objCfg.constellation = cstln_lut<256>::BPSK; m_objCfg.constellation = cstln_lut<256>::BPSK;
@ -485,7 +490,6 @@ void DATVDemod::InitDATVFramework()
m_objCfg.resample = m_objRunning.blnResample; m_objCfg.resample = m_objRunning.blnResample;
m_objCfg.viterbi = m_objRunning.blnViterbi; m_objCfg.viterbi = m_objRunning.blnViterbi;
// Min buffer size for baseband data // Min buffer size for baseband data
// scopes: 1024 // scopes: 1024
// ss_estimator: 1024 // ss_estimator: 1024
@ -517,7 +521,6 @@ void DATVDemod::InitDATVFramework()
m_lngExpectedReadIQ = BUF_BASEBAND; m_lngExpectedReadIQ = BUF_BASEBAND;
CleanUpDATVFramework(); CleanUpDATVFramework();
m_objScheduler = new scheduler(); m_objScheduler = new scheduler();
@ -529,20 +532,19 @@ void DATVDemod::InitDATVFramework()
// NOTCH FILTER // NOTCH FILTER
if ( m_objCfg.anf ) if (m_objCfg.anf)
{ {
p_autonotched = new pipebuf<cf32>(m_objScheduler, "autonotched", BUF_BASEBAND); p_autonotched = new pipebuf<cf32>(m_objScheduler, "autonotched", BUF_BASEBAND);
r_auto_notch = new auto_notch<f32>(m_objScheduler, *p_preprocessed, *p_autonotched, m_objCfg.anf, 0); r_auto_notch = new auto_notch<f32>(m_objScheduler, *p_preprocessed, *p_autonotched, m_objCfg.anf, 0);
p_preprocessed = p_autonotched; p_preprocessed = p_autonotched;
} }
// FREQUENCY CORRECTION // FREQUENCY CORRECTION
if ( m_objCfg.Fderot ) if (m_objCfg.Fderot)
{ {
p_derot = new pipebuf<cf32>(m_objScheduler, "derotated", BUF_BASEBAND); p_derot = new pipebuf<cf32>(m_objScheduler, "derotated", BUF_BASEBAND);
r_derot = new rotator<f32>(m_objScheduler, *p_preprocessed, *p_derot, -m_objCfg.Fderot/m_objCfg.Fs); r_derot = new rotator<f32>(m_objScheduler, *p_preprocessed, *p_derot, -m_objCfg.Fderot / m_objCfg.Fs);
p_preprocessed = p_derot; p_preprocessed = p_derot;
} }
@ -550,9 +552,9 @@ void DATVDemod::InitDATVFramework()
p_cnr = new pipebuf<f32>(m_objScheduler, "cnr", BUF_SLOW); p_cnr = new pipebuf<f32>(m_objScheduler, "cnr", BUF_SLOW);
if ( m_objCfg.cnr ) if (m_objCfg.cnr)
{ {
r_cnr = new cnr_fft<f32>(m_objScheduler, *p_preprocessed, *p_cnr, m_objCfg.Fm/m_objCfg.Fs); r_cnr = new cnr_fft<f32>(m_objScheduler, *p_preprocessed, *p_cnr, m_objCfg.Fm / m_objCfg.Fs);
r_cnr->decimation = decimation(m_objCfg.Fs, 1); // 1 Hz r_cnr->decimation = decimation(m_objCfg.Fs, 1); // 1 Hz
} }
@ -560,10 +562,10 @@ void DATVDemod::InitDATVFramework()
int decim = 1; int decim = 1;
if ( m_objCfg.resample ) if (m_objCfg.resample)
{ {
// Lowpass-filter and decimate. // Lowpass-filter and decimate.
if ( m_objCfg.decim ) if (m_objCfg.decim)
{ {
decim = m_objCfg.decim; decim = m_objCfg.decim;
} }
@ -572,30 +574,29 @@ void DATVDemod::InitDATVFramework()
// Decimate to just above 4 samples per symbol // Decimate to just above 4 samples per symbol
float target_Fs = m_objCfg.Fm * 4; float target_Fs = m_objCfg.Fm * 4;
decim = m_objCfg.Fs / target_Fs; decim = m_objCfg.Fs / target_Fs;
if ( decim < 1 ) if (decim < 1)
{ {
decim = 1; decim = 1;
} }
} }
float transition = (m_objCfg.Fm/2) * m_objCfg.rolloff; float transition = (m_objCfg.Fm / 2) * m_objCfg.rolloff;
int order = m_objCfg.resample_rej * m_objCfg.Fs / (22*transition); int order = m_objCfg.resample_rej * m_objCfg.Fs / (22 * transition);
order = ((order+1)/2) * 2; // Make even order = ((order + 1) / 2) * 2; // Make even
p_resampled = new pipebuf<cf32>(m_objScheduler, "resampled", BUF_BASEBAND); p_resampled = new pipebuf<cf32>(m_objScheduler, "resampled", BUF_BASEBAND);
#if 1 // Cut in middle of roll-off region
#if 1 // Cut in middle of roll-off region float Fcut = (m_objCfg.Fm / 2) * (1 + m_objCfg.rolloff / 2) / m_objCfg.Fs;
float Fcut = (m_objCfg.Fm/2) * (1+m_objCfg.rolloff/2) / m_objCfg.Fs; #else // Cut at beginning of roll-off region
#else // Cut at beginning of roll-off region
float Fcut = (m_objCfg.Fm/2) / cfg.Fs; float Fcut = (m_objCfg.Fm/2) / cfg.Fs;
#endif #endif
ncoeffs = filtergen::lowpass(order, Fcut, &coeffs); ncoeffs = filtergen::lowpass(order, Fcut, &coeffs);
filtergen::normalize_dcgain(ncoeffs, coeffs, 1); filtergen::normalize_dcgain(ncoeffs, coeffs, 1);
r_resample = new fir_filter<cf32,float>(m_objScheduler, ncoeffs, coeffs, *p_preprocessed, *p_resampled, decim); r_resample = new fir_filter<cf32, float>(m_objScheduler, ncoeffs, coeffs, *p_preprocessed, *p_resampled, decim);
p_preprocessed = p_resampled; p_preprocessed = p_resampled;
m_objCfg.Fs /= decim; m_objCfg.Fs /= decim;
} }
@ -603,7 +604,7 @@ void DATVDemod::InitDATVFramework()
// DECIMATION // DECIMATION
// (Unless already done in resampler) // (Unless already done in resampler)
if ( !m_objCfg.resample && m_objCfg.decim>1 ) if (!m_objCfg.resample && m_objCfg.decim > 1)
{ {
decim = m_objCfg.decim; decim = m_objCfg.decim;
@ -615,16 +616,15 @@ void DATVDemod::InitDATVFramework()
//Resampling FS //Resampling FS
// Generic constellation receiver // Generic constellation receiver
p_symbols = new pipebuf<softsymbol>(m_objScheduler, "PSK soft-symbols", BUF_SYMBOLS); p_symbols = new pipebuf<softsymbol>(m_objScheduler, "PSK soft-symbols", BUF_SYMBOLS);
p_freq = new pipebuf<f32> (m_objScheduler, "freq", BUF_SLOW); p_freq = new pipebuf<f32>(m_objScheduler, "freq", BUF_SLOW);
p_ss = new pipebuf<f32> (m_objScheduler, "SS", BUF_SLOW); p_ss = new pipebuf<f32>(m_objScheduler, "SS", BUF_SLOW);
p_mer = new pipebuf<f32> (m_objScheduler, "MER", BUF_SLOW); p_mer = new pipebuf<f32>(m_objScheduler, "MER", BUF_SLOW);
p_sampled = new pipebuf<cf32> (m_objScheduler, "PSK symbols", BUF_BASEBAND); p_sampled = new pipebuf<cf32>(m_objScheduler, "PSK symbols", BUF_BASEBAND);
switch ( m_objCfg.sampler ) switch (m_objCfg.sampler)
{ {
case SAMP_NEAREST: case SAMP_NEAREST:
sampler = new nearest_sampler<float>(); sampler = new nearest_sampler<float>();
@ -637,19 +637,18 @@ void DATVDemod::InitDATVFramework()
case SAMP_RRC: case SAMP_RRC:
{ {
if (m_objCfg.rrc_steps == 0)
if ( m_objCfg.rrc_steps == 0 )
{ {
// At least 64 discrete sampling points between symbols // At least 64 discrete sampling points between symbols
m_objCfg.rrc_steps = max(1, (int)(64*m_objCfg.Fm / m_objCfg.Fs)); m_objCfg.rrc_steps = 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 Frrc = m_objCfg.Fs * m_objCfg.rrc_steps; // Sample freq of the RRC filter
float transition = (m_objCfg.Fm/2) * m_objCfg.rolloff; float transition = (m_objCfg.Fm / 2) * m_objCfg.rolloff;
int order = m_objCfg.rrc_rej * Frrc / (22*transition); int order = m_objCfg.rrc_rej * Frrc / (22 * transition);
ncoeffs_sampler = filtergen::root_raised_cosine(order, m_objCfg.Fm/Frrc, m_objCfg.rolloff, &coeffs_sampler); ncoeffs_sampler = filtergen::root_raised_cosine(order, m_objCfg.Fm / Frrc, m_objCfg.rolloff, &coeffs_sampler);
sampler = new fir_sampler<float,float>(ncoeffs_sampler, coeffs_sampler, m_objCfg.rrc_steps); sampler = new fir_sampler<float, float>(ncoeffs_sampler, coeffs_sampler, m_objCfg.rrc_steps);
break; break;
} }
@ -659,42 +658,42 @@ void DATVDemod::InitDATVFramework()
m_objDemodulator = new cstln_receiver<f32>(m_objScheduler, sampler, *p_preprocessed, *p_symbols, p_freq, p_ss, p_mer, p_sampled); m_objDemodulator = new cstln_receiver<f32>(m_objScheduler, sampler, *p_preprocessed, *p_symbols, p_freq, p_ss, p_mer, p_sampled);
if ( m_objCfg.standard == DVB_S ) if (m_objCfg.standard == DVB_S)
{ {
if ( m_objCfg.constellation != cstln_lut<256>::QPSK && m_objCfg.constellation != cstln_lut<256>::BPSK ) if (m_objCfg.constellation != cstln_lut<256>::QPSK && m_objCfg.constellation != cstln_lut<256>::BPSK)
{ {
fprintf(stderr, "Warning: non-standard constellation for DVB-S\n"); qWarning("DATVDemod::InitDATVFramework: non-standard constellation for DVB-S");
} }
} }
if ( m_objCfg.standard == DVB_S2 ) if (m_objCfg.standard == DVB_S2)
{ {
// For DVB-S2 testing only. // For DVB-S2 testing only.
// Constellation should be determined from PL signalling. // Constellation should be determined from PL signalling.
fprintf(stderr, "DVB-S2: Testing symbol sampler only.\n"); qWarning("DATVDemod::InitDATVFramework: DVB-S2: Testing symbol sampler only.");
} }
m_objDemodulator->cstln = make_dvbs2_constellation(m_objCfg.constellation, m_objCfg.fec); m_objDemodulator->cstln = make_dvbs2_constellation(m_objCfg.constellation, m_objCfg.fec);
if ( m_objCfg.hard_metric ) if (m_objCfg.hard_metric)
{ {
m_objDemodulator->cstln->harden(); m_objDemodulator->cstln->harden();
} }
m_objDemodulator->set_omega(m_objCfg.Fs/m_objCfg.Fm); m_objDemodulator->set_omega(m_objCfg.Fs / m_objCfg.Fm);
if ( m_objCfg.Ftune ) if (m_objCfg.Ftune)
{ {
m_objDemodulator->set_freq(m_objCfg.Ftune/m_objCfg.Fs); m_objDemodulator->set_freq(m_objCfg.Ftune / m_objCfg.Fs);
} }
if ( m_objCfg.allow_drift ) if (m_objCfg.allow_drift)
{ {
m_objDemodulator->set_allow_drift(true); m_objDemodulator->set_allow_drift(true);
} }
if ( m_objCfg.viterbi ) if (m_objCfg.viterbi)
{ {
m_objDemodulator->pll_adjustment /= 6; m_objDemodulator->pll_adjustment /= 6;
} }
@ -703,15 +702,14 @@ void DATVDemod::InitDATVFramework()
// TRACKING FILTERS // TRACKING FILTERS
if ( r_resample ) if (r_resample)
{ {
r_resample->freq_tap = &m_objDemodulator->freq_tap; r_resample->freq_tap = &m_objDemodulator->freq_tap;
r_resample->tap_multiplier = 1.0 / decim; r_resample->tap_multiplier = 1.0 / decim;
r_resample->freq_tol = m_objCfg.Fm/(m_objCfg.Fs*decim) * 0.1; r_resample->freq_tol = m_objCfg.Fm / (m_objCfg.Fs * decim) * 0.1;
} }
if (r_cnr)
if ( r_cnr )
{ {
r_cnr->freq_tap = &m_objDemodulator->freq_tap; r_cnr->freq_tap = &m_objDemodulator->freq_tap;
r_cnr->tap_multiplier = 1.0 / decim; r_cnr->tap_multiplier = 1.0 / decim;
@ -719,9 +717,9 @@ void DATVDemod::InitDATVFramework()
//constellation //constellation
m_objRegisteredDATVScreen->resizeDATVScreen(256,256); m_objRegisteredDATVScreen->resizeDATVScreen(256, 256);
r_scope_symbols = new datvconstellation<f32>(m_objScheduler, *p_sampled, -128,128, NULL, m_objRegisteredDATVScreen); r_scope_symbols = new datvconstellation<f32>(m_objScheduler, *p_sampled, -128, 128, NULL, m_objRegisteredDATVScreen);
r_scope_symbols->decimation = 1; r_scope_symbols->decimation = 1;
r_scope_symbols->cstln = &m_objDemodulator->cstln; r_scope_symbols->cstln = &m_objDemodulator->cstln;
@ -731,9 +729,9 @@ void DATVDemod::InitDATVFramework()
r_deconv = NULL; r_deconv = NULL;
if ( m_objCfg.viterbi ) if (m_objCfg.viterbi)
{ {
if ( m_objCfg.fec==FEC23 && (m_objDemodulator->cstln->nsymbols==4 || m_objDemodulator->cstln->nsymbols==64) ) if (m_objCfg.fec == FEC23 && (m_objDemodulator->cstln->nsymbols == 4 || m_objDemodulator->cstln->nsymbols == 64))
{ {
m_objCfg.fec = FEC46; m_objCfg.fec = FEC46;
} }
@ -741,7 +739,7 @@ void DATVDemod::InitDATVFramework()
//To uncomment -> Linking Problem : undefined symbol: _ZN7leansdr21viterbi_dec_interfaceIhhiiE6updateEPiS2_ //To uncomment -> Linking Problem : undefined symbol: _ZN7leansdr21viterbi_dec_interfaceIhhiiE6updateEPiS2_
r = new viterbi_sync(m_objScheduler, (*p_symbols), (*p_bytes), m_objDemodulator->cstln, m_objCfg.fec); r = new viterbi_sync(m_objScheduler, (*p_symbols), (*p_bytes), m_objDemodulator->cstln, m_objCfg.fec);
if ( m_objCfg.fastlock ) if (m_objCfg.fastlock)
{ {
r->resync_period = 1; r->resync_period = 1;
} }
@ -752,73 +750,67 @@ void DATVDemod::InitDATVFramework()
r_deconv->fastlock = m_objCfg.fastlock; r_deconv->fastlock = m_objCfg.fastlock;
} }
if (m_objCfg.hdlc)
if ( m_objCfg.hdlc )
{ {
p_descrambled = new pipebuf<u8>(m_objScheduler, "descrambled", BUF_MPEGBYTES); p_descrambled = new pipebuf<u8>(m_objScheduler, "descrambled", BUF_MPEGBYTES);
r_etr192_descrambler = new etr192_descrambler(m_objScheduler, (*p_bytes), *p_descrambled); r_etr192_descrambler = new etr192_descrambler(m_objScheduler, (*p_bytes), *p_descrambled);
p_frames = new pipebuf<u8>(m_objScheduler, "frames", BUF_MPEGBYTES); p_frames = new pipebuf<u8>(m_objScheduler, "frames", BUF_MPEGBYTES);
r_sync = new hdlc_sync(m_objScheduler, *p_descrambled, *p_frames, 2, 278); r_sync = new hdlc_sync(m_objScheduler, *p_descrambled, *p_frames, 2, 278);
if ( m_objCfg.fastlock ) if (m_objCfg.fastlock)
{ {
r_sync->resync_period = 1; r_sync->resync_period = 1;
} }
if ( m_objCfg.packetized ) if (m_objCfg.packetized)
{ {
r_sync->header16 = true; r_sync->header16 = true;
} }
} }
p_mpegbytes = new pipebuf<u8> (m_objScheduler, "mpegbytes", BUF_MPEGBYTES); p_mpegbytes = new pipebuf<u8>(m_objScheduler, "mpegbytes", BUF_MPEGBYTES);
p_lock = new pipebuf<int> (m_objScheduler, "lock", BUF_SLOW); p_lock = new pipebuf<int>(m_objScheduler, "lock", BUF_SLOW);
p_locktime = new pipebuf<u32> (m_objScheduler, "locktime", BUF_PACKETS); p_locktime = new pipebuf<u32>(m_objScheduler, "locktime", BUF_PACKETS);
if ( ! m_objCfg.hdlc ) if (!m_objCfg.hdlc)
{ {
r_sync_mpeg = new mpeg_sync<u8,0>(m_objScheduler, *p_bytes, *p_mpegbytes, r_deconv, p_lock, p_locktime); r_sync_mpeg = new mpeg_sync<u8, 0>(m_objScheduler, *p_bytes, *p_mpegbytes, r_deconv, p_lock, p_locktime);
r_sync_mpeg->fastlock = m_objCfg.fastlock; r_sync_mpeg->fastlock = m_objCfg.fastlock;
} }
// DEINTERLEAVING // DEINTERLEAVING
p_rspackets = new pipebuf< rspacket<u8> >(m_objScheduler, "RS-enc packets", BUF_PACKETS); p_rspackets = new pipebuf<rspacket<u8> >(m_objScheduler, "RS-enc packets", BUF_PACKETS);
r_deinter = new deinterleaver<u8>(m_objScheduler, *p_mpegbytes, *p_rspackets); r_deinter = new deinterleaver<u8>(m_objScheduler, *p_mpegbytes, *p_rspackets);
// REED-SOLOMON // REED-SOLOMON
p_vbitcount = new pipebuf<int>(m_objScheduler, "Bits processed", BUF_PACKETS); p_vbitcount = new pipebuf<int>(m_objScheduler, "Bits processed", BUF_PACKETS);
p_verrcount = new pipebuf<int>(m_objScheduler, "Bits corrected", BUF_PACKETS); p_verrcount = new pipebuf<int>(m_objScheduler, "Bits corrected", BUF_PACKETS);
p_rtspackets = new pipebuf<tspacket>(m_objScheduler, "rand TS packets", BUF_PACKETS); p_rtspackets = new pipebuf<tspacket>(m_objScheduler, "rand TS packets", BUF_PACKETS);
r_rsdec = new rs_decoder<u8,0> (m_objScheduler, *p_rspackets, *p_rtspackets, p_vbitcount, p_verrcount); r_rsdec = new rs_decoder<u8, 0>(m_objScheduler, *p_rspackets, *p_rtspackets, p_vbitcount, p_verrcount);
// BER ESTIMATION // BER ESTIMATION
p_vber = new pipebuf<float>(m_objScheduler, "VBER", BUF_SLOW);
p_vber = new pipebuf<float> (m_objScheduler, "VBER", BUF_SLOW); r_vber = new rate_estimator<float>(m_objScheduler, *p_verrcount, *p_vbitcount, *p_vber);
r_vber = new rate_estimator<float> (m_objScheduler, *p_verrcount, *p_vbitcount, *p_vber); r_vber->sample_size = m_objCfg.Fm / 2; // About twice per second, depending on CR
r_vber->sample_size = m_objCfg.Fm/2; // About twice per second, depending on CR
// Require resolution better than 2E-5 // Require resolution better than 2E-5
if ( r_vber->sample_size < 50000 ) if (r_vber->sample_size < 50000)
{ {
r_vber->sample_size = 50000; r_vber->sample_size = 50000;
} }
// DERANDOMIZATION // DERANDOMIZATION
p_tspackets = new pipebuf<tspacket>(m_objScheduler, "TS packets", BUF_PACKETS); p_tspackets = new pipebuf<tspacket>(m_objScheduler, "TS packets", BUF_PACKETS);
r_derand = new derandomizer(m_objScheduler, *p_rtspackets, *p_tspackets); r_derand = new derandomizer(m_objScheduler, *p_rtspackets, *p_tspackets);
// OUTPUT // OUTPUT
r_videoplayer = new datvvideoplayer<tspacket>(m_objScheduler, *p_tspackets,m_objVideoStream); r_videoplayer = new datvvideoplayer<tspacket>(m_objScheduler, *p_tspackets, m_objVideoStream);
m_blnDVBInitialized=true; m_blnDVBInitialized = true;
} }
void DATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused))) void DATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused)))
@ -830,7 +822,6 @@ void DATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVect
fftfilt::cmplx *objRF; fftfilt::cmplx *objRF;
int intRFOut; int intRFOut;
#ifdef EXTENDED_DIRECT_SAMPLE #ifdef EXTENDED_DIRECT_SAMPLE
qint16 * ptrBufferToRelease=NULL; qint16 * ptrBufferToRelease=NULL;
@ -860,28 +851,27 @@ void DATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVect
fltQ = it->imag(); fltQ = it->imag();
#endif #endif
//********** demodulation ********** //********** demodulation **********
if((m_blnDVBInitialized==false) || (m_blnNeedConfigUpdate==true)) if ((m_blnDVBInitialized == false) || (m_blnNeedConfigUpdate == true))
{ {
m_blnNeedConfigUpdate=false; m_blnNeedConfigUpdate = false;
InitDATVFramework(); InitDATVFramework();
} }
//********** iq stream **************** //********** iq stream ****************
if(m_lngReadIQ>p_rawiq_writer->writable()) if (m_lngReadIQ > p_rawiq_writer->writable())
{ {
m_objScheduler->step(); m_objScheduler->step();
m_objRegisteredDATVScreen->renderImage(NULL); m_objRegisteredDATVScreen->renderImage(NULL);
m_lngReadIQ=0; m_lngReadIQ = 0;
p_rawiq_writer = new pipewriter<cf32>(*p_rawiq); p_rawiq_writer = new pipewriter<cf32>(*p_rawiq);
} }
if(false) if (false)
{ {
objIQ.re = fltI; objIQ.re = fltI;
objIQ.im = fltQ; objIQ.im = fltQ;
@ -893,25 +883,24 @@ void DATVDemod::feed(const SampleVector::const_iterator& begin, const SampleVect
else else
{ {
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++)
{ {
objIQ.re = objRF->real(); objIQ.re = objRF->real();
objIQ.im = objRF->imag(); objIQ.im = objRF->imag();
p_rawiq_writer->write(objIQ); p_rawiq_writer->write(objIQ);
objRF ++; objRF++;
m_lngReadIQ++; m_lngReadIQ++;
} }
} }
//********** demodulation ********** //********** demodulation **********
} }
@ -939,24 +928,21 @@ void DATVDemod::stop()
bool DATVDemod::handleMessage(const Message& cmd) bool DATVDemod::handleMessage(const Message& cmd)
{ {
qDebug() << "DATVDemod::handleMessage";
if (DownChannelizer::MsgChannelizerNotification::match(cmd)) if (DownChannelizer::MsgChannelizerNotification::match(cmd))
{ {
DownChannelizer::MsgChannelizerNotification& objNotif = (DownChannelizer::MsgChannelizerNotification&) cmd; DownChannelizer::MsgChannelizerNotification& objNotif = (DownChannelizer::MsgChannelizerNotification&) cmd;
if(m_objRunning.intMsps!=objNotif.getSampleRate()) qDebug() << "DATVDemod::handleMessage: MsgChannelizerNotification:" << " intMsps: " << objNotif.getSampleRate();
if (m_objRunning.intMsps != objNotif.getSampleRate())
{ {
m_objRunning.intMsps = objNotif.getSampleRate(); m_objRunning.intMsps = objNotif.getSampleRate();
m_objRunning.intSampleRate = m_objRunning.intMsps; m_objRunning.intSampleRate = m_objRunning.intMsps;
printf("Sample Rate: %d\r\n",m_objRunning.intSampleRate ); qDebug("DATVDemod::handleMessage: Sample Rate: %d", m_objRunning.intSampleRate);
ApplySettings(); ApplySettings();
} }
qDebug() << "DATVDemod::handleMessage: MsgChannelizerNotification:"
<< " intMsps: " << m_objRunning.intMsps;
return true; return true;
} }
else if (MsgConfigureChannelizer::match(cmd)) else if (MsgConfigureChannelizer::match(cmd))
@ -964,34 +950,28 @@ bool DATVDemod::handleMessage(const Message& cmd)
MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd; MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd;
m_channelizer->configure(m_channelizer->getInputMessageQueue(), qDebug() << "DATVDemod::handleMessage: MsgConfigureChannelizer:"
m_channelizer->getInputSampleRate(), << " sampleRate: " << m_channelizer->getInputSampleRate()
cfg.getCenterFrequency());
//m_objRunning.intCenterFrequency);
qDebug() << "DATVDemod::handleMessage: MsgConfigureChannelizer: sampleRate: " << m_channelizer->getInputSampleRate()
<< " centerFrequency: " << cfg.getCenterFrequency(); << " centerFrequency: " << cfg.getCenterFrequency();
m_channelizer->configure(m_channelizer->getInputMessageQueue(), m_channelizer->getInputSampleRate(), cfg.getCenterFrequency());
//m_objRunning.intCenterFrequency);
//<< " centerFrequency: " << m_objRunning.intCenterFrequency; //<< " centerFrequency: " << m_objRunning.intCenterFrequency;
return true; return true;
} }
else if (MsgConfigureDATVDemod::match(cmd)) else if (MsgConfigureDATVDemod::match(cmd))
{ {
qDebug() << "DATVDemod::handleMessage: MsgConfigureDATVDemod";
MsgConfigureDATVDemod& objCfg = (MsgConfigureDATVDemod&) cmd; MsgConfigureDATVDemod& objCfg = (MsgConfigureDATVDemod&) cmd;
if ((objCfg.m_objMsgConfig.blnAllowDrift != m_objRunning.blnAllowDrift) || (objCfg.m_objMsgConfig.intRFBandwidth != m_objRunning.intRFBandwidth)
if((objCfg.m_objMsgConfig.blnAllowDrift != m_objRunning.blnAllowDrift) || (objCfg.m_objMsgConfig.intCenterFrequency != m_objRunning.intCenterFrequency) || (objCfg.m_objMsgConfig.blnFastLock != m_objRunning.blnFastLock)
|| (objCfg.m_objMsgConfig.intRFBandwidth != m_objRunning.intRFBandwidth) || (objCfg.m_objMsgConfig.blnHardMetric != m_objRunning.blnHardMetric) || (objCfg.m_objMsgConfig.blnHDLC != m_objRunning.blnHDLC)
|| (objCfg.m_objMsgConfig.intCenterFrequency != m_objRunning.intCenterFrequency) || (objCfg.m_objMsgConfig.blnResample != m_objRunning.blnResample) || (objCfg.m_objMsgConfig.blnViterbi != m_objRunning.blnViterbi)
|| (objCfg.m_objMsgConfig.blnFastLock != m_objRunning.blnFastLock) || (objCfg.m_objMsgConfig.enmFEC != m_objRunning.enmFEC) || (objCfg.m_objMsgConfig.enmModulation != m_objRunning.enmModulation)
|| (objCfg.m_objMsgConfig.blnHardMetric != m_objRunning.blnHardMetric) || (objCfg.m_objMsgConfig.enmStandard != m_objRunning.enmStandard) || (objCfg.m_objMsgConfig.intNotchFilters != m_objRunning.intNotchFilters)
|| (objCfg.m_objMsgConfig.blnHDLC != m_objRunning.blnHDLC)
|| (objCfg.m_objMsgConfig.blnResample != m_objRunning.blnResample)
|| (objCfg.m_objMsgConfig.blnViterbi != m_objRunning.blnViterbi)
|| (objCfg.m_objMsgConfig.enmFEC != m_objRunning.enmFEC)
|| (objCfg.m_objMsgConfig.enmModulation != m_objRunning.enmModulation)
|| (objCfg.m_objMsgConfig.enmStandard != m_objRunning.enmStandard)
|| (objCfg.m_objMsgConfig.intNotchFilters != m_objRunning.intNotchFilters)
|| (objCfg.m_objMsgConfig.intSymbolRate != m_objRunning.intSymbolRate)) || (objCfg.m_objMsgConfig.intSymbolRate != m_objRunning.intSymbolRate))
{ {
m_objRunning.blnAllowDrift = objCfg.m_objMsgConfig.blnAllowDrift; m_objRunning.blnAllowDrift = objCfg.m_objMsgConfig.blnAllowDrift;
@ -1011,7 +991,11 @@ bool DATVDemod::handleMessage(const Message& cmd)
ApplySettings(); ApplySettings();
} }
return true;
}
else if (DSPSignalNotification::match(cmd))
{
qDebug() << "DATVDemod::handleMessage: DSPSignalNotification";
return true; return true;
} }
else else
@ -1023,14 +1007,15 @@ bool DATVDemod::handleMessage(const Message& cmd)
void DATVDemod::ApplySettings() void DATVDemod::ApplySettings()
{ {
if(m_objRunning.intMsps==0) if (m_objRunning.intMsps == 0)
{ {
return; return;
} }
//m_objSettingsMutex.lock(); //m_objSettingsMutex.lock();
InitDATVParameters(m_objRunning.intMsps, InitDATVParameters(
m_objRunning.intMsps,
m_objRunning.intRFBandwidth, m_objRunning.intRFBandwidth,
m_objRunning.intCenterFrequency, m_objRunning.intCenterFrequency,
m_objRunning.enmStandard, m_objRunning.enmStandard,
@ -1053,3 +1038,10 @@ int DATVDemod::GetSampleRate()
return m_objRunning.intMsps; return m_objRunning.intMsps;
} }
void DATVDemod::channelSampleRateChanged()
{
qDebug("DATVDemod::channelSampleRateChanged");
// reconfigure to get full available bandwidth
m_channelizer->configure(m_channelizer->getInputMessageQueue(), m_channelizer->getInputSampleRate(), m_channelizer->getRequestedCenterFrequency());
// TODO: forward to GUI if necessary
}

View File

@ -496,6 +496,8 @@ private:
void ApplySettings(); void ApplySettings();
private slots:
void channelSampleRateChanged();
}; };
#endif // INCLUDE_DATVDEMOD_H #endif // INCLUDE_DATVDEMOD_H

View File

@ -68,6 +68,7 @@ public:
void configure(MessageQueue* messageQueue, int sampleRate, int centerFrequency); void configure(MessageQueue* messageQueue, int sampleRate, int centerFrequency);
int getInputSampleRate() const { return m_inputSampleRate; } int getInputSampleRate() const { return m_inputSampleRate; }
int getRequestedCenterFrequency() const { return m_requestedCenterFrequency; }
virtual void start(); virtual void start();
virtual void stop(); virtual void stop();