Skip to content

Commit 3ecf974

Browse files
authored
Merge pull request #2645 from f4exb/fix-fftrrc-2
Rework FFT RRC filter and add a FIR RRC filter
2 parents 1c70dc9 + b6652ec commit 3ecf974

File tree

71 files changed

+1694
-183
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+1694
-183
lines changed

plugins/channelrx/chanalyzer/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ set(chanalyzer_SOURCES
88
chanalyzersink.cpp
99
chanalyzerbaseband.cpp
1010
chanalyzerwebapiadapter.cpp
11+
rrcfilterdialog.cpp
1112
chanalyzergui.ui
13+
rrcfilterdialog.ui
1214
)
1315

1416
set(chanalyzer_HEADERS
@@ -19,6 +21,7 @@ set(chanalyzer_HEADERS
1921
chanalyzersink.h
2022
chanalyzerbaseband.h
2123
chanalyzerwebapiadapter.h
24+
rrcfilterdialog.h
2225
)
2326

2427
include_directories(

plugins/channelrx/chanalyzer/chanalyzergui.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@
3030
#include "gui/basicchannelsettingsdialog.h"
3131
#include "gui/dialpopup.h"
3232
#include "gui/dialogpositioner.h"
33+
#include "gui/crightclickenabler.h"
3334
#include "plugin/pluginapi.h"
3435
#include "util/db.h"
3536
#include "maincore.h"
3637

3738
#include "ui_chanalyzergui.h"
3839
#include "chanalyzer.h"
40+
#include "rrcfilterdialog.h"
3941
#include "chanalyzergui.h"
4042

4143
ChannelAnalyzerGUI* ChannelAnalyzerGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
@@ -559,6 +561,9 @@ ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, DeviceUISet *device
559561
m_channelAnalyzer->setScopeVis(m_scopeVis);
560562
m_channelAnalyzer->setMessageQueueToGUI(getInputMessageQueue());
561563

564+
m_rrcRightClickEnabler = new CRightClickEnabler(ui->rrcFilter);
565+
connect(m_rrcRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(rrcSetupDialog(const QPoint &)));
566+
562567
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
563568
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
564569
ui->deltaFrequency->setValueRange(false, 8, -99999999, 99999999);
@@ -735,6 +740,47 @@ void ChannelAnalyzerGUI::enterEvent(EnterEventType* event)
735740
ChannelGUI::enterEvent(event);
736741
}
737742

743+
void ChannelAnalyzerGUI::rrcSetupDialog(const QPoint& p)
744+
{
745+
m_rrcFilterDialog = new RRCFilterDialog();
746+
m_rrcFilterDialog->move(p);
747+
m_rrcFilterDialog->setRRCType(m_settings.m_rrcType);
748+
m_rrcFilterDialog->setRRCSymbolSpan(m_settings.m_rrcSymbolSpan);
749+
m_rrcFilterDialog->setRRCNormalization(m_settings.m_rrcNormalization);
750+
m_rrcFilterDialog->setRRCFFTLog2Size(m_settings.m_rrcFFTLog2Size);
751+
QObject::connect(m_rrcFilterDialog, &RRCFilterDialog::valueChanged, this, &ChannelAnalyzerGUI::rrcSetup);
752+
m_rrcFilterDialog->exec();
753+
m_rrcFilterDialog->deleteLater();
754+
m_rrcFilterDialog = nullptr;
755+
}
756+
757+
void ChannelAnalyzerGUI::rrcSetup(int iValueChanged)
758+
{
759+
auto valueChanged = static_cast<RRCFilterDialog::ValueChanged>(iValueChanged);
760+
761+
switch(valueChanged)
762+
{
763+
case RRCFilterDialog::ValueChanged::ChangedRRCType:
764+
m_settings.m_rrcType = m_rrcFilterDialog->getRRCType();
765+
applySettings(QStringList({"rrcType"}));
766+
break;
767+
case RRCFilterDialog::ValueChanged::ChangedRRCSymbolSpan:
768+
m_settings.m_rrcSymbolSpan = m_rrcFilterDialog->getRRCSymbolSpan();
769+
applySettings(QStringList({"rrcSymbolSpan"}));
770+
break;
771+
case RRCFilterDialog::ValueChanged::ChangedRRCNormalization:
772+
m_settings.m_rrcNormalization = m_rrcFilterDialog->getRRCNormalization();
773+
applySettings(QStringList({"rrcNormalization"}));
774+
break;
775+
case RRCFilterDialog::ValueChanged::ChangedRRCFFTLog2Size:
776+
m_settings.m_rrcFFTLog2Size = m_rrcFilterDialog->getRRCFFTLog2Size();
777+
applySettings(QStringList({"rrcFFTLog2Size"}));
778+
break;
779+
default:
780+
break;
781+
}
782+
}
783+
738784
void ChannelAnalyzerGUI::makeUIConnections()
739785
{
740786
QObject::connect(ui->deltaFrequency, &ValueDialZ::changed, this, &ChannelAnalyzerGUI::on_deltaFrequency_changed);

plugins/channelrx/chanalyzer/chanalyzergui.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ class BasebandSampleSink;
3535
class ChannelAnalyzer;
3636
class SpectrumVis;
3737
class ScopeVis;
38+
class RRCFilterDialog;
39+
class CRightClickEnabler;
3840

3941
namespace Ui {
4042
class ChannelAnalyzerGUI;
@@ -83,6 +85,8 @@ public slots:
8385
SpectrumVis* m_spectrumVis;
8486
ScopeVis* m_scopeVis;
8587
MessageQueue m_inputMessageQueue;
88+
RRCFilterDialog* m_rrcFilterDialog;
89+
CRightClickEnabler* m_rrcRightClickEnabler;
8690

8791
explicit ChannelAnalyzerGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = nullptr);
8892
virtual ~ChannelAnalyzerGUI();
@@ -123,6 +127,8 @@ private slots:
123127
void on_ssb_toggled(bool checked);
124128
void onWidgetRolled(QWidget* widget, bool rollDown);
125129
void onMenuDialogCalled(const QPoint& p);
130+
void rrcSetupDialog(const QPoint& p);
131+
void rrcSetup(int valueChanged);
126132
void handleInputMessages();
127133
void tick();
128134
};

plugins/channelrx/chanalyzer/chanalyzergui.ui

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@
418418
<item>
419419
<widget class="ButtonSwitch" name="rrcFilter">
420420
<property name="toolTip">
421-
<string>Toggle RRC filter</string>
421+
<string>Toggle RRC filter - Right click for options</string>
422422
</property>
423423
<property name="text">
424424
<string/>

plugins/channelrx/chanalyzer/chanalyzersettings.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ void ChannelAnalyzerSettings::resetToDefaults()
4646
m_costasLoop = false;
4747
m_rrc = false;
4848
m_rrcRolloff = 35; // 0.35
49+
m_rrcType = RRCFIR;
50+
m_rrcSymbolSpan = 8;
51+
m_rrcNormalization = RRCNormGain;
52+
m_rrcFFTLog2Size = 9; // 512
4953
m_pllPskOrder = 1;
5054
m_pllBandwidth = 0.002f;
5155
m_pllDampingFactor = 0.5f;
@@ -110,6 +114,10 @@ QByteArray ChannelAnalyzerSettings::serialize() const
110114
s.writeS32(29, m_workspaceIndex);
111115
s.writeBlob(30, m_geometryBytes);
112116
s.writeBool(31, m_hidden);
117+
s.writeS32(32, m_rrcType);
118+
s.writeS32(33, m_rrcSymbolSpan);
119+
s.writeS32(34, m_rrcNormalization);
120+
s.writeS32(35, m_rrcFFTLog2Size);
113121

114122
return s.final();
115123
}
@@ -187,6 +195,12 @@ bool ChannelAnalyzerSettings::deserialize(const QByteArray& data)
187195
d.readS32(29, &m_workspaceIndex, 0);
188196
d.readBlob(30, &m_geometryBytes);
189197
d.readBool(31, &m_hidden, false);
198+
d.readS32(32, &tmp, 0);
199+
m_rrcType = (RRCType) tmp;
200+
d.readS32(33, &m_rrcSymbolSpan, 8);
201+
d.readS32(34, &tmp, 2);
202+
m_rrcNormalization = (RRCNormalization) tmp;
203+
d.readS32(35, &m_rrcFFTLog2Size, 9);
190204

