mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-03-23 12:48:49 -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…
Reference in New Issue
Block a user