mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-05-30 22:02: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;
|
m_inputFrequencyOffset = 0;
|
||||||
SSBFilter = new fftfilt(m_settings.m_lowCutoff / m_inputSampleRate, m_settings.m_bandwidth / m_inputSampleRate, ssbFftLen);
|
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);
|
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_corr = new fftcorr(8*ssbFftLen); // 8k for 4k effective samples
|
||||||
m_pll.computeCoefficients(0.002f, 0.5f, 10.0f); // bandwidth, damping factor, loop gain
|
m_pll.computeCoefficients(0.002f, 0.5f, 10.0f); // bandwidth, damping factor, loop gain
|
||||||
|
|
||||||
@ -72,6 +73,7 @@ ChannelAnalyzerNG::~ChannelAnalyzerNG()
|
|||||||
delete m_channelizer;
|
delete m_channelizer;
|
||||||
delete SSBFilter;
|
delete SSBFilter;
|
||||||
delete DSBFilter;
|
delete DSBFilter;
|
||||||
|
delete RRCFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelAnalyzerNG::configure(MessageQueue* messageQueue,
|
void ChannelAnalyzerNG::configure(MessageQueue* messageQueue,
|
||||||
@ -129,10 +131,17 @@ void ChannelAnalyzerNG::processOneSample(Complex& c, fftfilt::cmplx *sideband)
|
|||||||
int n_out;
|
int n_out;
|
||||||
int decim = 1<<m_settings.m_spanLog2;
|
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);
|
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++)
|
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);
|
SSBFilter->create_filter(lowCutoff / sampleRate, bandwidth / sampleRate);
|
||||||
DSBFilter->create_dsb_filter(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)
|
void ChannelAnalyzerNG::applySettings(const ChannelAnalyzerNGSettings& settings, bool force)
|
||||||
@ -300,6 +310,8 @@ void ChannelAnalyzerNG::applySettings(const ChannelAnalyzerNGSettings& settings,
|
|||||||
qDebug() << "ChannelAnalyzerNG::applySettings:"
|
qDebug() << "ChannelAnalyzerNG::applySettings:"
|
||||||
<< " m_downSample: " << settings.m_downSample
|
<< " m_downSample: " << settings.m_downSample
|
||||||
<< " m_downSampleRate: " << settings.m_downSampleRate
|
<< " m_downSampleRate: " << settings.m_downSampleRate
|
||||||
|
<< " m_rcc: " << settings.m_rrc
|
||||||
|
<< " m_rrcRolloff: " << settings.m_rrcRolloff / 100.0
|
||||||
<< " m_bandwidth: " << settings.m_bandwidth
|
<< " m_bandwidth: " << settings.m_bandwidth
|
||||||
<< " m_lowCutoff: " << settings.m_lowCutoff
|
<< " m_lowCutoff: " << settings.m_lowCutoff
|
||||||
<< " m_spanLog2: " << settings.m_spanLog2
|
<< " m_spanLog2: " << settings.m_spanLog2
|
||||||
@ -338,6 +350,14 @@ void ChannelAnalyzerNG::applySettings(const ChannelAnalyzerNGSettings& settings,
|
|||||||
m_settingsMutex.unlock();
|
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)
|
if ((settings.m_spanLog2 != m_settings.m_spanLog2) || force)
|
||||||
{
|
{
|
||||||
int sampleRate = (settings.m_downSample ? settings.m_downSampleRate : m_inputSampleRate) / (1<<m_settings.m_spanLog2);
|
int sampleRate = (settings.m_downSample ? settings.m_downSampleRate : m_inputSampleRate) / (1<<m_settings.m_spanLog2);
|
||||||
|
@ -231,6 +231,7 @@ private:
|
|||||||
|
|
||||||
fftfilt* SSBFilter;
|
fftfilt* SSBFilter;
|
||||||
fftfilt* DSBFilter;
|
fftfilt* DSBFilter;
|
||||||
|
fftfilt* RRCFilter;
|
||||||
fftcorr* m_corr;
|
fftcorr* m_corr;
|
||||||
|
|
||||||
BasebandSampleSink* m_sampleSink;
|
BasebandSampleSink* m_sampleSink;
|
||||||
|
@ -114,6 +114,9 @@ void ChannelAnalyzerNGGUI::displaySettings()
|
|||||||
ui->spanLog2->setCurrentIndex(m_settings.m_spanLog2);
|
ui->spanLog2->setCurrentIndex(m_settings.m_spanLog2);
|
||||||
displayPLLSettings();
|
displayPLLSettings();
|
||||||
ui->signalSelect->setCurrentIndex((int) m_settings.m_inputType);
|
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);
|
blockApplySettings(false);
|
||||||
}
|
}
|
||||||
@ -291,6 +294,20 @@ void ChannelAnalyzerNGGUI::on_deltaFrequency_changed(qint64 value)
|
|||||||
applySettings();
|
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)))
|
void ChannelAnalyzerNGGUI::on_BW_valueChanged(int value __attribute__((unused)))
|
||||||
{
|
{
|
||||||
setFiltersUIBoundaries();
|
setFiltersUIBoundaries();
|
||||||
|
@ -99,6 +99,8 @@ private slots:
|
|||||||
void on_pllPskOrder_currentIndexChanged(int index);
|
void on_pllPskOrder_currentIndexChanged(int index);
|
||||||
void on_useRationalDownsampler_toggled(bool checked);
|
void on_useRationalDownsampler_toggled(bool checked);
|
||||||
void on_signalSelect_currentIndexChanged(int index);
|
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_BW_valueChanged(int value);
|
||||||
void on_lowCut_valueChanged(int value);
|
void on_lowCut_valueChanged(int value);
|
||||||
void on_spanLog2_currentIndexChanged(int index);
|
void on_spanLog2_currentIndexChanged(int index);
|
||||||
|
@ -419,6 +419,58 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="BWLayout">
|
<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>
|
<item>
|
||||||
<widget class="QLabel" name="BWLabel">
|
<widget class="QLabel" name="BWLabel">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
|
@ -40,6 +40,8 @@ void ChannelAnalyzerNGSettings::resetToDefaults()
|
|||||||
m_ssb = false;
|
m_ssb = false;
|
||||||
m_pll = false;
|
m_pll = false;
|
||||||
m_fll = false;
|
m_fll = false;
|
||||||
|
m_rrc = false;
|
||||||
|
m_rrcRolloff = 30; // 0.3
|
||||||
m_pllPskOrder = 1;
|
m_pllPskOrder = 1;
|
||||||
m_inputType = InputSignal;
|
m_inputType = InputSignal;
|
||||||
m_rgbColor = QColor(128, 128, 128).rgb();
|
m_rgbColor = QColor(128, 128, 128).rgb();
|
||||||
@ -65,6 +67,8 @@ QByteArray ChannelAnalyzerNGSettings::serialize() const
|
|||||||
s.writeU32(13, m_pllPskOrder);
|
s.writeU32(13, m_pllPskOrder);
|
||||||
s.writeS32(14, (int) m_inputType);
|
s.writeS32(14, (int) m_inputType);
|
||||||
s.writeString(15, m_title);
|
s.writeString(15, m_title);
|
||||||
|
s.writeBool(16, m_rrc);
|
||||||
|
s.writeU32(17, m_rrcRolloff);
|
||||||
|
|
||||||
return s.final();
|
return s.final();
|
||||||
}
|
}
|
||||||
@ -110,6 +114,8 @@ bool ChannelAnalyzerNGSettings::deserialize(const QByteArray& data)
|
|||||||
d.readS32(14, &tmp, 0);
|
d.readS32(14, &tmp, 0);
|
||||||
m_inputType = (InputType) tmp;
|
m_inputType = (InputType) tmp;
|
||||||
d.readString(15, &m_title, "Channel Analyzer NG");
|
d.readString(15, &m_title, "Channel Analyzer NG");
|
||||||
|
d.readBool(16, &m_rrc, false);
|
||||||
|
d.readU32(17, &m_rrcRolloff, 30);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,8 @@ struct ChannelAnalyzerNGSettings
|
|||||||
bool m_ssb;
|
bool m_ssb;
|
||||||
bool m_pll;
|
bool m_pll;
|
||||||
bool m_fll;
|
bool m_fll;
|
||||||
|
bool m_rrc;
|
||||||
|
quint32 m_rrcRolloff; //!< in 100ths
|
||||||
unsigned int m_pllPskOrder;
|
unsigned int m_pllPskOrder;
|
||||||
InputType m_inputType;
|
InputType m_inputType;
|
||||||
quint32 m_rgbColor;
|
quint32 m_rgbColor;
|
||||||
|
@ -69,7 +69,7 @@ protected:
|
|||||||
{
|
{
|
||||||
float x = i/(float)len; // normalize to [0..1]
|
float x = i/(float)len; // normalize to [0..1]
|
||||||
x = 0.5-fabs(x-0.5); // apply symmetry: now both halves overlap near 0
|
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)
|
if (x < fb-tr)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user