mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 13:00:26 -04:00 
			
		
		
		
	Channel analyzer NG: implemented optional RRC filter
This commit is contained in:
		
							parent
							
								
									1dcb84ef8f
								
							
						
					
					
						commit
						775a9775eb
					
				| @ -52,6 +52,7 @@ ChannelAnalyzerNG::ChannelAnalyzerNG(DeviceSourceAPI *deviceAPI) : | ||||
| 	m_inputFrequencyOffset = 0; | ||||
| 	SSBFilter = new fftfilt(m_settings.m_lowCutoff / m_inputSampleRate, m_settings.m_bandwidth / m_inputSampleRate, ssbFftLen); | ||||
| 	DSBFilter = new fftfilt(m_settings.m_bandwidth / m_inputSampleRate, 2*ssbFftLen); | ||||
| 	RRCFilter = new fftfilt(m_settings.m_bandwidth / m_inputSampleRate, 2*ssbFftLen); | ||||
| 	m_corr = new fftcorr(8*ssbFftLen); // 8k for 4k effective samples
 | ||||
| 	m_pll.computeCoefficients(0.002f, 0.5f, 10.0f); // bandwidth, damping factor, loop gain
 | ||||
| 
 | ||||
| @ -72,6 +73,7 @@ ChannelAnalyzerNG::~ChannelAnalyzerNG() | ||||
|     delete m_channelizer; | ||||
|     delete SSBFilter; | ||||
|     delete DSBFilter; | ||||
|     delete RRCFilter; | ||||
| } | ||||
| 
 | ||||
