From 9a3585a7568b1375ac6e2c59f65f3151f27bd0cb Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Thu, 12 Nov 2020 13:25:49 +0000 Subject: [PATCH] Reduce interpolator taps to enable it to run in real-time. Should significantly improve PER for RTLSDR at 2.4MSa/s. Add developer controls to adjust interpolator settings. Fix tab-order in GUI. --- plugins/channelrx/demodadsb/adsbdemodgui.cpp | 27 ++++ plugins/channelrx/demodadsb/adsbdemodgui.h | 2 + plugins/channelrx/demodadsb/adsbdemodgui.ui | 116 +++++++++++++++++- .../channelrx/demodadsb/adsbdemodsettings.cpp | 6 + .../channelrx/demodadsb/adsbdemodsettings.h | 2 + plugins/channelrx/demodadsb/adsbdemodsink.cpp | 53 ++++---- 6 files changed, 180 insertions(+), 26 deletions(-) diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.cpp b/plugins/channelrx/demodadsb/adsbdemodgui.cpp index eee08a21c..9eae4e952 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodgui.cpp @@ -1214,6 +1214,21 @@ void ADSBDemodGUI::on_threshold_valueChanged(int value) applySettings(); } +void ADSBDemodGUI::on_phaseSteps_valueChanged(int value) +{ + ui->phaseStepsText->setText(QString("%1").arg(value)); + m_settings.m_interpolatorPhaseSteps = value; + applySettings(); +} + +void ADSBDemodGUI::on_tapsPerPhase_valueChanged(int value) +{ + Real tapsPerPhase = ((Real)value)/10.0f; + ui->tapsPerPhaseText->setText(QString("%1").arg(tapsPerPhase, 0, 'f', 1)); + m_settings.m_interpolatorTapsPerPhase = tapsPerPhase; + applySettings(); +} + void ADSBDemodGUI::on_feed_clicked(bool checked) { m_settings.m_feedEnabled = checked; @@ -1927,6 +1942,18 @@ void ADSBDemodGUI::displaySettings() ui->thresholdText->setText(QString("%1").arg(m_settings.m_correlationThreshold, 0, 'f', 1)); ui->threshold->setValue((int)(m_settings.m_correlationThreshold*10.0f)); + ui->phaseStepsText->setText(QString("%1").arg(m_settings.m_interpolatorPhaseSteps)); + ui->phaseSteps->setValue(m_settings.m_interpolatorPhaseSteps); + ui->tapsPerPhaseText->setText(QString("%1").arg(m_settings.m_interpolatorTapsPerPhase, 0, 'f', 1)); + ui->tapsPerPhase->setValue((int)(m_settings.m_interpolatorTapsPerPhase*10.0f)); + // Enable these controls only for developers + if (1) + { + ui->phaseStepsText->setVisible(false); + ui->phaseSteps->setVisible(false); + ui->tapsPerPhaseText->setVisible(false); + ui->tapsPerPhase->setVisible(false); + } ui->feed->setChecked(m_settings.m_feedEnabled); ui->flightPaths->setChecked(m_settings.m_flightPaths); diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.h b/plugins/channelrx/demodadsb/adsbdemodgui.h index 347003611..04e82c3a8 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.h +++ b/plugins/channelrx/demodadsb/adsbdemodgui.h @@ -528,6 +528,8 @@ private slots: void on_deltaFrequency_changed(qint64 value); void on_rfBW_valueChanged(int value); void on_threshold_valueChanged(int value); + void on_phaseSteps_valueChanged(int value); + void on_tapsPerPhase_valueChanged(int value); void on_adsbData_cellClicked(int row, int column); void on_adsbData_cellDoubleClicked(int row, int column); void adsbData_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex); diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.ui b/plugins/channelrx/demodadsb/adsbdemodgui.ui index d02baadfc..95886ee4e 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.ui +++ b/plugins/channelrx/demodadsb/adsbdemodgui.ui @@ -6,7 +6,7 @@ 0 0 - 384 + 435 1046 @@ -36,7 +36,7 @@ 0 0 - 381 + 431 141 @@ -167,6 +167,13 @@ + + + + Qt::Vertical + + + @@ -203,10 +210,17 @@ + + + + Qt::Vertical + + + - RFBW + BW @@ -262,6 +276,85 @@ + + + + + 24 + 24 + + + + Interpolator phase steps + + + 1 + + + 16 + + + 1 + + + 16 + + + + + + + + 16 + 0 + + + + 12 + + + + + + + true + + + + 24 + 24 + + + + Interpolator taps per phase + + + 10 + + + 60 + + + 1 + + + 45 + + + + + + + + 16 + 0 + + + + 4.5 + + + @@ -547,7 +640,7 @@ 0 140 - 381 + 431 291 @@ -787,7 +880,7 @@ 10 450 - 361 + 421 581 @@ -879,8 +972,21 @@ deltaFrequency rfBW + phaseSteps + tapsPerPhase spb + demodModeS + correlateFullPreamble threshold + getOSNDB + getAirportDB + displaySettings + flightPaths + feed + devicesRefresh + device + adsbData + map diff --git a/plugins/channelrx/demodadsb/adsbdemodsettings.cpp b/plugins/channelrx/demodadsb/adsbdemodsettings.cpp index 464db1aa7..c8edf7997 100644 --- a/plugins/channelrx/demodadsb/adsbdemodsettings.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodsettings.cpp @@ -61,6 +61,8 @@ void ADSBDemodSettings::resetToDefaults() m_demodModeS = false; m_deviceIndex = -1; m_autoResizeTableColumns = false; + m_interpolatorPhaseSteps = 4; // Higher than these two values will struggle to run in real-time + m_interpolatorTapsPerPhase = 3.5f; // without gaining much improvement in PER for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) { m_columnIndexes[i] = i; @@ -105,6 +107,8 @@ QByteArray ADSBDemodSettings::serialize() const s.writeBool(28, m_correlateFullPreamble); s.writeBool(29, m_demodModeS); s.writeBool(30, m_autoResizeTableColumns); + s.writeS32(31, m_interpolatorPhaseSteps); + s.writeFloat(32, m_interpolatorTapsPerPhase); for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) s.writeS32(100 + i, m_columnIndexes[i]); @@ -182,6 +186,8 @@ bool ADSBDemodSettings::deserialize(const QByteArray& data) d.readBool(28, &m_correlateFullPreamble, true); d.readBool(29, &m_demodModeS, false); d.readBool(30, &m_autoResizeTableColumns, false); + d.readS32(31, &m_interpolatorPhaseSteps, 4); + d.readFloat(32, &m_interpolatorTapsPerPhase, 3.5f); for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) d.readS32(100 + i, &m_columnIndexes[i], i); diff --git a/plugins/channelrx/demodadsb/adsbdemodsettings.h b/plugins/channelrx/demodadsb/adsbdemodsettings.h index c8d1d621d..081e5934d 100644 --- a/plugins/channelrx/demodadsb/adsbdemodsettings.h +++ b/plugins/channelrx/demodadsb/adsbdemodsettings.h @@ -74,6 +74,8 @@ struct ADSBDemodSettings bool m_demodModeS; //!< Demodulate all Mode-S frames, not just ADS-B int m_deviceIndex; //!< Device to set to ATC frequencies bool m_autoResizeTableColumns; + int m_interpolatorPhaseSteps; + float m_interpolatorTapsPerPhase; ADSBDemodSettings(); void resetToDefaults(); diff --git a/plugins/channelrx/demodadsb/adsbdemodsink.cpp b/plugins/channelrx/demodadsb/adsbdemodsink.cpp index 80ee2a517..1983f82f4 100644 --- a/plugins/channelrx/demodadsb/adsbdemodsink.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodsink.cpp @@ -83,33 +83,41 @@ void ADSBDemodSink::feed(const SampleVector::const_iterator& begin, const Sample processOneSample(magsq); } } - else + else if (m_interpolatorDistance == 1.0f) // just apply offset { for (SampleVector::const_iterator it = begin; it != end; ++it) { Complex c(it->real(), it->imag()); Complex ci; c *= m_nco.nextIQ(); - - if (m_interpolatorDistance == 1.0f) + processOneSample(complexMagSq(c)); + } + } + else if (m_interpolatorDistance < 1.0f) // interpolate + { + for (SampleVector::const_iterator it = begin; it != end; ++it) + { + Complex c(it->real(), it->imag()); + Complex ci; + c *= m_nco.nextIQ(); + while (!m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci)) { - processOneSample(complexMagSq(c)); + processOneSample(complexMagSq(ci)); + m_interpolatorDistanceRemain += m_interpolatorDistance; } - else if (m_interpolatorDistance < 1.0f) // interpolate + } + } + else // decimate + { + for (SampleVector::const_iterator it = begin; it != end; ++it) + { + Complex c(it->real(), it->imag()); + Complex ci; + c *= m_nco.nextIQ(); + if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci)) { - while (!m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci)) - { - processOneSample(complexMagSq(ci)); - m_interpolatorDistanceRemain += m_interpolatorDistance; - } - } - else // decimate - { - if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci)) - { - processOneSample(complexMagSq(ci)); - m_interpolatorDistanceRemain += m_interpolatorDistance; - } + processOneSample(complexMagSq(ci)); + m_interpolatorDistanceRemain += m_interpolatorDistance; } } } @@ -228,7 +236,7 @@ void ADSBDemodSink::applyChannelSettings(int channelSampleRate, int channelFrequ if ((channelSampleRate != m_channelSampleRate) || force) { - m_interpolator.create(16, channelSampleRate, m_settings.m_rfBandwidth / 2.2); + m_interpolator.create(m_settings.m_interpolatorPhaseSteps, channelSampleRate, m_settings.m_rfBandwidth / 2.2, m_settings.m_interpolatorTapsPerPhase); m_interpolatorDistanceRemain = 0; m_interpolatorDistance = (Real) channelSampleRate / (Real) (ADS_B_BITS_PER_SECOND * m_settings.m_samplesPerBit); } @@ -249,9 +257,12 @@ void ADSBDemodSink::applySettings(const ADSBDemodSettings& settings, bool force) << " force: " << force; if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) - || (settings.m_samplesPerBit != m_settings.m_samplesPerBit) || force) + || (settings.m_samplesPerBit != m_settings.m_samplesPerBit) + || (settings.m_interpolatorPhaseSteps != m_settings.m_interpolatorPhaseSteps) + || (settings.m_interpolatorTapsPerPhase != m_settings.m_interpolatorTapsPerPhase) + || force) { - m_interpolator.create(16, m_channelSampleRate, settings.m_rfBandwidth / 2.2); + m_interpolator.create(m_settings.m_interpolatorPhaseSteps, m_channelSampleRate, settings.m_rfBandwidth / 2.2, m_settings.m_interpolatorTapsPerPhase); m_interpolatorDistanceRemain = 0; m_interpolatorDistance = (Real) m_channelSampleRate / (Real) (ADS_B_BITS_PER_SECOND * settings.m_samplesPerBit); }