Channel analyzer NG: implemented optional RRC filter

This commit is contained in:
f4exb 2018-05-22 02:20:36 +02:00
parent 1dcb84ef8f
commit 775a9775eb
8 changed files with 104 additions and 4 deletions

View File

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

View File

@ -231,6 +231,7 @@ private:
fftfilt* SSBFilter;
fftfilt* DSBFilter;
fftfilt* RRCFilter;
fftcorr* m_corr;
BasebandSampleSink* m_sampleSink;

View File

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

View File

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

View File

@ -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">

View File

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

View File

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

View File

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