| void ChannelAnalyzerNG::configure(MessageQueue* messageQueue, | ||||
| @ -129,10 +131,17 @@ void ChannelAnalyzerNG::processOneSample(Complex& c, fftfilt::cmplx *sideband) | ||||
|     int n_out; | ||||
|     int decim = 1<<m_settings.m_spanLog2; | ||||
| 
 | ||||
|     if (m_settings.m_ssb) { | ||||
|     if (m_settings.m_ssb) | ||||
|     { | ||||
|         n_out = SSBFilter->runSSB(c, &sideband, m_usb); | ||||
|     } else { | ||||
|         n_out = DSBFilter->runDSB(c, &sideband); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         if (m_settings.m_rrc) { | ||||
|             n_out = RRCFilter->runFilt(c, &sideband); | ||||
|         } else { | ||||
|             n_out = DSBFilter->runDSB(c, &sideband); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     for (int i = 0; i < n_out; i++) | ||||
| @ -293,6 +302,7 @@ void ChannelAnalyzerNG::setFilters(int sampleRate, float bandwidth, float lowCut | ||||
| 
 | ||||
|     SSBFilter->create_filter(lowCutoff / sampleRate, bandwidth / sampleRate); | ||||
|     DSBFilter->create_dsb_filter(bandwidth / sampleRate); | ||||
|     RRCFilter->create_rrc_filter(bandwidth / sampleRate, m_settings.m_rrcRolloff / 100.0); | ||||
| } | ||||
| 
 | ||||
| void ChannelAnalyzerNG::applySettings(const ChannelAnalyzerNGSettings& settings, bool force) | ||||
| @ -300,6 +310,8 @@ void ChannelAnalyzerNG::applySettings(const ChannelAnalyzerNGSettings& settings, | ||||
|     qDebug() << "ChannelAnalyzerNG::applySettings:" | ||||
|             << " m_downSample: " << settings.m_downSample | ||||
|             << " m_downSampleRate: " << settings.m_downSampleRate | ||||
|             << " m_rcc: " << settings.m_rrc | ||||
|             << " m_rrcRolloff: " << settings.m_rrcRolloff / 100.0 | ||||
|             << " m_bandwidth: " << settings.m_bandwidth | ||||
|             << " m_lowCutoff: " << settings.m_lowCutoff | ||||
|             << " m_spanLog2: " << settings.m_spanLog2 | ||||
| @ -338,6 +350,14 @@ void ChannelAnalyzerNG::applySettings(const ChannelAnalyzerNGSettings& settings, | ||||
|         m_settingsMutex.unlock(); | ||||
|     } | ||||
| 
 | ||||
|     if ((settings.m_rrcRolloff != m_settings.m_rrcRolloff) || force) | ||||
|     { | ||||
|         float sampleRate = settings.m_downSample ? (float) settings.m_downSampleRate : (float) m_inputSampleRate; | ||||
|         m_settingsMutex.lock(); | ||||
|         RRCFilter->create_rrc_filter(settings.m_bandwidth / sampleRate, settings.m_rrcRolloff / 100.0); | ||||
|         m_settingsMutex.unlock(); | ||||
|     } | ||||
| 
 | ||||
|     if ((settings.m_spanLog2 != m_settings.m_spanLog2) || force) | ||||
|     { | ||||
|         int sampleRate = (settings.m_downSample ? settings.m_downSampleRate : m_inputSampleRate) / (1<<m_settings.m_spanLog2); | ||||
|  | ||||
| @ -231,6 +231,7 @@ private: | ||||
| 
 | ||||
| 	fftfilt* SSBFilter; | ||||
| 	fftfilt* DSBFilter; | ||||
| 	fftfilt* RRCFilter; | ||||
| 	fftcorr* m_corr; | ||||
| 
 | ||||
| 	BasebandSampleSink* m_sampleSink; | ||||
|  | ||||
| @ -114,6 +114,9 @@ void ChannelAnalyzerNGGUI::displaySettings() | ||||
|     ui->spanLog2->setCurrentIndex(m_settings.m_spanLog2); | ||||
|     displayPLLSettings(); | ||||
|     ui->signalSelect->setCurrentIndex((int) m_settings.m_inputType); | ||||
|     ui->rrcFilter->setChecked(m_settings.m_rrc); | ||||
|     QString rolloffStr = QString::number(m_settings.m_rrcRolloff/100.0, 'f', 2); | ||||
|     ui->rrcRolloffText->setText(rolloffStr); | ||||
| 
 | ||||
|     blockApplySettings(false); | ||||
| } | ||||
| @ -291,6 +294,20 @@ void ChannelAnalyzerNGGUI::on_deltaFrequency_changed(qint64 value) | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| void ChannelAnalyzerNGGUI::on_rrcFilter_toggled(bool checked) | ||||
| { | ||||
|     m_settings.m_rrc = checked; | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| void ChannelAnalyzerNGGUI::on_rrcRolloff_valueChanged(int value) | ||||
| { | ||||
|     m_settings.m_rrcRolloff = value; | ||||
|     QString rolloffStr = QString::number(value/100.0, 'f', 2); | ||||
|     ui->rrcRolloffText->setText(rolloffStr); | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| void ChannelAnalyzerNGGUI::on_BW_valueChanged(int value __attribute__((unused))) | ||||
| { | ||||
|     setFiltersUIBoundaries(); | ||||
|  | ||||
| @ -99,6 +99,8 @@ private slots: | ||||
|     void on_pllPskOrder_currentIndexChanged(int index); | ||||
|     void on_useRationalDownsampler_toggled(bool checked); | ||||
|     void on_signalSelect_currentIndexChanged(int index); | ||||
|     void on_rrcFilter_toggled(bool checked); | ||||
|     void on_rrcRolloff_valueChanged(int value); | ||||
| 	void on_BW_valueChanged(int value); | ||||
| 	void on_lowCut_valueChanged(int value); | ||||
| 	void on_spanLog2_currentIndexChanged(int index); | ||||
|  | ||||
| @ -419,6 +419,58 @@ | ||||
|     </item> | ||||
|     <item> | ||||
|      <layout class="QHBoxLayout" name="BWLayout"> | ||||
|       <item> | ||||
|        <widget class="ButtonSwitch" name="rrcFilter"> | ||||
|         <property name="toolTip"> | ||||
|          <string>Toggle RRC filter</string> | ||||
|         </property> | ||||
|         <property name="text"> | ||||
|          <string/> | ||||
|         </property> | ||||
|         <property name="icon"> | ||||
|          <iconset resource="../../../sdrgui/resources/res.qrc"> | ||||
|           <normaloff>:/dsb.png</normaloff>:/dsb.png</iconset> | ||||
|         </property> | ||||
|         <property name="checkable"> | ||||
|          <bool>true</bool> | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|       <item> | ||||
|        <widget class="QDial" name="rrcRolloff"> | ||||
|         <property name="maximumSize"> | ||||
|          <size> | ||||
|           <width>24</width> | ||||
|           <height>24</height> | ||||
|          </size> | ||||
|         </property> | ||||
|         <property name="toolTip"> | ||||
|          <string>Tune RRC filter rolloff factor</string> | ||||
|         </property> | ||||
|         <property name="minimum"> | ||||
|          <number>10</number> | ||||
|         </property> | ||||
|         <property name="maximum"> | ||||
|          <number>50</number> | ||||
|         </property> | ||||
|         <property name="pageStep"> | ||||
|          <number>1</number> | ||||
|         </property> | ||||
|         <property name="value"> | ||||
|          <number>30</number> | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|       <item> | ||||
|        <widget class="QLabel" name="rrcRolloffText"> | ||||
|         <property name="toolTip"> | ||||
|          <string>RRC filter rolloff factor value</string> | ||||
|         </property> | ||||
|         <property name="text"> | ||||
|          <string>0.00</string> | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|       <item> | ||||
|        <widget class="QLabel" name="BWLabel"> | ||||
|         <property name="minimumSize"> | ||||
|  | ||||
| @ -40,6 +40,8 @@ void ChannelAnalyzerNGSettings::resetToDefaults() | ||||
|     m_ssb = false; | ||||
|     m_pll = false; | ||||
|     m_fll = false; | ||||
|     m_rrc = false; | ||||
|     m_rrcRolloff = 30; // 0.3
 | ||||
|     m_pllPskOrder = 1; | ||||
|     m_inputType = InputSignal; | ||||
|     m_rgbColor = QColor(128, 128, 128).rgb(); | ||||
| @ -65,6 +67,8 @@ QByteArray ChannelAnalyzerNGSettings::serialize() const | ||||
|     s.writeU32(13, m_pllPskOrder); | ||||
|     s.writeS32(14, (int) m_inputType); | ||||
|     s.writeString(15, m_title); | ||||
|     s.writeBool(16, m_rrc); | ||||
|     s.writeU32(17, m_rrcRolloff); | ||||
| 
 | ||||
|     return s.final(); | ||||
| } | ||||
| @ -110,6 +114,8 @@ bool ChannelAnalyzerNGSettings::deserialize(const QByteArray& data) | ||||
|         d.readS32(14, &tmp, 0); | ||||
|         m_inputType = (InputType) tmp; | ||||
|         d.readString(15, &m_title, "Channel Analyzer NG"); | ||||
|         d.readBool(16, &m_rrc, false); | ||||
|         d.readU32(17, &m_rrcRolloff, 30); | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| @ -39,6 +39,8 @@ struct ChannelAnalyzerNGSettings | ||||
|     bool m_ssb; | ||||
|     bool m_pll; | ||||
|     bool m_fll; | ||||
|     bool m_rrc; | ||||
|     quint32 m_rrcRolloff; //!< in 100ths
 | ||||
|     unsigned int m_pllPskOrder; | ||||
|     InputType m_inputType; | ||||
|     quint32 m_rgbColor; | ||||
|  | ||||
| @ -69,7 +69,7 @@ protected: | ||||
| 	{ | ||||
|         float x = i/(float)len; // normalize to [0..1]
 | ||||
|         x = 0.5-fabs(x-0.5); // apply symmetry: now both halves overlap near 0
 | ||||
|         float tr = (fb*a)/2.0; // half the transition zone
 | ||||
|         float tr = fb*a; // half the transition zone
 | ||||
| 
 | ||||
|         if (x < fb-tr) | ||||
|         { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user