From e76e2321c1744222a51d83de1d7558ed1fe0047d Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 18 Aug 2020 16:23:40 +0200 Subject: [PATCH] ATV demod: effective support of random channel sample rate --- plugins/channelrx/demodatv/atvdemod.cpp | 3 - plugins/channelrx/demodatv/atvdemodgui.cpp | 90 +++------- plugins/channelrx/demodatv/atvdemodgui.h | 5 - plugins/channelrx/demodatv/atvdemodgui.ui | 160 +++++------------- .../channelrx/demodatv/atvdemodsettings.cpp | 39 +---- plugins/channelrx/demodatv/atvdemodsettings.h | 10 +- plugins/channelrx/demodatv/atvdemodsink.cpp | 137 +++++---------- plugins/channelrx/demodatv/atvdemodsink.h | 25 +-- .../demodatv/atvdemodwebapiadapter.cpp | 12 -- 9 files changed, 123 insertions(+), 358 deletions(-) diff --git a/plugins/channelrx/demodatv/atvdemod.cpp b/plugins/channelrx/demodatv/atvdemod.cpp index dd81e85ad..7ce1a9eb2 100644 --- a/plugins/channelrx/demodatv/atvdemod.cpp +++ b/plugins/channelrx/demodatv/atvdemod.cpp @@ -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 diff --git a/plugins/channelrx/demodatv/atvdemodgui.cpp b/plugins/channelrx/demodatv/atvdemodgui.cpp index 02d7f91cc..fc3dde666 100644 --- a/plugins/channelrx/demodatv/atvdemodgui.cpp +++ b/plugins/channelrx/demodatv/atvdemodgui.cpp @@ -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)); } diff --git a/plugins/channelrx/demodatv/atvdemodgui.h b/plugins/channelrx/demodatv/atvdemodgui.h index 067228f7d..763eb37e8 100644 --- a/plugins/channelrx/demodatv/atvdemodgui.h +++ b/plugins/channelrx/demodatv/atvdemodgui.h @@ -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); diff --git a/plugins/channelrx/demodatv/atvdemodgui.ui b/plugins/channelrx/demodatv/atvdemodgui.ui index 02641c0fd..628836dca 100644 --- a/plugins/channelrx/demodatv/atvdemodgui.ui +++ b/plugins/channelrx/demodatv/atvdemodgui.ui @@ -7,7 +7,7 @@ 0 0 700 - 743 + 699 @@ -114,23 +114,6 @@ - - - - Toggle decimator on/off - - - - - - - :/arrow_down.png:/arrow_down.png - - - true - - - @@ -592,7 +575,7 @@ 10 570 681 - 81 + 104 @@ -903,19 +886,6 @@ - - - - Black level value - - - <html><head/><body><p align="right">mV</p></body></html> - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - @@ -936,14 +906,27 @@ - + + + + Qt::Horizontal + + + + 40 + 20 + + + + + <html><head/><body><p>Black Lvl</p></body></html> - + Black level @@ -965,38 +948,42 @@ - - + + + + Black level value + - Line + <html><head/><body><p align="right">mV</p></body></html> + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - + + + + + 62 + 0 + + - Line length adjustment + Effective line length value - - -100 + + <html><head/><body><p align="right">&mu;S</p></body></html> - - 100 + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - 1 - - - 1 - - - 0 - - - 0 - - - Qt::Horizontal + + + + + + Line @@ -1007,31 +994,6 @@ - - - - Horizontal sync pulse length adjustment - - - 1 - - - 100 - - - 1 - - - 1 - - - 25 - - - Qt::Horizontal - - - @@ -1051,38 +1013,6 @@ - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 62 - 0 - - - - Effective line length value - - - <html><head/><body><p align="right">&mu;S</p></body></html> - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - diff --git a/plugins/channelrx/demodatv/atvdemodsettings.cpp b/plugins/channelrx/demodatv/atvdemodsettings.cpp index f8163992b..78beae444 100644 --- a/plugins/channelrx/demodatv/atvdemodsettings.cpp +++ b/plugins/channelrx/demodatv/atvdemodsettings.cpp @@ -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(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; } \ No newline at end of file diff --git a/plugins/channelrx/demodatv/atvdemodsettings.h b/plugins/channelrx/demodatv/atvdemodsettings.h index 538a62ef1..1f7b4e5ef 100644 --- a/plugins/channelrx/demodatv/atvdemodsettings.h +++ b/plugins/channelrx/demodatv/atvdemodsettings.h @@ -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; }; diff --git a/plugins/channelrx/demodatv/atvdemodsink.cpp b/plugins/channelrx/demodatv/atvdemodsink.cpp index 09f1559e1..6d031d327 100644 --- a/plugins/channelrx/demodatv/atvdemodsink.cpp +++ b/plugins/channelrx/demodatv/atvdemodsink.cpp @@ -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); } diff --git a/plugins/channelrx/demodatv/atvdemodsink.h b/plugins/channelrx/demodatv/atvdemodsink.h index 53221a91e..dc4e71dce 100644 --- a/plugins/channelrx/demodatv/atvdemodsink.h +++ b/plugins/channelrx/demodatv/atvdemodsink.h @@ -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 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; } diff --git a/plugins/channelrx/demodatv/atvdemodwebapiadapter.cpp b/plugins/channelrx/demodatv/atvdemodwebapiadapter.cpp index e2902d71d..fa2ca20c0 100644 --- a/plugins/channelrx/demodatv/atvdemodwebapiadapter.cpp +++ b/plugins/channelrx/demodatv/atvdemodwebapiadapter.cpp @@ -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(); }