191205
return true;
192206
}
@@ -235,6 +249,18 @@ void ChannelAnalyzerSettings::applySettings(const QStringList& settingsKeys, con
235249
if (settingsKeys.contains("rrcRolloff")) {
236250
m_rrcRolloff = settings.m_rrcRolloff;
237251
}
252+
if (settingsKeys.contains("rrcType")) {
253+
m_rrcType = settings.m_rrcType;
254+
}
255+
if (settingsKeys.contains("rrcSymbolSpan")) {
256+
m_rrcSymbolSpan = settings.m_rrcSymbolSpan;
257+
}
258+
if (settingsKeys.contains("rrcNormalization")) {
259+
m_rrcNormalization = settings.m_rrcNormalization;
260+
}
261+
if (settingsKeys.contains("rrcFFTLog2Size")) {
262+
m_rrcFFTLog2Size = settings.m_rrcFFTLog2Size;
263+
}
238264
if (settingsKeys.contains("pllPskOrder")) {
239265
m_pllPskOrder = settings.m_pllPskOrder;
240266
}
@@ -322,6 +348,18 @@ QString ChannelAnalyzerSettings::getDebugString(const QStringList& settingsKeys,
322348
if (settingsKeys.contains("rrcRolloff") || force) {
323349
ostr << " m_rrcRolloff: " << m_rrcRolloff;
324350
}
351+
if (settingsKeys.contains("rrcType") || force) {
352+
ostr << " m_rrcType: " << m_rrcType;
353+
}
354+
if (settingsKeys.contains("rrcSymbolSpan") || force) {
355+
ostr << " m_rrcSymbolSpan: " << m_rrcSymbolSpan;
356+
}
357+
if (settingsKeys.contains("rrcNormalization") || force) {
358+
ostr << " m_rrcNormalization: " << m_rrcNormalization;
359+
}
360+
if (settingsKeys.contains("rrcFFTLog2Size") || force) {
361+
ostr << " m_rrcFFTLog2Size: " << m_rrcFFTLog2Size;
362+
}
325363
if (settingsKeys.contains("pllPskOrder") || force) {
326364
ostr << " m_pllPskOrder: " << m_pllPskOrder;
327365
}

plugins/channelrx/chanalyzer/chanalyzersettings.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@ struct ChannelAnalyzerSettings
3434
InputAutoCorr
3535
};
3636

37+
enum RRCType
38+
{
39+
RRCFIR,
40+
RRCFFT
41+
};
42+
43+
enum RRCNormalization
44+
{
45+
RRCNormEnergy,
46+
RRCNormAmpltude,
47+
RRCNormGain
48+
};
49+
3750
int m_inputFrequencyOffset;
3851
bool m_rationalDownSample;
3952
quint32 m_rationalDownSamplerRate;
@@ -46,6 +59,10 @@ struct ChannelAnalyzerSettings
4659
bool m_costasLoop;
4760
bool m_rrc;
4861
quint32 m_rrcRolloff; //!< in 100ths
62+
RRCType m_rrcType;
63+
int m_rrcSymbolSpan;
64+
RRCNormalization m_rrcNormalization;
65+
int m_rrcFFTLog2Size;
4966
unsigned int m_pllPskOrder;
5067
float m_pllBandwidth;
5168
float m_pllDampingFactor;

plugins/channelrx/chanalyzer/chanalyzersink.cpp

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,52 @@
2828
const unsigned int ChannelAnalyzerSink::m_ssbFftLen = 1024;
2929
const unsigned int ChannelAnalyzerSink::m_corrFFTLen = 4*m_ssbFftLen;
3030

31+
ChannelAnalyzerSink::RRCHelper::RRCHelper(int flen) :
32+
m_useFFT(false),
33+
m_filterFIR(new FIRFilterRRC()),
34+
m_filterFFT(new FFTFilterRRC(m_ssbFftLen)),
35+
m_buffer(new std::complex<float>[flen/2]),
36+
m_bufferPos(0),
37+
flen2(flen/2)
38+
{
39+
}
40+
41+
ChannelAnalyzerSink::RRCHelper::~RRCHelper()
42+
{
43+
delete m_filterFIR;
44+
delete[] m_buffer;
45+
}
46+
47+
void ChannelAnalyzerSink::RRCHelper::setUseFFT(bool useFFT)
48+
{
49+
m_useFFT = useFFT;
50+
m_bufferPos = 0;
51+
}
52+
53+
void ChannelAnalyzerSink::RRCHelper::create(float symbolRate, float rolloff, unsigned int samplesPerSymbol, FIRFilterRRC::Normalization normalization)
54+
{
55+
m_filterFIR->create(symbolRate, rolloff, samplesPerSymbol, normalization);
56+
m_filterFFT->create(symbolRate, rolloff);
57+
}
58+
59+
int ChannelAnalyzerSink::RRCHelper::runFilt(const std::complex<float> & in, std::complex<float> **out)
60+
{
61+
if (m_useFFT) {
62+
return m_filterFFT->process(in, out);
63+
} else {
64+
m_buffer[m_bufferPos++] = m_filterFIR->filter(in);
65+
}
66+
67+
if (m_bufferPos < flen2) {
68+
*out = nullptr;
69+
return 0;
70+
}
71+
72+
m_bufferPos = 0;
73+
*out = m_buffer;
74+
return flen2;
75+
}
76+
3177
ChannelAnalyzerSink::ChannelAnalyzerSink() :
3278
m_channelSampleRate(48000),
3379
m_channelFrequencyOffset(0),
@@ -39,7 +85,8 @@ ChannelAnalyzerSink::ChannelAnalyzerSink() :
3985
m_magsq = 0;
4086
SSBFilter = new fftfilt(m_settings.m_lowCutoff / m_channelSampleRate, m_settings.m_bandwidth / m_channelSampleRate, m_ssbFftLen);
4187
DSBFilter = new fftfilt(m_settings.m_bandwidth / m_channelSampleRate, 2*m_ssbFftLen);
42-
RRCFilter = new fftfilt(m_settings.m_bandwidth / m_channelSampleRate, 2*m_ssbFftLen);
88+
m_rrcHelper = new RRCHelper(2*m_ssbFftLen);
89+
// m_rrcHelper->setUseFFT(true);
4390
m_corr = new fftcorr(2*m_corrFFTLen); // 8k for 4k effective samples
4491
m_pll.computeCoefficients(m_settings.m_pllBandwidth, m_settings.m_pllDampingFactor, m_settings.m_pllLoopGain);
4592
m_costasLoop.computeCoefficients(m_settings.m_pllBandwidth);
@@ -52,7 +99,7 @@ ChannelAnalyzerSink::~ChannelAnalyzerSink()
5299
{
53100
delete SSBFilter;
54101
delete DSBFilter;
55-
delete RRCFilter;
102+
delete m_rrcHelper;
56103
delete m_corr;
57104
}
58105

@@ -126,7 +173,7 @@ void ChannelAnalyzerSink::processOneSample(Complex& c, fftfilt::cmplx *sideband)
126173
else
127174
{
128175
if (m_settings.m_rrc) {
129-
n_out = RRCFilter->runFilt(c, &sideband);
176+
n_out = m_rrcHelper->runFilt(c, &sideband);
130177
} else {
131178
n_out = DSBFilter->runDSB(c, &sideband);
132179
}
@@ -240,7 +287,7 @@ void ChannelAnalyzerSink::setFilters(int sampleRate, float bandwidth, float lowC
240287

241288
SSBFilter->create_filter(lowCutoff / sampleRate, bandwidth / sampleRate);
242289
DSBFilter->create_dsb_filter(bandwidth / sampleRate);
243-
RRCFilter->create_rrc_filter(bandwidth / sampleRate, m_settings.m_rrcRolloff / 100.0);
290+
m_rrcHelper->create(bandwidth / sampleRate, m_settings.m_rrcRolloff / 100.0, m_settings.m_rrcSymbolSpan, (FIRFilterRRC::Normalization) m_settings.m_rrcNormalization);
244291
}
245292

246293
void ChannelAnalyzerSink::applySettings(const ChannelAnalyzerSettings& settings, const QStringList& settingsKeys, bool force)
@@ -314,6 +361,29 @@ void ChannelAnalyzerSink::applySettings(const ChannelAnalyzerSettings& settings,
314361
}
315362
}
316363

364+
if (settings.m_rrcType != m_settings.m_rrcType || force)
365+
{
366+
m_rrcHelper->setUseFFT(settings.m_rrcType == ChannelAnalyzerSettings::RRCFFT);
367+
}
368+
369+
if (settings.m_rrcSymbolSpan != m_settings.m_rrcSymbolSpan || force)
370+
{
371+
m_rrcHelper->create(m_settings.m_bandwidth / (float) m_sinkSampleRate, m_settings.m_rrcRolloff / 100.0, settings.m_rrcSymbolSpan, (FIRFilterRRC::Normalization) m_settings.m_rrcNormalization);
372+
}
373+
374+
if (settings.m_rrcNormalization != m_settings.m_rrcNormalization || force)
375+
{
376+
m_rrcHelper->create(m_settings.m_bandwidth / (float) m_sinkSampleRate, m_settings.m_rrcRolloff / 100.0, m_settings.m_rrcSymbolSpan, (FIRFilterRRC::Normalization) settings.m_rrcNormalization);
377+
}
378+
379+
if (settings.m_rrcFFTLog2Size != m_settings.m_rrcFFTLog2Size || force)
380+
{
381+
delete m_rrcHelper;
382+
m_rrcHelper = new RRCHelper(1 << settings.m_rrcFFTLog2Size);
383+
m_rrcHelper->create(settings.m_bandwidth / (float) m_sinkSampleRate, settings.m_rrcRolloff / 100.0, settings.m_rrcSymbolSpan, (FIRFilterRRC::Normalization) settings.m_rrcNormalization);
384+
m_rrcHelper->setUseFFT(settings.m_rrcType == ChannelAnalyzerSettings::RRCFFT);
385+
}
386+
317387
if (force) {
318388
m_settings = settings;
319389
} else {
@@ -383,5 +453,5 @@ void ChannelAnalyzerSink::applySampleRate()
383453
m_pll.setSampleRate(sampleRate);
384454
m_fll.setSampleRate(sampleRate);
385455
m_costasLoop.setSampleRate(sampleRate);
386-
RRCFilter->create_rrc_filter(m_settings.m_bandwidth / (float) sampleRate, m_settings.m_rrcRolloff / 100.0);
456+
m_rrcHelper->create(m_settings.m_bandwidth / (float) sampleRate, m_settings.m_rrcRolloff / 100.0, m_settings.m_rrcSymbolSpan, (FIRFilterRRC::Normalization) m_settings.m_rrcNormalization);
387457
}

plugins/channelrx/chanalyzer/chanalyzersink.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "dsp/nco.h"
2626
#include "dsp/fftcorr.h"
2727
#include "dsp/fftfilt.h"
28+
#include "dsp/firfilterrrc.h"
29+
#include "dsp/fftfilterrrc.h"
2830
#include "dsp/phaselockcomplex.h"
2931
#include "dsp/freqlockcomplex.h"
3032
#include "dsp/costasloop.h"
@@ -57,6 +59,22 @@ class ChannelAnalyzerSink : public ChannelSampleSink {
5759
static const unsigned int m_ssbFftLen;
5860

5961
private:
62+
class RRCHelper {
63+
public:
64+
RRCHelper(int flen);
65+
~RRCHelper();
66+
void setUseFFT(bool useFFT);
67+
void create(float symbolRate, float rolloff, unsigned int samplesPerSymbol, FIRFilterRRC::Normalization normalization);
68+
int runFilt(const std::complex<float> & in, std::complex<float> **out);
69+
private:
70+
bool m_useFFT;
71+
FIRFilterRRC* m_filterFIR;
72+
FFTFilterRRC* m_filterFFT;
73+
std::complex<float>* m_buffer;
74+
int m_bufferPos;
75+
int flen2;
76+
};
77+
6078
int m_channelSampleRate;
6179
int m_channelFrequencyOffset;
6280
int m_sinkSampleRate;
@@ -76,7 +94,7 @@ class ChannelAnalyzerSink : public ChannelSampleSink {
7694

7795
fftfilt* SSBFilter;
7896
fftfilt* DSBFilter;
79-
fftfilt* RRCFilter;
97+
RRCHelper* m_rrcHelper;
8098
fftcorr* m_corr;
8199

82100
SampleVector m_sampleBuffer;

0 commit comments

Comments
 (0)