diff --git a/plugins/samplesource/testsource/testsourcegui.cpp b/plugins/samplesource/testsource/testsourcegui.cpp index ce15db692..80500ed4c 100644 --- a/plugins/samplesource/testsource/testsourcegui.cpp +++ b/plugins/samplesource/testsource/testsourcegui.cpp @@ -236,6 +236,13 @@ void TestSourceGui::on_qBias_valueChanged(int value) sendSettings(); } +void TestSourceGui::on_phaseImbalance_valueChanged(int value) +{ + ui->phaseImbalanceText->setText(QString(tr("%1 %").arg(value))); + m_settings.m_phaseImbalance = value / 100.0f; + sendSettings(); +} + void TestSourceGui::on_record_toggled(bool checked) { if (checked) { diff --git a/plugins/samplesource/testsource/testsourcegui.h b/plugins/samplesource/testsource/testsourcegui.h index ccbab9835..f66eba45d 100644 --- a/plugins/samplesource/testsource/testsourcegui.h +++ b/plugins/samplesource/testsource/testsourcegui.h @@ -92,6 +92,7 @@ private slots: void on_dcBias_valueChanged(int value); void on_iBias_valueChanged(int value); void on_qBias_valueChanged(int value); + void on_phaseImbalance_valueChanged(int value); void on_record_toggled(bool checked); void updateStatus(); void updateHardware(); diff --git a/plugins/samplesource/testsource/testsourcegui.ui b/plugins/samplesource/testsource/testsourcegui.ui index c8b5f40dc..2479b89ba 100644 --- a/plugins/samplesource/testsource/testsourcegui.ui +++ b/plugins/samplesource/testsource/testsourcegui.ui @@ -624,12 +624,6 @@ - - - 45 - 0 - - -100 % @@ -688,12 +682,6 @@ - - - 45 - 0 - - -100 % @@ -745,6 +733,37 @@ + + -100 % + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Phase + + + + + + + - + + + + + + + + + + + + + 45 @@ -759,24 +778,23 @@ + + + + -99 + + + 1 + + + Qt::Horizontal + + + - - - - - Qt::Vertical - - - - 20 - 40 - - - - - + diff --git a/plugins/samplesource/testsource/testsourceinput.cpp b/plugins/samplesource/testsource/testsourceinput.cpp index 213176a3b..8a8ea5880 100644 --- a/plugins/samplesource/testsource/testsourceinput.cpp +++ b/plugins/samplesource/testsource/testsourceinput.cpp @@ -316,6 +316,13 @@ bool TestSourceInput::applySettings(const TestSourceSettings& settings, bool for } } + if ((m_settings.m_phaseImbalance != settings.m_phaseImbalance) || force) + { + if (m_testSourceThread != 0) { + m_testSourceThread->setPhaseImbalance(settings.m_phaseImbalance); + } + } + if ((m_settings.m_sampleSizeIndex != settings.m_sampleSizeIndex) || force) { if (m_testSourceThread != 0) { diff --git a/plugins/samplesource/testsource/testsourceplugin.cpp b/plugins/samplesource/testsource/testsourceplugin.cpp index 13bcacc88..618fb408d 100644 --- a/plugins/samplesource/testsource/testsourceplugin.cpp +++ b/plugins/samplesource/testsource/testsourceplugin.cpp @@ -29,7 +29,7 @@ const PluginDescriptor TestSourcePlugin::m_pluginDescriptor = { QString("Test Source input"), - QString("3.11.0"), + QString("3.12.0"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplesource/testsource/testsourcesettings.cpp b/plugins/samplesource/testsource/testsourcesettings.cpp index 6fe1aac82..0b234557f 100644 --- a/plugins/samplesource/testsource/testsourcesettings.cpp +++ b/plugins/samplesource/testsource/testsourcesettings.cpp @@ -37,6 +37,7 @@ void TestSourceSettings::resetToDefaults() m_dcFactor = 0.0f; m_iFactor = 0.0f; m_qFactor = 0.0f; + m_phaseImbalance = 0.0f; } QByteArray TestSourceSettings::serialize() const @@ -54,6 +55,7 @@ QByteArray TestSourceSettings::serialize() const s.writeFloat(10, m_dcFactor); s.writeFloat(11, m_iFactor); s.writeFloat(12, m_qFactor); + s.writeFloat(13, m_phaseImbalance); return s.final(); } @@ -84,6 +86,7 @@ bool TestSourceSettings::deserialize(const QByteArray& data) d.readFloat(10, &m_dcFactor, 0.0f); d.readFloat(11, &m_iFactor, 0.0f); d.readFloat(12, &m_qFactor, 0.0f); + d.readFloat(13, &m_phaseImbalance, 0.0f); return true; } diff --git a/plugins/samplesource/testsource/testsourcesettings.h b/plugins/samplesource/testsource/testsourcesettings.h index 883746a62..9c348e1fb 100644 --- a/plugins/samplesource/testsource/testsourcesettings.h +++ b/plugins/samplesource/testsource/testsourcesettings.h @@ -33,9 +33,10 @@ struct TestSourceSettings { qint32 m_amplitudeBits; bool m_dcBlock; bool m_iqImbalance; - float m_dcFactor; //!< -1.0 < x < 1.0 - float m_iFactor; //!< -1.0 < x < 1.0 - float m_qFactor; //!< -1.0 < x < 1.0 + float m_dcFactor; //!< -1.0 < x < 1.0 + float m_iFactor; //!< -1.0 < x < 1.0 + float m_qFactor; //!< -1.0 < x < 1.0 + float m_phaseImbalance; //!< -1.0 < x < 1.0 TestSourceSettings(); void resetToDefaults(); diff --git a/plugins/samplesource/testsource/testsourcethread.cpp b/plugins/samplesource/testsource/testsourcethread.cpp index b88a03271..5267fe58c 100644 --- a/plugins/samplesource/testsource/testsourcethread.cpp +++ b/plugins/samplesource/testsource/testsourcethread.cpp @@ -40,6 +40,7 @@ TestSourceThread::TestSourceThread(SampleSinkFifo* sampleFifo, QObject* parent) m_dcBias(0.0f), m_iBias(0.0f), m_qBias(0.0f), + m_phaseImbalance(0.0f), m_amplitudeBitsDC(0), m_amplitudeBitsI(127), m_amplitudeBitsQ(127), @@ -138,6 +139,11 @@ void TestSourceThread::setQFactor(float iFactor) m_amplitudeBitsQ = (1.0f + m_qBias) * m_amplitudeBits; } +void TestSourceThread::setPhaseImbalance(float phaseImbalance) +{ + m_phaseImbalance = phaseImbalance; +} + void TestSourceThread::setFrequencyShift(int shift) { m_nco.setFreq(shift, m_samplerate); @@ -189,7 +195,7 @@ void TestSourceThread::generate(quint32 chunksize) for (int i = 0; i < n-1;) { - Complex c = m_nco.nextIQ(); + Complex c = m_nco.nextIQ(m_phaseImbalance); m_buf[i++] = (int16_t) (c.real() * (float) m_amplitudeBitsI) + m_amplitudeBitsDC; m_buf[i++] = (int16_t) (c.imag() * (float) m_amplitudeBitsQ); } diff --git a/plugins/samplesource/testsource/testsourcethread.h b/plugins/samplesource/testsource/testsourcethread.h index d8a8f219c..43d64c78f 100644 --- a/plugins/samplesource/testsource/testsourcethread.h +++ b/plugins/samplesource/testsource/testsourcethread.h @@ -47,6 +47,7 @@ public: void setDCFactor(float iFactor); void setIFactor(float iFactor); void setQFactor(float qFactor); + void setPhaseImbalance(float phaseImbalance); void setFrequencyShift(int shift); void connectTimer(const QTimer& timer); @@ -73,6 +74,7 @@ private: float m_dcBias; float m_iBias; float m_qBias; + float m_phaseImbalance; int32_t m_amplitudeBitsDC; int32_t m_amplitudeBitsI; int32_t m_amplitudeBitsQ; diff --git a/sdrbase/dsp/ncof.cpp b/sdrbase/dsp/ncof.cpp index 361af4f1e..59ff93b9c 100644 --- a/sdrbase/dsp/ncof.cpp +++ b/sdrbase/dsp/ncof.cpp @@ -61,6 +61,14 @@ Complex NCOF::nextIQ() return Complex(m_table[phase], -m_table[(phase + TableSize / 4) % TableSize]); } +Complex NCOF::nextIQ(float imbalance) +{ + int phase = nextPhase(); + int phaseQ = imbalance < 0.0 ? phase + (int) (imbalance*TableSize) : phase; + int phaseI = imbalance < 0.0 ? phase : phase + (int) (imbalance*TableSize); + return Complex(m_table[phaseI % TableSize], -m_table[(phaseQ + TableSize / 4) % TableSize]); +} + Complex NCOF::nextQI() { int phase = nextPhase(); diff --git a/sdrbase/dsp/ncof.h b/sdrbase/dsp/ncof.h index 349541809..6c4217565 100644 --- a/sdrbase/dsp/ncof.h +++ b/sdrbase/dsp/ncof.h @@ -49,14 +49,15 @@ public: return (int) m_phase; } - Real next(); //!< Return next real sample - Complex nextIQ(); //!< Return next complex sample - Complex nextQI(); //!< Return next complex sample (reversed) - Real get(); //!< Return current real sample (no phase increment) - Complex getIQ(); //!< Return current complex sample (no phase increment) - void getIQ(Complex& c); //!< Sets to the current complex sample (no phase increment) - Complex getQI(); //!< Return current complex sample (no phase increment, reversed) - void getQI(Complex& c); //!< Sets to the current complex sample (no phase increment, reversed) + Real next(); //!< Return next real sample + Complex nextIQ(); //!< Return next complex sample + Complex nextIQ(float imbalance); //!< Return next complex sample with an imbalance factor on I + Complex nextQI(); //!< Return next complex sample (reversed) + Real get(); //!< Return current real sample (no phase increment) + Complex getIQ(); //!< Return current complex sample (no phase increment) + void getIQ(Complex& c); //!< Sets to the current complex sample (no phase increment) + Complex getQI(); //!< Return current complex sample (no phase increment, reversed) + void getQI(Complex& c); //!< Sets to the current complex sample (no phase increment, reversed) }; #endif // INCLUDE_NCO_H