kopia lustrzana https://github.com/f4exb/sdrangel
				
				
				
			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.pull/704/head
							rodzic
							
								
									21956dc9d0
								
							
						
					
					
						commit
						9a3585a756
					
				|  | @ -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); | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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"/> | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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(); | ||||
|  |  | |||
|  | @ -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); | ||||
|     } | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Jon Beniston
						Jon Beniston