mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-03 21:20:31 -05:00 
			
		
		
		
	ATV demod: effective support of random channel sample rate
This commit is contained in:
		
							parent
							
								
									51c2eaee82
								
							
						
					
					
						commit
						e76e2321c1
					
				@ -129,7 +129,6 @@ void ATVDemod::applySettings(const ATVDemodSettings& settings, bool force)
 | 
			
		||||
{
 | 
			
		||||
    qDebug() << "ATVDemod::applySettings:"
 | 
			
		||||
            << "m_inputFrequencyOffset:" << settings.m_inputFrequencyOffset
 | 
			
		||||
            << "m_forceDecimator:" << settings.m_forceDecimator
 | 
			
		||||
            << "m_bfoFrequency:" << settings.m_bfoFrequency
 | 
			
		||||
            << "m_atvModulation:" << settings.m_atvModulation
 | 
			
		||||
            << "m_fmDeviation:" << settings.m_fmDeviation
 | 
			
		||||
@ -145,8 +144,6 @@ void ATVDemod::applySettings(const ATVDemodSettings& settings, bool force)
 | 
			
		||||
            << "m_halfFrames:" << settings.m_halfFrames
 | 
			
		||||
            << "m_levelSynchroTop:" << settings.m_levelSynchroTop
 | 
			
		||||
            << "m_levelBlack:" << settings.m_levelBlack
 | 
			
		||||
            << "m_lineTimeFactor:" << settings.m_lineTimeFactor
 | 
			
		||||
            << "m_topTimeFactor:" << settings.m_topTimeFactor
 | 
			
		||||
            << "m_rgbColor:" << settings.m_rgbColor
 | 
			
		||||
            << "m_title:" << settings.m_title
 | 
			
		||||
            << "m_udpAddress:" << settings.m_udpAddress
 | 
			
		||||
 | 
			
		||||
@ -116,8 +116,6 @@ void ATVDemodGUI::displaySettings()
 | 
			
		||||
    ui->synchLevelText->setText(QString("%1 mV").arg((int) (m_settings.m_levelSynchroTop * 1000.0f)));
 | 
			
		||||
    ui->blackLevel->setValue((int) (m_settings.m_levelBlack * 1000.0f));
 | 
			
		||||
    ui->blackLevelText->setText(QString("%1 mV").arg((int) (m_settings.m_levelBlack * 1000.0f)));
 | 
			
		||||
    ui->lineTime->setValue(m_settings.m_lineTimeFactor);
 | 
			
		||||
    ui->topTime->setValue(m_settings.m_topTimeFactor);
 | 
			
		||||
    ui->modulation->setCurrentIndex((int) m_settings.m_atvModulation);
 | 
			
		||||
    ui->fps->setCurrentIndex(ATVDemodSettings::getFpsIndex(m_settings.m_fps));
 | 
			
		||||
    ui->nbLines->setCurrentIndex(ATVDemodSettings::getNumberOfLinesIndex(m_settings.m_nbLines));
 | 
			
		||||
@ -131,7 +129,6 @@ void ATVDemodGUI::displaySettings()
 | 
			
		||||
 | 
			
		||||
    //********** RF values **********
 | 
			
		||||
    ui->deltaFrequency->setValue(m_settings.m_inputFrequencyOffset);
 | 
			
		||||
    ui->decimatorEnable->setChecked(m_settings.m_forceDecimator);
 | 
			
		||||
    ui->rfFiltering->setChecked(m_settings.m_fftFiltering);
 | 
			
		||||
    ui->bfo->setValue(m_settings.m_bfoFrequency);
 | 
			
		||||
    ui->bfoText->setText(QString("%1").arg(m_settings.m_bfoFrequency * 1.0, 0, 'f', 0));
 | 
			
		||||
@ -172,11 +169,11 @@ void ATVDemodGUI::applyTVSampleRate()
 | 
			
		||||
{
 | 
			
		||||
    qDebug("TVDemodGUI::applyTVSampleRate");
 | 
			
		||||
    unsigned int nbPointsPerLine;
 | 
			
		||||
    ATVDemodSettings::getBaseValues(m_basebandSampleRate, m_settings.m_fps*m_settings.m_nbLines, m_tvSampleRate, nbPointsPerLine);
 | 
			
		||||
    ui->tvSampleRateText->setText(tr("%1k").arg(m_tvSampleRate/1000.0f, 0, 'f', 2));
 | 
			
		||||
    ATVDemodSettings::getBaseValues(m_basebandSampleRate, m_settings.m_fps*m_settings.m_nbLines, nbPointsPerLine);
 | 
			
		||||
    ui->tvSampleRateText->setText(tr("%1k").arg(m_basebandSampleRate/1000.0f, 0, 'f', 2));
 | 
			
		||||
    ui->nbPointsPerLineText->setText(tr("%1p").arg(nbPointsPerLine));
 | 
			
		||||
    m_scopeVis->setLiveRate(m_tvSampleRate);
 | 
			
		||||
    setRFFiltersSlidersRange(m_tvSampleRate);
 | 
			
		||||
    m_scopeVis->setLiveRate(m_basebandSampleRate);
 | 
			
		||||
    setRFFiltersSlidersRange(m_basebandSampleRate);
 | 
			
		||||
    displayRFBandwidths();
 | 
			
		||||
    lineTimeUpdate();
 | 
			
		||||
    topTimeUpdate();
 | 
			
		||||
@ -238,8 +235,7 @@ ATVDemodGUI::ATVDemodGUI(PluginAPI* objPluginAPI, DeviceUISet *deviceUISet, Base
 | 
			
		||||
        m_channelMarker(this),
 | 
			
		||||
        m_doApplySettings(false),
 | 
			
		||||
        m_intTickCount(0),
 | 
			
		||||
        m_basebandSampleRate(48000),
 | 
			
		||||
        m_tvSampleRate(48000)
 | 
			
		||||
        m_basebandSampleRate(48000)
 | 
			
		||||
{
 | 
			
		||||
    ui->setupUi(this);
 | 
			
		||||
    setAttribute(Qt::WA_DeleteOnClose, true);
 | 
			
		||||
@ -341,12 +337,7 @@ void ATVDemodGUI::setChannelMarkerBandwidth()
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        if ((m_basebandSampleRate == m_tvSampleRate) && (!m_settings.m_forceDecimator)) {
 | 
			
		||||
            m_channelMarker.setBandwidth(m_basebandSampleRate);
 | 
			
		||||
        } else {
 | 
			
		||||
            m_channelMarker.setBandwidth(ui->rfBW->value()*m_rfSliderDivisor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_channelMarker.setBandwidth(m_basebandSampleRate);
 | 
			
		||||
        m_channelMarker.setSidebands(ChannelMarker::dsb);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -435,22 +426,6 @@ void ATVDemodGUI::on_blackLevel_valueChanged(int value)
 | 
			
		||||
    applySettings();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ATVDemodGUI::on_lineTime_valueChanged(int value)
 | 
			
		||||
{
 | 
			
		||||
	ui->lineTime->setToolTip(QString("Line length adjustment (%1)").arg(value));
 | 
			
		||||
    m_settings.m_lineTimeFactor = value;
 | 
			
		||||
    lineTimeUpdate();
 | 
			
		||||
    applySettings();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ATVDemodGUI::on_topTime_valueChanged(int value)
 | 
			
		||||
{
 | 
			
		||||
	ui->topTime->setToolTip(QString("Horizontal sync pulse length adjustment (%1 %)").arg(value));
 | 
			
		||||
    m_settings.m_topTimeFactor = value;
 | 
			
		||||
    topTimeUpdate();
 | 
			
		||||
    applySettings();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ATVDemodGUI::on_hSync_clicked()
 | 
			
		||||
{
 | 
			
		||||
    m_settings.m_hSync = ui->hSync->isChecked();
 | 
			
		||||
@ -504,7 +479,7 @@ void ATVDemodGUI::on_reset_clicked(bool checked)
 | 
			
		||||
void ATVDemodGUI::on_modulation_currentIndexChanged(int index)
 | 
			
		||||
{
 | 
			
		||||
    m_settings.m_atvModulation = (ATVDemodSettings::ATVModulation) index;
 | 
			
		||||
    setRFFiltersSlidersRange(m_tvSampleRate);
 | 
			
		||||
    setRFFiltersSlidersRange(m_basebandSampleRate);
 | 
			
		||||
    setChannelMarkerBandwidth();
 | 
			
		||||
    applySettings();
 | 
			
		||||
}
 | 
			
		||||
@ -528,14 +503,7 @@ void ATVDemodGUI::on_rfOppBW_valueChanged(int value)
 | 
			
		||||
void ATVDemodGUI::on_rfFiltering_toggled(bool checked)
 | 
			
		||||
{
 | 
			
		||||
    m_settings.m_fftFiltering = checked;
 | 
			
		||||
    setRFFiltersSlidersRange(m_tvSampleRate);
 | 
			
		||||
    setChannelMarkerBandwidth();
 | 
			
		||||
    applySettings();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ATVDemodGUI::on_decimatorEnable_toggled(bool checked)
 | 
			
		||||
{
 | 
			
		||||
    m_settings.m_forceDecimator = checked;
 | 
			
		||||
    setRFFiltersSlidersRange(m_basebandSampleRate);
 | 
			
		||||
    setChannelMarkerBandwidth();
 | 
			
		||||
    applySettings();
 | 
			
		||||
}
 | 
			
		||||
@ -585,41 +553,31 @@ void ATVDemodGUI::on_screenTabWidget_currentChanged(int index)
 | 
			
		||||
void ATVDemodGUI::lineTimeUpdate()
 | 
			
		||||
{
 | 
			
		||||
    float nominalLineTime = ATVDemodSettings::getNominalLineTime(m_settings.m_nbLines, m_settings.m_fps);
 | 
			
		||||
    int lineTimeScaleFactor = (int) std::log10(nominalLineTime);
 | 
			
		||||
 | 
			
		||||
    if (m_tvSampleRate == 0) {
 | 
			
		||||
        m_fltLineTimeMultiplier = std::pow(10.0, lineTimeScaleFactor-3);
 | 
			
		||||
    } else {
 | 
			
		||||
        m_fltLineTimeMultiplier = 1.0f / m_tvSampleRate;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    float lineTime = nominalLineTime + m_fltLineTimeMultiplier * ui->lineTime->value();
 | 
			
		||||
 | 
			
		||||
    if (lineTime < 0.0)
 | 
			
		||||
    if (nominalLineTime < 0.0)
 | 
			
		||||
        ui->lineTimeText->setText("invalid");
 | 
			
		||||
    else if(lineTime < 0.000001)
 | 
			
		||||
        ui->lineTimeText->setText(tr("%1 ns").arg(lineTime * 1000000000.0, 0, 'f', 2));
 | 
			
		||||
    else if(lineTime < 0.001)
 | 
			
		||||
        ui->lineTimeText->setText(tr("%1 µs").arg(lineTime * 1000000.0, 0, 'f', 2));
 | 
			
		||||
    else if(lineTime < 1.0)
 | 
			
		||||
        ui->lineTimeText->setText(tr("%1 ms").arg(lineTime * 1000.0, 0, 'f', 2));
 | 
			
		||||
    else if(nominalLineTime < 0.000001)
 | 
			
		||||
        ui->lineTimeText->setText(tr("%1 ns").arg(nominalLineTime * 1000000000.0, 0, 'f', 2));
 | 
			
		||||
    else if(nominalLineTime < 0.001)
 | 
			
		||||
        ui->lineTimeText->setText(tr("%1 µs").arg(nominalLineTime * 1000000.0, 0, 'f', 2));
 | 
			
		||||
    else if(nominalLineTime < 1.0)
 | 
			
		||||
        ui->lineTimeText->setText(tr("%1 ms").arg(nominalLineTime * 1000.0, 0, 'f', 2));
 | 
			
		||||
    else
 | 
			
		||||
        ui->lineTimeText->setText(tr("%1 s").arg(lineTime * 1.0, 0, 'f', 2));
 | 
			
		||||
        ui->lineTimeText->setText(tr("%1 s").arg(nominalLineTime * 1.0, 0, 'f', 2));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ATVDemodGUI::topTimeUpdate()
 | 
			
		||||
{
 | 
			
		||||
    float nominalTopTime = ATVDemodSettings::getNominalLineTime(m_settings.m_nbLines, m_settings.m_fps) * (4.7f / 64.0f);
 | 
			
		||||
    float topTime = nominalTopTime * (ui->topTime->value() / 100.0f);
 | 
			
		||||
 | 
			
		||||
    if (topTime < 0.0)
 | 
			
		||||
    if (nominalTopTime < 0.0)
 | 
			
		||||
        ui->topTimeText->setText("invalid");
 | 
			
		||||
    else if (topTime < 0.000001)
 | 
			
		||||
        ui->topTimeText->setText(tr("%1 ns").arg(topTime * 1000000000.0, 0, 'f', 2));
 | 
			
		||||
    else if(topTime < 0.001)
 | 
			
		||||
        ui->topTimeText->setText(tr("%1 µs").arg(topTime * 1000000.0, 0, 'f', 2));
 | 
			
		||||
    else if(topTime < 1.0)
 | 
			
		||||
        ui->topTimeText->setText(tr("%1 ms").arg(topTime * 1000.0, 0, 'f', 2));
 | 
			
		||||
    else if (nominalTopTime < 0.000001)
 | 
			
		||||
        ui->topTimeText->setText(tr("%1 ns").arg(nominalTopTime * 1000000000.0, 0, 'f', 2));
 | 
			
		||||
    else if(nominalTopTime < 0.001)
 | 
			
		||||
        ui->topTimeText->setText(tr("%1 µs").arg(nominalTopTime * 1000000.0, 0, 'f', 2));
 | 
			
		||||
    else if(nominalTopTime < 1.0)
 | 
			
		||||
        ui->topTimeText->setText(tr("%1 ms").arg(nominalTopTime * 1000.0, 0, 'f', 2));
 | 
			
		||||
    else
 | 
			
		||||
        ui->topTimeText->setText(tr("%1 s").arg(topTime * 1.0, 0, 'f', 2));
 | 
			
		||||
        ui->topTimeText->setText(tr("%1 s").arg(nominalTopTime * 1.0, 0, 'f', 2));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -76,10 +76,8 @@ private:
 | 
			
		||||
 | 
			
		||||
    ScopeVis* m_scopeVis;
 | 
			
		||||
 | 
			
		||||
    float m_fltLineTimeMultiplier;
 | 
			
		||||
    int m_rfSliderDivisor;
 | 
			
		||||
    int m_basebandSampleRate;
 | 
			
		||||
    int m_tvSampleRate;
 | 
			
		||||
    MessageQueue m_inputMessageQueue;
 | 
			
		||||
 | 
			
		||||
    explicit ATVDemodGUI(PluginAPI* objPluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* objParent = 0);
 | 
			
		||||
@ -104,8 +102,6 @@ private slots:
 | 
			
		||||
    void tick();
 | 
			
		||||
    void on_synchLevel_valueChanged(int value);
 | 
			
		||||
    void on_blackLevel_valueChanged(int value);
 | 
			
		||||
    void on_lineTime_valueChanged(int value);
 | 
			
		||||
    void on_topTime_valueChanged(int value);
 | 
			
		||||
    void on_hSync_clicked();
 | 
			
		||||
    void on_vSync_clicked();
 | 
			
		||||
    void on_invertVideo_clicked();
 | 
			
		||||
@ -118,7 +114,6 @@ private slots:
 | 
			
		||||
    void on_rfBW_valueChanged(int value);
 | 
			
		||||
    void on_rfOppBW_valueChanged(int value);
 | 
			
		||||
    void on_rfFiltering_toggled(bool checked);
 | 
			
		||||
    void on_decimatorEnable_toggled(bool checked);
 | 
			
		||||
    void on_deltaFrequency_changed(qint64 value);
 | 
			
		||||
    void on_bfo_valueChanged(int value);
 | 
			
		||||
    void on_fmDeviation_valueChanged(int value);
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>700</width>
 | 
			
		||||
    <height>743</height>
 | 
			
		||||
    <height>699</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="sizePolicy">
 | 
			
		||||
@ -114,23 +114,6 @@
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="ButtonSwitch" name="decimatorEnable">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string>Toggle decimator on/off</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string/>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="icon">
 | 
			
		||||
         <iconset resource="../../../sdrgui/resources/res.qrc">
 | 
			
		||||
          <normaloff>:/arrow_down.png</normaloff>:/arrow_down.png</iconset>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="checkable">
 | 
			
		||||
         <bool>true</bool>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QLabel" name="tvSampleRateText">
 | 
			
		||||
        <property name="minimumSize">
 | 
			
		||||
@ -592,7 +575,7 @@
 | 
			
		||||
     <x>10</x>
 | 
			
		||||
     <y>570</y>
 | 
			
		||||
     <width>681</width>
 | 
			
		||||
     <height>81</height>
 | 
			
		||||
     <height>104</height>
 | 
			
		||||
    </rect>
 | 
			
		||||
   </property>
 | 
			
		||||
   <property name="windowTitle">
 | 
			
		||||
@ -903,19 +886,6 @@
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="0" column="6">
 | 
			
		||||
       <widget class="QLabel" name="blackLevelText">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string>Black level value</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string><html><head/><body><p align="right">mV</p></body></html></string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="alignment">
 | 
			
		||||
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="0" column="2">
 | 
			
		||||
       <widget class="QLabel" name="synchLevelText">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
@ -936,14 +906,27 @@
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="0" column="4">
 | 
			
		||||
      <item row="0" column="3">
 | 
			
		||||
       <spacer name="horizontalSpacer_2">
 | 
			
		||||
        <property name="orientation">
 | 
			
		||||
         <enum>Qt::Horizontal</enum>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="sizeHint" stdset="0">
 | 
			
		||||
         <size>
 | 
			
		||||
          <width>40</width>
 | 
			
		||||
          <height>20</height>
 | 
			
		||||
         </size>
 | 
			
		||||
        </property>
 | 
			
		||||
       </spacer>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="1" column="0">
 | 
			
		||||
       <widget class="QLabel" name="blackLevelLabel">
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string><html><head/><body><p>Black Lvl</p></body></html></string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="0" column="5">
 | 
			
		||||
      <item row="1" column="1">
 | 
			
		||||
       <widget class="QSlider" name="blackLevel">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string>Black level</string>
 | 
			
		||||
@ -965,38 +948,42 @@
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="1" column="0">
 | 
			
		||||
       <widget class="QLabel" name="lineTimeLabel">
 | 
			
		||||
      <item row="1" column="2">
 | 
			
		||||
       <widget class="QLabel" name="blackLevelText">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string>Black level value</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Line</string>
 | 
			
		||||
         <string><html><head/><body><p align="right">mV</p></body></html></string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="alignment">
 | 
			
		||||
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="1" column="1">
 | 
			
		||||
       <widget class="QSlider" name="lineTime">
 | 
			
		||||
      <item row="0" column="6">
 | 
			
		||||
       <widget class="QLabel" name="lineTimeText">
 | 
			
		||||
        <property name="minimumSize">
 | 
			
		||||
         <size>
 | 
			
		||||
          <width>62</width>
 | 
			
		||||
          <height>0</height>
 | 
			
		||||
         </size>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string>Line length adjustment</string>
 | 
			
		||||
         <string>Effective line length value</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="minimum">
 | 
			
		||||
         <number>-100</number>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string><html><head/><body><p align="right">&mu;S</p></body></html></string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="maximum">
 | 
			
		||||
         <number>100</number>
 | 
			
		||||
        <property name="alignment">
 | 
			
		||||
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="singleStep">
 | 
			
		||||
         <number>1</number>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="pageStep">
 | 
			
		||||
         <number>1</number>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="value">
 | 
			
		||||
         <number>0</number>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="sliderPosition">
 | 
			
		||||
         <number>0</number>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="orientation">
 | 
			
		||||
         <enum>Qt::Horizontal</enum>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="0" column="4">
 | 
			
		||||
       <widget class="QLabel" name="lineTimeLabel">
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Line</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
@ -1007,31 +994,6 @@
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="1" column="5">
 | 
			
		||||
       <widget class="QSlider" name="topTime">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string>Horizontal sync pulse length adjustment</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="minimum">
 | 
			
		||||
         <number>1</number>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="maximum">
 | 
			
		||||
         <number>100</number>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="singleStep">
 | 
			
		||||
         <number>1</number>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="pageStep">
 | 
			
		||||
         <number>1</number>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="value">
 | 
			
		||||
         <number>25</number>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="orientation">
 | 
			
		||||
         <enum>Qt::Horizontal</enum>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="1" column="6">
 | 
			
		||||
       <widget class="QLabel" name="topTimeText">
 | 
			
		||||
        <property name="minimumSize">
 | 
			
		||||
@ -1051,38 +1013,6 @@
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="0" column="3">
 | 
			
		||||
       <spacer name="horizontalSpacer_2">
 | 
			
		||||
        <property name="orientation">
 | 
			
		||||
         <enum>Qt::Horizontal</enum>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="sizeHint" stdset="0">
 | 
			
		||||
         <size>
 | 
			
		||||
          <width>40</width>
 | 
			
		||||
          <height>20</height>
 | 
			
		||||
         </size>
 | 
			
		||||
        </property>
 | 
			
		||||
       </spacer>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="1" column="2">
 | 
			
		||||
       <widget class="QLabel" name="lineTimeText">
 | 
			
		||||
        <property name="minimumSize">
 | 
			
		||||
         <size>
 | 
			
		||||
          <width>62</width>
 | 
			
		||||
          <height>0</height>
 | 
			
		||||
         </size>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string>Effective line length value</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string><html><head/><body><p align="right">&mu;S</p></body></html></string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="alignment">
 | 
			
		||||
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
     </layout>
 | 
			
		||||
    </item>
 | 
			
		||||
   </layout>
 | 
			
		||||
 | 
			
		||||
@ -31,7 +31,6 @@ ATVDemodSettings::ATVDemodSettings() :
 | 
			
		||||
void ATVDemodSettings::resetToDefaults()
 | 
			
		||||
{
 | 
			
		||||
    m_inputFrequencyOffset = 0;
 | 
			
		||||
    m_forceDecimator = false;
 | 
			
		||||
    m_bfoFrequency = 0.0f;
 | 
			
		||||
    m_atvModulation = ATV_FM1;
 | 
			
		||||
    m_fmDeviation = 0.5f;
 | 
			
		||||
@ -49,8 +48,6 @@ void ATVDemodSettings::resetToDefaults()
 | 
			
		||||
    m_halfFrames = false; // m_fltRatioOfRowsToDisplay = 1.0
 | 
			
		||||
    m_levelSynchroTop = 0.15f;
 | 
			
		||||
    m_levelBlack = 0.3f;
 | 
			
		||||
    m_lineTimeFactor = 0;
 | 
			
		||||
    m_topTimeFactor = 25;
 | 
			
		||||
    m_rgbColor = QColor(255, 255, 255).rgb();
 | 
			
		||||
    m_title = "ATV Demodulator";
 | 
			
		||||
    m_udpAddress = "127.0.0.1";
 | 
			
		||||
@ -66,8 +63,6 @@ QByteArray ATVDemodSettings::serialize() const
 | 
			
		||||
    s.writeU32(2, m_rgbColor);
 | 
			
		||||
    s.writeS32(3, roundf(m_levelSynchroTop*1000.0)); // mV
 | 
			
		||||
    s.writeS32(4, roundf(m_levelBlack*1000.0));      // mV
 | 
			
		||||
    s.writeS32(5, m_lineTimeFactor);
 | 
			
		||||
    s.writeS32(6, m_topTimeFactor);
 | 
			
		||||
    s.writeS32(7, m_atvModulation);
 | 
			
		||||
    s.writeS32(8, m_fps);
 | 
			
		||||
    s.writeBool(9, m_hSync);
 | 
			
		||||
@ -90,7 +85,6 @@ QByteArray ATVDemodSettings::serialize() const
 | 
			
		||||
    s.writeS32(22, m_amScalingFactor);
 | 
			
		||||
    s.writeS32(23, m_amOffsetFactor);
 | 
			
		||||
    s.writeBool(24, m_fftFiltering);
 | 
			
		||||
    s.writeBool(25, m_forceDecimator);
 | 
			
		||||
 | 
			
		||||
    return s.final();
 | 
			
		||||
}
 | 
			
		||||
@ -116,8 +110,6 @@ bool ATVDemodSettings::deserialize(const QByteArray& arrData)
 | 
			
		||||
        m_levelSynchroTop = tmp / 1000.0f;
 | 
			
		||||
        d.readS32(4, &tmp, 310);
 | 
			
		||||
        m_levelBlack = tmp / 1000.0f;
 | 
			
		||||
        d.readS32(5, &m_lineTimeFactor, 0);
 | 
			
		||||
        d.readS32(6, &m_topTimeFactor, 25);
 | 
			
		||||
        d.readS32(7, &tmp, 0);
 | 
			
		||||
        m_atvModulation = static_cast<ATVModulation>(tmp);
 | 
			
		||||
        d.readS32(8, &tmp, 25);
 | 
			
		||||
@ -141,7 +133,6 @@ bool ATVDemodSettings::deserialize(const QByteArray& arrData)
 | 
			
		||||
        d.readS32(22, &m_amScalingFactor, 100);
 | 
			
		||||
        d.readS32(23, &m_amOffsetFactor, 0);
 | 
			
		||||
        d.readBool(24, &m_fftFiltering, false);
 | 
			
		||||
        d.readBool(25, &m_forceDecimator, false);
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
@ -303,33 +294,6 @@ float ATVDemodSettings::getNominalLineTime(int nbLines, int fps)
 | 
			
		||||
    return 1.0f / ((float) nbLines * (float) fps);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * calculates m_fltLineTimeMultiplier
 | 
			
		||||
 */
 | 
			
		||||
void ATVDemodSettings::lineTimeUpdate(unsigned int sampleRate)
 | 
			
		||||
{
 | 
			
		||||
    float nominalLineTime = getNominalLineTime(m_nbLines, m_fps);
 | 
			
		||||
    int lineTimeScaleFactor = (int) std::log10(nominalLineTime);
 | 
			
		||||
 | 
			
		||||
    if (sampleRate == 0) {
 | 
			
		||||
        m_fltLineTimeMultiplier = std::pow(10.0, lineTimeScaleFactor-3);
 | 
			
		||||
    } else {
 | 
			
		||||
        m_fltLineTimeMultiplier = 1.0f / sampleRate;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float ATVDemodSettings::getLineTime(unsigned int sampleRate)
 | 
			
		||||
{
 | 
			
		||||
    lineTimeUpdate(sampleRate);
 | 
			
		||||
    float nominalLineTime =  1.0f / ((float) m_nbLines * (float) m_fps);
 | 
			
		||||
    return nominalLineTime + m_fltLineTimeMultiplier * m_lineTimeFactor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float ATVDemodSettings::getTopTime(unsigned int sampleRate)
 | 
			
		||||
{
 | 
			
		||||
    return getNominalLineTime(m_nbLines, m_fps) * (4.7f / 64.0f) * (m_topTimeFactor / 100.0f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ATVDemodSettings::getRFSliderDivisor(unsigned int sampleRate)
 | 
			
		||||
{
 | 
			
		||||
    int scaleFactor = (int) std::log10(sampleRate/2);
 | 
			
		||||
@ -352,7 +316,7 @@ float ATVDemodSettings::getRFBandwidthDivisor(ATVModulation modulation)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ATVDemodSettings::getBaseValues(int sampleRate, int linesPerSecond, int& tvSampleRate, uint32_t& nbPointsPerLine)
 | 
			
		||||
void ATVDemodSettings::getBaseValues(int sampleRate, int linesPerSecond, uint32_t& nbPointsPerLine)
 | 
			
		||||
{
 | 
			
		||||
    int maxPoints = sampleRate / linesPerSecond;
 | 
			
		||||
    int i = maxPoints;
 | 
			
		||||
@ -365,5 +329,4 @@ void ATVDemodSettings::getBaseValues(int sampleRate, int linesPerSecond, int& tv
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    nbPointsPerLine = i == 0 ? maxPoints : i;
 | 
			
		||||
    tvSampleRate = nbPointsPerLine * linesPerSecond;
 | 
			
		||||
}
 | 
			
		||||
@ -47,7 +47,6 @@ struct ATVDemodSettings
 | 
			
		||||
 | 
			
		||||
    // RF settings
 | 
			
		||||
    qint64        m_inputFrequencyOffset; //!< Offset from baseband center frequency
 | 
			
		||||
    bool          m_forceDecimator;       //!< Force use of rational decimator when channel sample rate matches TV sample rate
 | 
			
		||||
    int           m_bfoFrequency;         //!< BFO frequency (Hz)
 | 
			
		||||
    ATVModulation m_atvModulation;        //!< RF modulation type
 | 
			
		||||
    float         m_fmDeviation;          //!< Expected FM deviation
 | 
			
		||||
@ -67,8 +66,6 @@ struct ATVDemodSettings
 | 
			
		||||
    bool          m_halfFrames;           //!< Toggle half frames processing
 | 
			
		||||
    float         m_levelSynchroTop;      //!< Horizontal synchronization top level (0.0 to 1.0 scale)
 | 
			
		||||
    float         m_levelBlack;           //!< Black level (0.0 to 1.0 scale)
 | 
			
		||||
    int           m_lineTimeFactor;       //!< added: +/- 100 something
 | 
			
		||||
    int           m_topTimeFactor;        //!< percentage of nominal horizontal top (pulse) time
 | 
			
		||||
 | 
			
		||||
    // common channel settings
 | 
			
		||||
    quint32 m_rgbColor;
 | 
			
		||||
@ -84,8 +81,6 @@ struct ATVDemodSettings
 | 
			
		||||
    QByteArray serialize() const;
 | 
			
		||||
    bool deserialize(const QByteArray& data);
 | 
			
		||||
 | 
			
		||||
    float getLineTime(unsigned int sampleRate);
 | 
			
		||||
    float getTopTime(unsigned int sampleRate);
 | 
			
		||||
    int getRFSliderDivisor(unsigned int sampleRate);
 | 
			
		||||
 | 
			
		||||
    static int getFps(int fpsIndex);
 | 
			
		||||
@ -94,12 +89,9 @@ struct ATVDemodSettings
 | 
			
		||||
    static int getNumberOfLinesIndex(int nbLines);
 | 
			
		||||
    static float getNominalLineTime(int nbLines, int fps);
 | 
			
		||||
    static float getRFBandwidthDivisor(ATVModulation modulation);
 | 
			
		||||
    static void getBaseValues(int sampleRate, int linesPerSecond, int& tvSampleRate, uint32_t& nbPointsPerLine);
 | 
			
		||||
    static void getBaseValues(int sampleRate, int linesPerSecond, uint32_t& nbPointsPerLine);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void lineTimeUpdate(unsigned int sampleRate);
 | 
			
		||||
 | 
			
		||||
    float m_fltLineTimeMultiplier;
 | 
			
		||||
    int m_rfSliderDivisor;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -30,8 +30,8 @@ const int ATVDemodSink::m_ssbFftLen = 1024;
 | 
			
		||||
ATVDemodSink::ATVDemodSink() :
 | 
			
		||||
    m_channelSampleRate(1000000),
 | 
			
		||||
    m_channelFrequencyOffset(0),
 | 
			
		||||
    m_tvSampleRate(1000000),
 | 
			
		||||
    m_samplesPerLine(100),
 | 
			
		||||
	m_samplesPerLineFrac(0.0f),
 | 
			
		||||
    m_videoTabIndex(0),
 | 
			
		||||
    m_scopeSink(nullptr),
 | 
			
		||||
    m_registeredTVScreen(nullptr),
 | 
			
		||||
@ -53,19 +53,16 @@ ATVDemodSink::ATVDemodSink() :
 | 
			
		||||
    m_ampAverage(4800),
 | 
			
		||||
    m_bfoPLL(200/1000000, 100/1000000, 0.01),
 | 
			
		||||
    m_bfoFilter(200.0, 1000000.0, 0.9),
 | 
			
		||||
    m_interpolatorDistance(1.0f),
 | 
			
		||||
    m_interpolatorDistanceRemain(0.0f),
 | 
			
		||||
    m_DSBFilter(nullptr),
 | 
			
		||||
    m_DSBFilterBuffer(nullptr),
 | 
			
		||||
    m_DSBFilterBufferIndex(0)
 | 
			
		||||
{
 | 
			
		||||
    qDebug("ATVDemodSink::ATVDemodSink");
 | 
			
		||||
    //*************** ATV PARAMETERS  ***************
 | 
			
		||||
    //m_intNumberSamplePerLine=0;
 | 
			
		||||
    m_synchroSamples=0;
 | 
			
		||||
    m_interleaved = true;
 | 
			
		||||
 | 
			
		||||
    m_DSBFilter = new fftfilt(m_settings.m_fftBandwidth / (float) m_tvSampleRate, 2*m_ssbFftLen); // arbitrary cutoff
 | 
			
		||||
    m_DSBFilter = new fftfilt(m_settings.m_fftBandwidth / (float) m_channelSampleRate, 2*m_ssbFftLen); // arbitrary cutoff
 | 
			
		||||
    m_DSBFilterBuffer = new Complex[m_ssbFftLen];
 | 
			
		||||
    std::fill(m_DSBFilterBuffer, m_DSBFilterBuffer + m_ssbFftLen, Complex{0.0, 0.0});
 | 
			
		||||
    std::fill(m_fltBufferI, m_fltBufferI+6, 0.0f);
 | 
			
		||||
@ -97,19 +94,7 @@ void ATVDemodSink::feed(const SampleVector::const_iterator& begin, const SampleV
 | 
			
		||||
            c *= m_nco.nextIQ();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ((m_tvSampleRate == m_channelSampleRate) && (!m_settings.m_forceDecimator)) // no decimation
 | 
			
		||||
        {
 | 
			
		||||
            demod(c);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            Complex ci;
 | 
			
		||||
            if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci))
 | 
			
		||||
            {
 | 
			
		||||
                demod(ci);
 | 
			
		||||
                m_interpolatorDistanceRemain += m_interpolatorDistance;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        demod(c);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((m_videoTabIndex == 1) && (m_scopeSink)) // do only if scope tab is selected and scope is available
 | 
			
		||||
@ -327,9 +312,9 @@ void ATVDemodSink::demod(Complex& c)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ATVDemodSink::applyStandard(int sampleRate, const ATVDemodSettings& settings, float lineDuration)
 | 
			
		||||
void ATVDemodSink::applyStandard(int sampleRate, ATVDemodSettings::ATVStd atvStd, float lineDuration)
 | 
			
		||||
{
 | 
			
		||||
    switch(settings.m_atvStd)
 | 
			
		||||
    switch(atvStd)
 | 
			
		||||
    {
 | 
			
		||||
    case ATVDemodSettings::ATVStdHSkip:
 | 
			
		||||
        // what is left in a line for the image
 | 
			
		||||
@ -385,7 +370,7 @@ void ATVDemodSink::applyStandard(int sampleRate, const ATVDemodSettings& setting
 | 
			
		||||
    // Table 2. Details of line synchronizing signals
 | 
			
		||||
    m_numberSamplesPerLineSignals = (int)(lineDuration * sampleRate * 12.0  / 64.0); // "a", Line-blanking interval
 | 
			
		||||
    m_numberSamplesPerHSync       = (int)(lineDuration * sampleRate * 10.5  / 64.0); // "b", Interval between time datum and back edge of line-blanking pulse
 | 
			
		||||
    m_numberSamplesPerHTopNom     = (int)(lineDuration * sampleRate *  4.7  / 64.0); // "d", Duration of synchronizing pulse
 | 
			
		||||
    m_numberSamplesPerHTop        = (int)(lineDuration * sampleRate *  4.7  / 64.0); // "d", Duration of synchronizing pulse
 | 
			
		||||
 | 
			
		||||
    // Table 3. Details of field synchronizing signals
 | 
			
		||||
    float hl = 32.0f; // half of the line
 | 
			
		||||
@ -406,8 +391,6 @@ void ATVDemodSink::applyStandard(int sampleRate, const ATVDemodSettings& setting
 | 
			
		||||
 | 
			
		||||
    float vSyncDetectPercent = 0.5f;
 | 
			
		||||
    m_vSyncDetectThreshold = (int)(detectTotalLen * vSyncDetectPercent);
 | 
			
		||||
 | 
			
		||||
    m_numberSamplesPerHTop = m_numberSamplesPerHTopNom * (settings.m_topTimeFactor / 100.0f);  // adjust the value used in the system
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ATVDemodSink::getBFOLocked()
 | 
			
		||||
@ -440,43 +423,31 @@ void ATVDemodSink::applyChannelSettings(int channelSampleRate, int channelFreque
 | 
			
		||||
    if ((channelSampleRate != m_channelSampleRate) || force)
 | 
			
		||||
    {
 | 
			
		||||
        unsigned int samplesPerLineNom;
 | 
			
		||||
        ATVDemodSettings::getBaseValues(channelSampleRate, m_settings.m_nbLines * m_settings.m_fps, m_tvSampleRate, samplesPerLineNom);
 | 
			
		||||
        m_samplesPerLine = samplesPerLineNom + m_settings.m_lineTimeFactor;
 | 
			
		||||
        ATVDemodSettings::getBaseValues(channelSampleRate, m_settings.m_nbLines * m_settings.m_fps, samplesPerLineNom);
 | 
			
		||||
        m_samplesPerLine = samplesPerLineNom;
 | 
			
		||||
		m_samplesPerLineFrac = (float)channelSampleRate / (m_settings.m_nbLines * m_settings.m_fps) - m_samplesPerLine;
 | 
			
		||||
        qDebug() << "ATVDemodSink::applyChannelSettings:"
 | 
			
		||||
                << " m_tvSampleRate: " << m_tvSampleRate
 | 
			
		||||
                << " m_channelSampleRate: " << m_channelSampleRate
 | 
			
		||||
                << " m_fftBandwidth: " << m_settings.m_fftBandwidth
 | 
			
		||||
                << " m_fftOppBandwidth:" << m_settings.m_fftOppBandwidth
 | 
			
		||||
                << " m_bfoFrequency: " << m_settings.m_bfoFrequency;
 | 
			
		||||
 | 
			
		||||
        if (m_tvSampleRate > 0)
 | 
			
		||||
        {
 | 
			
		||||
            m_interpolatorDistanceRemain = 0;
 | 
			
		||||
            m_interpolatorDistance = (Real) m_tvSampleRate / (Real) channelSampleRate;
 | 
			
		||||
            m_interpolator.create(24,
 | 
			
		||||
                m_tvSampleRate,
 | 
			
		||||
                m_settings.m_fftBandwidth / ATVDemodSettings::getRFBandwidthDivisor(m_settings.m_atvModulation),
 | 
			
		||||
                3.0
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            m_tvSampleRate = channelSampleRate;
 | 
			
		||||
        }
 | 
			
		||||
        m_channelSampleRate = channelSampleRate;
 | 
			
		||||
 | 
			
		||||
        m_DSBFilter->create_asym_filter(
 | 
			
		||||
            m_settings.m_fftOppBandwidth / (float) m_tvSampleRate,
 | 
			
		||||
            m_settings.m_fftBandwidth / (float) m_tvSampleRate
 | 
			
		||||
            m_settings.m_fftOppBandwidth / (float) m_channelSampleRate,
 | 
			
		||||
            m_settings.m_fftBandwidth / (float) m_channelSampleRate
 | 
			
		||||
        );
 | 
			
		||||
        std::fill(m_DSBFilterBuffer, m_DSBFilterBuffer + m_ssbFftLen, Complex{0.0, 0.0});
 | 
			
		||||
        m_DSBFilterBufferIndex = 0;
 | 
			
		||||
 | 
			
		||||
        m_bfoPLL.configure((float) m_settings.m_bfoFrequency / (float) m_tvSampleRate,
 | 
			
		||||
                100.0 / m_tvSampleRate,
 | 
			
		||||
        m_bfoPLL.configure((float) m_settings.m_bfoFrequency / (float) m_channelSampleRate,
 | 
			
		||||
                100.0 / m_channelSampleRate,
 | 
			
		||||
                0.01);
 | 
			
		||||
        m_bfoFilter.setFrequencies(m_tvSampleRate, m_settings.m_bfoFrequency);
 | 
			
		||||
        m_bfoFilter.setFrequencies(m_channelSampleRate, m_settings.m_bfoFrequency);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    applyStandard(m_tvSampleRate, m_settings, ATVDemodSettings::getNominalLineTime(m_settings.m_nbLines, m_settings.m_fps));
 | 
			
		||||
    applyStandard(m_channelSampleRate, m_settings.m_atvStd, ATVDemodSettings::getNominalLineTime(m_settings.m_nbLines, m_settings.m_fps));
 | 
			
		||||
 | 
			
		||||
    if (m_registeredTVScreen)
 | 
			
		||||
    {
 | 
			
		||||
@ -497,7 +468,6 @@ void ATVDemodSink::applySettings(const ATVDemodSettings& settings, bool force)
 | 
			
		||||
{
 | 
			
		||||
    qDebug() << "ATVDemodSink::applySettings:"
 | 
			
		||||
            << "m_inputFrequencyOffset:" << settings.m_inputFrequencyOffset
 | 
			
		||||
            << "m_forceDecimator:" << settings.m_forceDecimator
 | 
			
		||||
            << "m_bfoFrequency:" << settings.m_bfoFrequency
 | 
			
		||||
            << "m_atvModulation:" << settings.m_atvModulation
 | 
			
		||||
            << "m_fmDeviation:" << settings.m_fmDeviation
 | 
			
		||||
@ -513,62 +483,47 @@ void ATVDemodSink::applySettings(const ATVDemodSettings& settings, bool force)
 | 
			
		||||
            << "m_halfFrames:" << settings.m_halfFrames
 | 
			
		||||
            << "m_levelSynchroTop:" << settings.m_levelSynchroTop
 | 
			
		||||
            << "m_levelBlack:" << settings.m_levelBlack
 | 
			
		||||
            << "m_lineTimeFactor:" << settings.m_lineTimeFactor
 | 
			
		||||
            << "m_topTimeFactor:" << settings.m_topTimeFactor
 | 
			
		||||
            << "m_rgbColor:" << settings.m_rgbColor
 | 
			
		||||
            << "m_title:" << settings.m_title
 | 
			
		||||
            << "m_udpAddress:" << settings.m_udpAddress
 | 
			
		||||
            << "m_udpPort:" << settings.m_udpPort
 | 
			
		||||
            << "force:" << force;
 | 
			
		||||
 | 
			
		||||
    if ((settings.m_nbLines != m_settings.m_nbLines)
 | 
			
		||||
     || (settings.m_fps != m_settings.m_fps)
 | 
			
		||||
     || (settings.m_atvStd != m_settings.m_atvStd)
 | 
			
		||||
     || (settings.m_atvModulation != m_settings.m_atvModulation)
 | 
			
		||||
     || (settings.m_fftBandwidth != m_settings.m_fftBandwidth)
 | 
			
		||||
     || (settings.m_fftOppBandwidth != m_settings.m_fftOppBandwidth)
 | 
			
		||||
     || (settings.m_atvStd != m_settings.m_atvStd)
 | 
			
		||||
     || (settings.m_lineTimeFactor != m_settings.m_lineTimeFactor) || force)
 | 
			
		||||
    if ((settings.m_fftBandwidth != m_settings.m_fftBandwidth)
 | 
			
		||||
     || (settings.m_fftOppBandwidth != m_settings.m_fftOppBandwidth) || force)
 | 
			
		||||
    {
 | 
			
		||||
        unsigned int samplesPerLineNom;
 | 
			
		||||
        ATVDemodSettings::getBaseValues(m_channelSampleRate, settings.m_nbLines * settings.m_fps, m_tvSampleRate, samplesPerLineNom);
 | 
			
		||||
        m_samplesPerLine = samplesPerLineNom + settings.m_lineTimeFactor;
 | 
			
		||||
        m_ampAverage.resize(m_samplesPerLine * m_settings.m_nbLines * 2); // AGC average in two full images
 | 
			
		||||
 | 
			
		||||
        qDebug() << "ATVDemodSink::applySettings:"
 | 
			
		||||
                << " m_tvSampleRate: " << m_tvSampleRate
 | 
			
		||||
                << " m_fftBandwidth: " << settings.m_fftBandwidth
 | 
			
		||||
                << " m_fftOppBandwidth:" << settings.m_fftOppBandwidth
 | 
			
		||||
                << " m_bfoFrequency: " << settings.m_bfoFrequency;
 | 
			
		||||
 | 
			
		||||
        if (m_tvSampleRate > 0)
 | 
			
		||||
        {
 | 
			
		||||
            m_interpolatorDistanceRemain = 0;
 | 
			
		||||
            m_interpolatorDistance = (Real) m_tvSampleRate / (Real) m_channelSampleRate;
 | 
			
		||||
            m_interpolator.create(24,
 | 
			
		||||
                m_tvSampleRate,
 | 
			
		||||
                settings.m_fftBandwidth / ATVDemodSettings::getRFBandwidthDivisor(settings.m_atvModulation),
 | 
			
		||||
                3.0
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            m_tvSampleRate = m_channelSampleRate;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_DSBFilter->create_asym_filter(
 | 
			
		||||
            settings.m_fftOppBandwidth / (float) m_tvSampleRate,
 | 
			
		||||
            settings.m_fftBandwidth / (float) m_tvSampleRate
 | 
			
		||||
            settings.m_fftOppBandwidth / (float) m_channelSampleRate,
 | 
			
		||||
            settings.m_fftBandwidth / (float) m_channelSampleRate
 | 
			
		||||
        );
 | 
			
		||||
        std::fill(m_DSBFilterBuffer, m_DSBFilterBuffer + m_ssbFftLen, Complex{0.0, 0.0});
 | 
			
		||||
        m_DSBFilterBufferIndex = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        m_bfoPLL.configure((float) settings.m_bfoFrequency / (float) m_tvSampleRate,
 | 
			
		||||
                100.0 / m_tvSampleRate,
 | 
			
		||||
    if ((settings.m_bfoFrequency != m_settings.m_bfoFrequency) || force)
 | 
			
		||||
    {
 | 
			
		||||
        m_bfoPLL.configure((float) settings.m_bfoFrequency / (float) m_channelSampleRate,
 | 
			
		||||
                100.0 / m_channelSampleRate,
 | 
			
		||||
                0.01);
 | 
			
		||||
        m_bfoFilter.setFrequencies(m_tvSampleRate, settings.m_bfoFrequency);
 | 
			
		||||
        m_bfoFilter.setFrequencies(m_channelSampleRate, settings.m_bfoFrequency);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        applyStandard(m_tvSampleRate, settings, ATVDemodSettings::getNominalLineTime(settings.m_nbLines, settings.m_fps));
 | 
			
		||||
    if ((settings.m_nbLines != m_settings.m_nbLines)
 | 
			
		||||
     || (settings.m_fps != m_settings.m_fps)
 | 
			
		||||
     || (settings.m_atvStd != m_settings.m_atvStd) || force)
 | 
			
		||||
    {
 | 
			
		||||
        unsigned int samplesPerLineNom;
 | 
			
		||||
        ATVDemodSettings::getBaseValues(m_channelSampleRate, settings.m_nbLines * settings.m_fps, samplesPerLineNom);
 | 
			
		||||
        m_samplesPerLine = samplesPerLineNom;
 | 
			
		||||
		m_samplesPerLineFrac = (float)m_channelSampleRate / (m_settings.m_nbLines * m_settings.m_fps) - m_samplesPerLine;
 | 
			
		||||
		m_ampAverage.resize(m_samplesPerLine * m_settings.m_nbLines * 2); // AGC average in two full images
 | 
			
		||||
 | 
			
		||||
        qDebug() << "ATVDemodSink::applySettings:"
 | 
			
		||||
                << " m_channelSampleRate: " << m_channelSampleRate
 | 
			
		||||
                << " m_samplesPerLine:" << m_samplesPerLine
 | 
			
		||||
                << " m_samplesPerLineFrac:" << m_samplesPerLineFrac;
 | 
			
		||||
 | 
			
		||||
        applyStandard(m_channelSampleRate, settings.m_atvStd, ATVDemodSettings::getNominalLineTime(settings.m_nbLines, settings.m_fps));
 | 
			
		||||
 | 
			
		||||
        if (m_registeredTVScreen)
 | 
			
		||||
        {
 | 
			
		||||
@ -582,10 +537,6 @@ void ATVDemodSink::applySettings(const ATVDemodSettings& settings, bool force)
 | 
			
		||||
        m_fieldIndex = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((settings.m_topTimeFactor != m_settings.m_topTimeFactor) || force) {
 | 
			
		||||
        m_numberSamplesPerHTop = m_numberSamplesPerHTopNom * (settings.m_topTimeFactor / 100.0f);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force) {
 | 
			
		||||
        m_objPhaseDiscri.setFMScaling(1.0f / settings.m_fmDeviation);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -97,9 +97,9 @@ private:
 | 
			
		||||
 | 
			
		||||
    int m_channelSampleRate;
 | 
			
		||||
	int m_channelFrequencyOffset;
 | 
			
		||||
    int m_tvSampleRate;
 | 
			
		||||
    int m_samplesPerLine;    //!< number of samples per complete line (includes sync signals) - adusted value
 | 
			
		||||
    ATVDemodSettings m_settings;
 | 
			
		||||
    int m_samplesPerLine;       //!< number of samples per complete line (includes sync signals) - adusted value
 | 
			
		||||
	float m_samplesPerLineFrac; //!< number of samples per complete line (includes sync signals), fractional part
 | 
			
		||||
	ATVDemodSettings m_settings;
 | 
			
		||||
    int m_videoTabIndex;
 | 
			
		||||
 | 
			
		||||
    //*************** SCOPE  ***************
 | 
			
		||||
@ -112,8 +112,7 @@ private:
 | 
			
		||||
	std::shared_ptr<TVScreenAnalogBuffer> m_tvScreenBuffer;
 | 
			
		||||
 | 
			
		||||
    //int m_intNumberSamplePerLine;
 | 
			
		||||
    int m_numberSamplesPerHTopNom;     //!< number of samples per horizontal synchronization pulse (pulse in ultra-black) - nominal value
 | 
			
		||||
    int m_numberSamplesPerHTop;        //!< number of samples per horizontal synchronization pulse (pulse in ultra-black) - adusted value
 | 
			
		||||
    int m_numberSamplesPerHTop;        //!< number of samples per horizontal synchronization pulse (pulse in ultra-black) - integer value
 | 
			
		||||
    int m_numberOfBlackLines;          //!< this is the total number of lines not part of the image and is used for vertical screen size
 | 
			
		||||
    int m_firstVisibleLine;
 | 
			
		||||
 | 
			
		||||
@ -161,7 +160,6 @@ private:
 | 
			
		||||
    int m_hSyncErrorCount;
 | 
			
		||||
 | 
			
		||||
    float prevSample;
 | 
			
		||||
 | 
			
		||||
    int m_avgColIndex;
 | 
			
		||||
 | 
			
		||||
    SampleVector m_sampleBuffer;
 | 
			
		||||
@ -177,11 +175,6 @@ private:
 | 
			
		||||
    SimplePhaseLock m_bfoPLL;
 | 
			
		||||
    SecondOrderRecursiveFilter m_bfoFilter;
 | 
			
		||||
 | 
			
		||||
    // Interpolator group for decimation and/or double sideband RF filtering
 | 
			
		||||
    Interpolator m_interpolator;
 | 
			
		||||
    Real m_interpolatorDistance;
 | 
			
		||||
    Real m_interpolatorDistanceRemain;
 | 
			
		||||
 | 
			
		||||
    // Used for vestigial SSB with asymmetrical filtering (needs double sideband scheme)
 | 
			
		||||
    fftfilt* m_DSBFilter;
 | 
			
		||||
    Complex* m_DSBFilterBuffer;
 | 
			
		||||
@ -191,10 +184,8 @@ private:
 | 
			
		||||
    // Used for FM
 | 
			
		||||
    PhaseDiscriminators m_objPhaseDiscri;
 | 
			
		||||
 | 
			
		||||
    //QElapsedTimer m_objTimer;
 | 
			
		||||
 | 
			
		||||
    void demod(Complex& c);
 | 
			
		||||
    void applyStandard(int sampleRate, const ATVDemodSettings& settings, float lineDuration);
 | 
			
		||||
    void applyStandard(int sampleRate, ATVDemodSettings::ATVStd atvStd, float lineDuration);
 | 
			
		||||
 | 
			
		||||
    inline void processSample(float& sample, int& sampleVideo)
 | 
			
		||||
    {
 | 
			
		||||
@ -206,7 +197,7 @@ private:
 | 
			
		||||
            // Horizontal Synchro detection
 | 
			
		||||
            if ((prevSample >= m_settings.m_levelSynchroTop &&
 | 
			
		||||
                sample < m_settings.m_levelSynchroTop) // horizontal synchro detected
 | 
			
		||||
                && (m_sampleOffsetDetected > m_samplesPerLine - m_numberSamplesPerHTopNom))
 | 
			
		||||
                && (m_sampleOffsetDetected > m_samplesPerLine - m_numberSamplesPerHTop))
 | 
			
		||||
            {
 | 
			
		||||
                float sampleOffsetDetectedFrac =
 | 
			
		||||
                    (sample - m_settings.m_levelSynchroTop) / (prevSample - sample);
 | 
			
		||||
@ -216,7 +207,7 @@ private:
 | 
			
		||||
                else if (hSyncShift < -m_samplesPerLine / 2)
 | 
			
		||||
					hSyncShift += m_samplesPerLine;
 | 
			
		||||
 | 
			
		||||
                if (fabs(hSyncShift) > m_numberSamplesPerHTopNom)
 | 
			
		||||
                if (fabs(hSyncShift) > m_numberSamplesPerHTop)
 | 
			
		||||
                {
 | 
			
		||||
                    m_hSyncErrorCount++;
 | 
			
		||||
                    if (m_hSyncErrorCount >= 4)
 | 
			
		||||
@ -252,7 +243,7 @@ private:
 | 
			
		||||
        {
 | 
			
		||||
			if (m_settings.m_hSync)
 | 
			
		||||
			{
 | 
			
		||||
				float sampleOffsetFloat = m_hSyncShift + m_sampleOffsetFrac;
 | 
			
		||||
				float sampleOffsetFloat = m_hSyncShift + m_sampleOffsetFrac - m_samplesPerLineFrac;
 | 
			
		||||
				m_sampleOffset = sampleOffsetFloat;
 | 
			
		||||
				m_sampleOffsetFrac = sampleOffsetFloat - m_sampleOffset;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@ -51,7 +51,6 @@ void ATVDemodWebAPIAdapter::webapiFormatChannelSettings(
 | 
			
		||||
        SWGSDRangel::SWGChannelSettings& response,
 | 
			
		||||
        const ATVDemodSettings& settings)
 | 
			
		||||
{
 | 
			
		||||
    response.getAtvDemodSettings()->setBlndecimatorEnable(settings.m_forceDecimator ? 1 : 0);
 | 
			
		||||
    response.getAtvDemodSettings()->setBlnFftFiltering(settings.m_fftFiltering ? 1 : 0);
 | 
			
		||||
    response.getAtvDemodSettings()->setBlnHSync(settings.m_hSync ? 1 : 0);
 | 
			
		||||
    response.getAtvDemodSettings()->setBlnInvertVideo(settings.m_invertVideo ? 1 : 0);
 | 
			
		||||
@ -71,11 +70,9 @@ void ATVDemodWebAPIAdapter::webapiFormatChannelSettings(
 | 
			
		||||
    response.getAtvDemodSettings()->setHalfImage(settings.m_halfFrames ? 1 : 0);
 | 
			
		||||
    response.getAtvDemodSettings()->setIntFrequencyOffset(settings.m_inputFrequencyOffset);
 | 
			
		||||
    response.getAtvDemodSettings()->setIntNumberOfLines(settings.m_nbLines);
 | 
			
		||||
    response.getAtvDemodSettings()->setLineTimeFactor(settings.m_lineTimeFactor);
 | 
			
		||||
    response.getAtvDemodSettings()->setNbLinesIndex(ATVDemodSettings::getNumberOfLinesIndex(settings.m_nbLines));
 | 
			
		||||
    response.getAtvDemodSettings()->setRgbColor(settings.m_rgbColor);
 | 
			
		||||
    response.getAtvDemodSettings()->setTitle(new QString(settings.m_title));
 | 
			
		||||
    response.getAtvDemodSettings()->setTopTimeFactor(settings.m_topTimeFactor);
 | 
			
		||||
    response.getAtvDemodSettings()->setUdpAddress(new QString(settings.m_udpAddress));
 | 
			
		||||
    response.getAtvDemodSettings()->setUdpPort(settings.m_udpPort);
 | 
			
		||||
}
 | 
			
		||||
@ -85,9 +82,6 @@ void ATVDemodWebAPIAdapter::webapiUpdateChannelSettings(
 | 
			
		||||
        const QStringList& channelSettingsKeys,
 | 
			
		||||
        SWGSDRangel::SWGChannelSettings& response)
 | 
			
		||||
{
 | 
			
		||||
    if (channelSettingsKeys.contains("blndecimatorEnable")) {
 | 
			
		||||
        settings.m_forceDecimator = response.getAtvDemodSettings()->getBlndecimatorEnable() != 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (channelSettingsKeys.contains("blnFFTFiltering")) {
 | 
			
		||||
        settings.m_fftFiltering = response.getAtvDemodSettings()->getBlnFftFiltering() != 0;
 | 
			
		||||
    }
 | 
			
		||||
@ -142,18 +136,12 @@ void ATVDemodWebAPIAdapter::webapiUpdateChannelSettings(
 | 
			
		||||
    if (channelSettingsKeys.contains("intNumberOfLines")) {
 | 
			
		||||
        settings.m_nbLines = response.getAtvDemodSettings()->getIntNumberOfLines();
 | 
			
		||||
    }
 | 
			
		||||
    if (channelSettingsKeys.contains("lineTimeFactor")) {
 | 
			
		||||
        settings.m_lineTimeFactor = response.getAtvDemodSettings()->getLineTimeFactor();
 | 
			
		||||
    }
 | 
			
		||||
    if (channelSettingsKeys.contains("rgbColor")) {
 | 
			
		||||
        settings.m_rgbColor = response.getAtvDemodSettings()->getRgbColor();
 | 
			
		||||
    }
 | 
			
		||||
    if (channelSettingsKeys.contains("title")) {
 | 
			
		||||
        settings.m_title = *response.getAtvDemodSettings()->getTitle();
 | 
			
		||||
    }
 | 
			
		||||
    if (channelSettingsKeys.contains("topTimeFactor")) {
 | 
			
		||||
        settings.m_topTimeFactor = response.getAtvDemodSettings()->getTopTimeFactor();
 | 
			
		||||
    }
 | 
			
		||||
    if (channelSettingsKeys.contains("udpAddress")) {
 | 
			
		||||
        settings.m_udpAddress = *response.getAtvDemodSettings()->getUdpAddress();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user