1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-02-03 09:44:01 -05:00

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.
This commit is contained in:
Jon Beniston 2020-11-12 13:25:49 +00:00
parent 21956dc9d0
commit 9a3585a756
6 changed files with 180 additions and 26 deletions

View File

@ -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);

View File

@ -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);

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>384</width>
<width>435</width>
<height>1046</height>
</rect>
</property>
@ -36,7 +36,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>381</width>
<width>431</width>
<height>141</height>
</rect>
</property>
@ -167,6 +167,13 @@
</item>
<item>
<layout class="QHBoxLayout" name="levelMeterLayout">
<item>
<widget class="Line" name="line_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="channelPowerMeterUnits">
<property name="text">
@ -203,10 +210,17 @@
</item>
<item>
<layout class="QHBoxLayout" name="rfBWLayout">
<item>
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="rfBWLabel">
<property name="text">
<string>RFBW</string>
<string>BW</string>
</property>
</widget>
</item>
@ -262,6 +276,85 @@
</property>
</widget>
</item>
<item>
<widget class="QDial" name="phaseSteps">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>Interpolator phase steps</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>16</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>16</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="phaseStepsText">
<property name="minimumSize">
<size>
<width>16</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>12</string>
</property>
</widget>
</item>
<item>
<widget class="QDial" name="tapsPerPhase">
<property name="enabled">
<bool>true</bool>
</property>
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>Interpolator taps per phase</string>
</property>
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>60</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>45</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="tapsPerPhaseText">
<property name="minimumSize">
<size>
<width>16</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>4.5</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="spbrLabel">
<property name="text">
@ -547,7 +640,7 @@
<rect>
<x>0</x>
<y>140</y>
<width>381</width>
<width>431</width>
<height>291</height>
</rect>
</property>
@ -787,7 +880,7 @@
<rect>
<x>10</x>
<y>450</y>
<width>361</width>
<width>421</width>
<height>581</height>
</rect>
</property>
@ -879,8 +972,21 @@
<tabstops>
<tabstop>deltaFrequency</tabstop>
<tabstop>rfBW</tabstop>
<tabstop>phaseSteps</tabstop>
<tabstop>tapsPerPhase</tabstop>
<tabstop>spb</tabstop>
<tabstop>demodModeS</tabstop>
<tabstop>correlateFullPreamble</tabstop>
<tabstop>threshold</tabstop>
<tabstop>getOSNDB</tabstop>
<tabstop>getAirportDB</tabstop>
<tabstop>displaySettings</tabstop>
<tabstop>flightPaths</tabstop>
<tabstop>feed</tabstop>
<tabstop>devicesRefresh</tabstop>
<tabstop>device</tabstop>
<tabstop>adsbData</tabstop>
<tabstop>map</tabstop>
</tabstops>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>

View File

@ -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);

View File

@ -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();

View File

@ -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);
}