From b6b4eb405fe7b0578a404895aafbe87ae19f9ae8 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 12 May 2024 00:00:06 +0200 Subject: [PATCH] Interferometer: added channel B gain control --- .../interferometer/interferometer.cpp | 7 +- .../interferometer/interferometerbaseband.cpp | 6 +- .../interferometer/interferometerbaseband.h | 1 + .../interferometer/interferometercorr.cpp | 214 +++++++----------- .../interferometer/interferometercorr.h | 13 +- .../interferometer/interferometergui.cpp | 24 ++ .../interferometer/interferometergui.h | 3 + .../interferometer/interferometergui.ui | 80 ++++++- .../interferometer/interferometersettings.cpp | 3 + .../interferometer/interferometersettings.h | 1 + 10 files changed, 205 insertions(+), 147 deletions(-) diff --git a/plugins/channelmimo/interferometer/interferometer.cpp b/plugins/channelmimo/interferometer/interferometer.cpp index 0f2290428..33c5c46e9 100644 --- a/plugins/channelmimo/interferometer/interferometer.cpp +++ b/plugins/channelmimo/interferometer/interferometer.cpp @@ -162,6 +162,7 @@ void Interferometer::applySettings(const InterferometerSettings& settings, bool << "m_filterChainHash: " << settings.m_filterChainHash << "m_log2Decim: " << settings.m_log2Decim << "m_phase: " << settings.m_phase + << "m_gain: " << settings.m_gain / 10.0 << "m_useReverseAPI: " << settings.m_useReverseAPI << "m_reverseAPIAddress: " << settings.m_reverseAPIAddress << "m_reverseAPIPort: " << settings.m_reverseAPIPort @@ -188,7 +189,7 @@ void Interferometer::applySettings(const InterferometerSettings& settings, bool } if (m_running && ((m_settings.m_log2Decim != settings.m_log2Decim) - || (m_settings.m_filterChainHash != settings.m_filterChainHash) || force)) + || (m_settings.m_filterChainHash != settings.m_filterChainHash) || force)) { InterferometerBaseband::MsgConfigureChannelizer *msg = InterferometerBaseband::MsgConfigureChannelizer::create( settings.m_log2Decim, settings.m_filterChainHash); @@ -206,6 +207,10 @@ void Interferometer::applySettings(const InterferometerSettings& settings, bool m_basebandSink->setPhase(settings.m_phase); } + if (m_running && ((m_settings.m_gain != settings.m_gain) || force)) { + m_basebandSink->setGain(settings.m_gain); + } + QList pipes; MainCore::instance()->getMessagePipes().getMessagePipes(this, "settings", pipes); diff --git a/plugins/channelmimo/interferometer/interferometerbaseband.cpp b/plugins/channelmimo/interferometer/interferometerbaseband.cpp index 0c0db4887..b70368bf4 100644 --- a/plugins/channelmimo/interferometer/interferometerbaseband.cpp +++ b/plugins/channelmimo/interferometer/interferometerbaseband.cpp @@ -153,9 +153,9 @@ void InterferometerBaseband::run() if (m_spectrumSink) { if ((m_correlator.getCorrType() == InterferometerSettings::CorrelationFFT) - || (m_correlator.getCorrType() == InterferometerSettings::CorrelationIFFT) - || (m_correlator.getCorrType() == InterferometerSettings::CorrelationIFFT2) - || (m_correlator.getCorrType() == InterferometerSettings::CorrelationIFFTStar)) + || (m_correlator.getCorrType() == InterferometerSettings::CorrelationIFFT) + || (m_correlator.getCorrType() == InterferometerSettings::CorrelationIFFT2) + || (m_correlator.getCorrType() == InterferometerSettings::CorrelationIFFTStar)) { m_spectrumSink->feed(m_correlator.m_scorr.begin(), m_correlator.m_scorr.begin() + m_correlator.m_processed, false); } diff --git a/plugins/channelmimo/interferometer/interferometerbaseband.h b/plugins/channelmimo/interferometer/interferometerbaseband.h index 9528ec549..86d2ef770 100644 --- a/plugins/channelmimo/interferometer/interferometerbaseband.h +++ b/plugins/channelmimo/interferometer/interferometerbaseband.h @@ -112,6 +112,7 @@ public: void setSpectrumSink(BasebandSampleSink *spectrumSink) { m_spectrumSink = spectrumSink; } void setScopeSink(ScopeVis *scopeSink) { m_scopeSink = scopeSink; } void setPhase(int phase) { m_correlator.setPhase(phase); } + void setGain(int gain) { m_correlator.setGain(gain); } void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, unsigned int streamIndex); void setBasebandSampleRate(unsigned int sampleRate); diff --git a/plugins/channelmimo/interferometer/interferometercorr.cpp b/plugins/channelmimo/interferometer/interferometercorr.cpp index 8e050d3c2..1c90c433d 100644 --- a/plugins/channelmimo/interferometer/interferometercorr.cpp +++ b/plugins/channelmimo/interferometer/interferometercorr.cpp @@ -21,6 +21,7 @@ #include "dsp/dspengine.h" #include "dsp/fftfactory.h" #include "dsp/fftengine.h" +#include "util/db.h" #include "interferometercorr.h" @@ -123,6 +124,7 @@ InterferometerCorrelator::InterferometerCorrelator(int fftSize) : m_fftSize(fftSize) { setPhase(0); + setGain(0); FFTFactory *fftFactory = DSPEngine::instance()->getFFTFactory(); m_window.create(FFTWindow::Function::Hanning, fftSize); m_data0w.resize(m_fftSize); @@ -166,141 +168,78 @@ bool InterferometerCorrelator::performCorr( ) { bool results = false; + const SampleVector *pdata1 = &data1; - if (m_phase == 0) - { - switch (m_corrType) - { - case InterferometerSettings::Correlation0: - results = performOpCorr(data0, size0, data1, size1, sFirst); - break; - case InterferometerSettings::Correlation1: - results = performOpCorr(data0, size0, data1, size1, sSecond); - break; - case InterferometerSettings::CorrelationAdd: - results = performOpCorr(data0, size0, data1, size1, sAdd); - break; - case InterferometerSettings::CorrelationMultiply: - results = performOpCorr(data0, size0, data1, size1, sMulConj); - break; - case InterferometerSettings::CorrelationIFFT: - results = performIFFTCorr(data0, size0, data1, size1); - break; - case InterferometerSettings::CorrelationIFFTStar: - results = performIFFTCorr(data0, size0, data1, size1, true); - break; - case InterferometerSettings::CorrelationFFT: - results = performFFTProd(data0, size0, data1, size1); - break; - case InterferometerSettings::CorrelationIFFT2: - results = performIFFT2Corr(data0, size0, data1, size1); - break; - default: - break; - } - } - else if ((m_phase == -180) || (m_phase == 180)) - { - if ((m_corrType == InterferometerSettings::CorrelationIFFT) - || (m_corrType == InterferometerSettings::CorrelationIFFT2) - || (m_corrType == InterferometerSettings::CorrelationIFFTStar) - || (m_corrType == InterferometerSettings::CorrelationFFT)) - { - if (size1 > m_data1p.size()) { - m_data1p.resize(size1); - } - - std::transform( - data1.begin(), - data1.begin() + size1, - m_data1p.begin(), - [](const Sample& s) -> Sample { - return Sample{-s.real(), -s.imag()}; - } - ); - } - - switch (m_corrType) - { - case InterferometerSettings::Correlation0: - results = performOpCorr(data0, size0, data1, size1, sFirst); - break; - case InterferometerSettings::Correlation1: - results = performOpCorr(data0, size0, data1, size1, sSecondInv); - break; - case InterferometerSettings::CorrelationAdd: - results = performOpCorr(data0, size0, data1, size1, sAddInv); - break; - case InterferometerSettings::CorrelationMultiply: - results = performOpCorr(data0, size0, data1, size1, sMulConjInv); - break; - case InterferometerSettings::CorrelationIFFT: - results = performIFFTCorr(data0, size0, m_data1p, size1); - break; - case InterferometerSettings::CorrelationIFFTStar: - results = performIFFTCorr(data0, size0, m_data1p, size1, true); - break; - case InterferometerSettings::CorrelationFFT: - results = performFFTProd(data0, size0, m_data1p, size1); - break; - case InterferometerSettings::CorrelationIFFT2: - results = performIFFT2Corr(data0, size0, m_data1p, size1); - break; - default: - break; - } - } - else + if ((m_gain != 0) || (m_phase != 0)) { if (size1 > m_data1p.size()) { m_data1p.resize(size1); } - std::transform( - data1.begin(), - data1.begin() + size1, - m_data1p.begin(), - [this](const Sample& s) -> Sample { - Sample t; - int64_t sx = s.real(); - int64_t sy = s.imag(); - int64_t x = sx*m_cos + sy*m_sin; - int64_t y = sy*m_cos - sx*m_sin; - t.setReal(x>>(SDR_RX_SAMP_SZ-1)); - t.setImag(y>>(SDR_RX_SAMP_SZ-1)); - return t; - } - ); + pdata1 = &m_data1p; - switch (m_corrType) + if (m_phase == 0) { - case InterferometerSettings::Correlation0: - results = performOpCorr(data0, size0, m_data1p, size1, sFirst); - break; - case InterferometerSettings::Correlation1: - results = performOpCorr(data0, size0, m_data1p, size1, sSecond); - break; - case InterferometerSettings::CorrelationAdd: - results = performOpCorr(data0, size0, m_data1p, size1, sAdd); - break; - case InterferometerSettings::CorrelationMultiply: - results = performOpCorr(data0, size0, m_data1p, size1, sMulConj); - break; - case InterferometerSettings::CorrelationIFFT: - results = performIFFTCorr(data0, size0, m_data1p, size1); - break; - case InterferometerSettings::CorrelationIFFTStar: - results = performIFFTCorr(data0, size0, m_data1p, size1, true); - break; - case InterferometerSettings::CorrelationFFT: - results = performFFTProd(data0, size0, m_data1p, size1); - break; - case InterferometerSettings::CorrelationIFFT2: - results = performIFFT2Corr(data0, size0, m_data1p, size1); - break; - default: - break; + std::transform( + data1.begin(), + data1.begin() + size1, + m_data1p.begin(), + [this](const Sample& s) -> Sample + { + FixReal sx = s.real()*m_gain; + FixReal sy = s.imag()*m_gain; + return Sample{sx, sy}; + } + ); } + else + { + std::transform( + data1.begin(), + data1.begin() + size1, + m_data1p.begin(), + [this](const Sample& s) -> Sample { + Sample t; + int64_t sx = s.real()*m_gain; + int64_t sy = s.imag()*m_gain; + int64_t x = sx*m_cos + sy*m_sin; + int64_t y = sy*m_cos - sx*m_sin; + t.setReal(x>>(SDR_RX_SAMP_SZ-1)); + t.setImag(y>>(SDR_RX_SAMP_SZ-1)); + return t; + } + ); + } + } + + switch (m_corrType) + { + case InterferometerSettings::Correlation0: + results = performOpCorr(data0, size0, pdata1, size1, sFirst); + break; + case InterferometerSettings::Correlation1: + results = performOpCorr(data0, size0, pdata1, size1, sSecond); + break; + case InterferometerSettings::CorrelationAdd: + results = performOpCorr(data0, size0, pdata1, size1, sAdd); + break; + case InterferometerSettings::CorrelationMultiply: + results = performOpCorr(data0, size0, pdata1, size1, sMulConj); + break; + case InterferometerSettings::CorrelationIFFT: + results = performIFFTCorr(data0, size0, pdata1, size1); + break; + case InterferometerSettings::CorrelationIFFTStar: + results = performIFFTCorr(data0, size0, pdata1, size1, true); + break; + case InterferometerSettings::CorrelationFFT: + results = performFFTProd(data0, size0, pdata1, size1); + break; + case InterferometerSettings::CorrelationIFFT2: + results = performIFFT2Corr(data0, size0, pdata1, size1); + break; + default: + break; } return results; @@ -309,7 +248,7 @@ bool InterferometerCorrelator::performCorr( bool InterferometerCorrelator::performOpCorr( const SampleVector& data0, unsigned int size0, - const SampleVector& data1, + const SampleVector* data1, unsigned int size1, Sample sampleOp(const Sample& a, const Sample& b) ) @@ -320,7 +259,7 @@ bool InterferometerCorrelator::performOpCorr( std::transform( data0.begin(), data0.begin() + size, - data1.begin(), + data1->begin(), m_tcorr.begin(), sampleOp ); @@ -334,7 +273,7 @@ bool InterferometerCorrelator::performOpCorr( bool InterferometerCorrelator::performIFFTCorr( const SampleVector& data0, unsigned int size0, - const SampleVector& data1, + const SampleVector* data1, unsigned int size1, bool star ) @@ -342,7 +281,7 @@ bool InterferometerCorrelator::performIFFTCorr( unsigned int size = std::min(size0, size1); int nfft = 0; SampleVector::const_iterator begin0 = data0.begin(); - SampleVector::const_iterator begin1 = data1.begin(); + SampleVector::const_iterator begin1 = data1->begin(); adjustSCorrSize(size); adjustTCorrSize(size); @@ -458,14 +397,14 @@ bool InterferometerCorrelator::performIFFTCorr( bool InterferometerCorrelator::performIFFT2Corr( const SampleVector& data0, unsigned int size0, - const SampleVector& data1, + const SampleVector* data1, unsigned int size1 ) { unsigned int size = std::min(size0, size1); int nfft = 0; SampleVector::const_iterator begin0 = data0.begin(); - SampleVector::const_iterator begin1 = data1.begin(); + SampleVector::const_iterator begin1 = data1->begin(); adjustSCorrSize(size); adjustTCorrSize(size); @@ -567,14 +506,14 @@ bool InterferometerCorrelator::performIFFT2Corr( bool InterferometerCorrelator::performFFTProd( const SampleVector& data0, unsigned int size0, - const SampleVector& data1, + const SampleVector* data1, unsigned int size1 ) { unsigned int size = std::min(size0, size1); int nfft = 0; SampleVector::const_iterator begin0 = data0.begin(); - SampleVector::const_iterator begin1 = data1.begin(); + SampleVector::const_iterator begin1 = data1->begin(); adjustSCorrSize(size); adjustTCorrSize(size); @@ -723,3 +662,10 @@ void InterferometerCorrelator::setPhase(int phase) m_cos = d_cos; } } + +void InterferometerCorrelator::setGain(int gainCB) +{ + double db = gainCB / 10.0; + m_gainCB = gainCB; + m_gain = CalcDb::powerFromdB(db); +} diff --git a/plugins/channelmimo/interferometer/interferometercorr.h b/plugins/channelmimo/interferometer/interferometercorr.h index efacd303f..a9860d161 100644 --- a/plugins/channelmimo/interferometer/interferometercorr.h +++ b/plugins/channelmimo/interferometer/interferometercorr.h @@ -29,7 +29,7 @@ class FFTEngine; class InterferometerCorrelator : public QObject { - Q_OBJECT + Q_OBJECT public: InterferometerCorrelator(int fftSize); ~InterferometerCorrelator(); @@ -44,6 +44,7 @@ public: ); int getFullFFTSize() const { return 2*m_fftSize; } void setPhase(int phase); + void setGain(int gainCB); SampleVector m_scorr; //!< raw correlation result (spectrum) - Sample vector expected SampleVector m_tcorr; //!< correlation result (time or spectrum inverse FFT) - Sample vector expected @@ -57,27 +58,27 @@ private: bool performOpCorr( //!< Returns true if results were produced const SampleVector& data0, unsigned int size0, - const SampleVector& data1, + const SampleVector* data1, unsigned int size1, Sample sampleOp(const Sample& a, const Sample& b) ); bool performIFFTCorr( //!< Returns true if results were produced const SampleVector& data0, unsigned int size0, - const SampleVector& data1, + const SampleVector* data1, unsigned int size1, bool star = false ); bool performIFFT2Corr( //!< Returns true if results were produced const SampleVector& data0, unsigned int size0, - const SampleVector& data1, + const SampleVector* data1, unsigned int size1 ); bool performFFTProd( //!< Returns true if results were produced const SampleVector& data0, unsigned int size0, - const SampleVector& data1, + const SampleVector* data1, unsigned int size1 ); void adjustSCorrSize(int size); @@ -101,6 +102,8 @@ private: int m_scorrSize; //!< spectrum correlations vector size int m_tcorrSize; //!< time correlations vector size int m_phase; //!< phase correction + int m_gainCB; + double m_gain; int64_t m_sin; //!< scaled sine of phase correction int64_t m_cos; //!< scaled cosine of phase correction }; diff --git a/plugins/channelmimo/interferometer/interferometergui.cpp b/plugins/channelmimo/interferometer/interferometergui.cpp index 49a2789c4..faff6c994 100644 --- a/plugins/channelmimo/interferometer/interferometergui.cpp +++ b/plugins/channelmimo/interferometer/interferometergui.cpp @@ -214,6 +214,8 @@ void InterferometerGUI::displaySettings() applyDecimation(); ui->phaseCorrection->setValue(m_settings.m_phase); ui->phaseCorrectionText->setText(tr("%1").arg(m_settings.m_phase)); + ui->gain->setValue(m_settings.m_gain); + ui->gainText->setText(QString("%1").arg(m_settings.m_gain / 10.0, 0, 'f', 1)); getRollupContents()->restoreState(m_rollupState); updateAbsoluteCenterFrequency(); blockApplySettings(false); @@ -317,6 +319,25 @@ void InterferometerGUI::on_phaseCorrection_valueChanged(int value) applySettings(); } +void InterferometerGUI::on_gain_valueChanged(int value) +{ + m_settings.m_gain = value; + ui->gainText->setText(QString("%1").arg(m_settings.m_gain / 10.0, 0, 'f', 1)); + applySettings(); +} + +void InterferometerGUI::on_phaseCorrectionLabel_clicked() +{ + m_settings.m_phase = 0; + ui->phaseCorrection->setValue(0); +} + +void InterferometerGUI::on_gainLabel_clicked() +{ + m_settings.m_gain = 0; + ui->gain->setValue(0); +} + void InterferometerGUI::on_correlationType_currentIndexChanged(int index) { m_settings.m_correlationType = (InterferometerSettings::CorrelationType) index; @@ -361,6 +382,9 @@ void InterferometerGUI::makeUIConnections() QObject::connect(ui->decimationFactor, QOverload::of(&QComboBox::currentIndexChanged), this, &InterferometerGUI::on_decimationFactor_currentIndexChanged); QObject::connect(ui->position, &QSlider::valueChanged, this, &InterferometerGUI::on_position_valueChanged); QObject::connect(ui->phaseCorrection, &QSlider::valueChanged, this, &InterferometerGUI::on_phaseCorrection_valueChanged); + QObject::connect(ui->gain, &QDial::valueChanged, this, &InterferometerGUI::on_gain_valueChanged); + QObject::connect(ui->phaseCorrectionLabel, &ClickableLabel::clicked, this, &InterferometerGUI::on_phaseCorrectionLabel_clicked); + QObject::connect(ui->gainLabel, &ClickableLabel::clicked, this, &InterferometerGUI::on_gainLabel_clicked); QObject::connect(ui->correlationType, QOverload::of(&QComboBox::currentIndexChanged), this, &InterferometerGUI::on_correlationType_currentIndexChanged); } diff --git a/plugins/channelmimo/interferometer/interferometergui.h b/plugins/channelmimo/interferometer/interferometergui.h index 7eb5bed96..0662d8e71 100644 --- a/plugins/channelmimo/interferometer/interferometergui.h +++ b/plugins/channelmimo/interferometer/interferometergui.h @@ -102,6 +102,9 @@ private slots: void on_decimationFactor_currentIndexChanged(int index); void on_position_valueChanged(int value); void on_phaseCorrection_valueChanged(int value); + void on_gain_valueChanged(int value); + void on_phaseCorrectionLabel_clicked(); + void on_gainLabel_clicked(); void on_correlationType_currentIndexChanged(int index); void onWidgetRolled(QWidget* widget, bool rollDown); void onMenuDialogCalled(const QPoint& p); diff --git a/plugins/channelmimo/interferometer/interferometergui.ui b/plugins/channelmimo/interferometer/interferometergui.ui index dc806c9c7..f9e9927a0 100644 --- a/plugins/channelmimo/interferometer/interferometergui.ui +++ b/plugins/channelmimo/interferometer/interferometergui.ui @@ -170,7 +170,7 @@ - + Corr @@ -224,7 +224,10 @@ - + + + Click to set phase correction to 0 + Ph @@ -233,7 +236,7 @@ - Phase correction on stream 1 + Phase correction on B -180 @@ -258,7 +261,7 @@ - Phase correction on stream 1 in degrees + Phase correction on B in degrees -180 @@ -268,6 +271,70 @@ + + + + Qt::Vertical + + + + + + + Click to set gain to 0dB + + + Gain + + + + + + + + 24 + 24 + + + + B gain (dB) + + + -300 + + + 300 + + + 1 + + + 1 + + + 0 + + + + + + + + 30 + 0 + + + + B gain (dB) + + + -99.9 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + @@ -521,6 +588,11 @@
gui/glscopegui.h
1 + + ClickableLabel + QLabel +
gui/clickablelabel.h
+
diff --git a/plugins/channelmimo/interferometer/interferometersettings.cpp b/plugins/channelmimo/interferometer/interferometersettings.cpp index fdb5c39c0..0102d2957 100644 --- a/plugins/channelmimo/interferometer/interferometersettings.cpp +++ b/plugins/channelmimo/interferometer/interferometersettings.cpp @@ -40,6 +40,7 @@ void InterferometerSettings::resetToDefaults() m_log2Decim = 0; m_filterChainHash = 0; m_phase = 0; + m_gain = 0; m_reverseAPIAddress = "127.0.0.1"; m_reverseAPIPort = 8888; m_reverseAPIDeviceIndex = 0; @@ -66,6 +67,7 @@ QByteArray InterferometerSettings::serialize() const s.writeS32(13,m_workspaceIndex); s.writeBlob(14, m_geometryBytes); s.writeBool(15, m_hidden); + s.writeS32(16, m_gain); if (m_spectrumGUI) { s.writeBlob(20, m_spectrumGUI->serialize()); @@ -125,6 +127,7 @@ bool InterferometerSettings::deserialize(const QByteArray& data) d.readS32(13, &m_workspaceIndex); d.readBlob(14, &m_geometryBytes); d.readBool(15, &m_hidden, false); + d.readS32(16, &m_gain, 0); if (m_spectrumGUI) { diff --git a/plugins/channelmimo/interferometer/interferometersettings.h b/plugins/channelmimo/interferometer/interferometersettings.h index 673c72259..5df39261e 100644 --- a/plugins/channelmimo/interferometer/interferometersettings.h +++ b/plugins/channelmimo/interferometer/interferometersettings.h @@ -46,6 +46,7 @@ struct InterferometerSettings uint32_t m_log2Decim; uint32_t m_filterChainHash; int m_phase; + int m_gain; bool m_useReverseAPI; QString m_reverseAPIAddress; uint16_t m_reverseAPIPort;