1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-11-09 07:40:24 -05:00

IQ swap: implementation in MIMO plugins

This commit is contained in:
f4exb 2020-06-21 11:46:25 +02:00
parent 24aa55027c
commit f9f1a1d99c
15 changed files with 291 additions and 53 deletions

View File

@ -42,6 +42,7 @@ void BladeRF2MIMOSettings::resetToDefaults()
m_iqCorrection = false; m_iqCorrection = false;
m_rxTransverterMode = false; m_rxTransverterMode = false;
m_rxTransverterDeltaFrequency = 0; m_rxTransverterDeltaFrequency = 0;
m_iqOrder = true;
m_txCenterFrequency = 435000*1000; m_txCenterFrequency = 435000*1000;
m_log2Interp = 0; m_log2Interp = 0;
@ -80,6 +81,7 @@ QByteArray BladeRF2MIMOSettings::serialize() const
s.writeBool(20, m_iqCorrection); s.writeBool(20, m_iqCorrection);
s.writeBool(21, m_rxTransverterMode); s.writeBool(21, m_rxTransverterMode);
s.writeS64(22, m_rxTransverterDeltaFrequency); s.writeS64(22, m_rxTransverterDeltaFrequency);
s.writeBool(23, m_iqOrder);
s.writeU64(30, m_txCenterFrequency); s.writeU64(30, m_txCenterFrequency);
s.writeU32(31, m_log2Interp); s.writeU32(31, m_log2Interp);
@ -132,6 +134,7 @@ bool BladeRF2MIMOSettings::deserialize(const QByteArray& data)
d.readBool(20, &m_iqCorrection); d.readBool(20, &m_iqCorrection);
d.readBool(21, &m_rxTransverterMode, false); d.readBool(21, &m_rxTransverterMode, false);
d.readS64(22, &m_rxTransverterDeltaFrequency, 0); d.readS64(22, &m_rxTransverterDeltaFrequency, 0);
d.readBool(23, &m_iqOrder, true);
d.readU64(30, &m_txCenterFrequency, 435000*1000); d.readU64(30, &m_txCenterFrequency, 435000*1000);
d.readU32(31, &m_log2Interp); d.readU32(31, &m_log2Interp);

View File

@ -44,6 +44,7 @@ struct BladeRF2MIMOSettings {
bool m_iqCorrection; bool m_iqCorrection;
bool m_rxTransverterMode; bool m_rxTransverterMode;
qint64 m_rxTransverterDeltaFrequency; qint64 m_rxTransverterDeltaFrequency;
bool m_iqOrder; //!< true: IQ - false: QI
quint64 m_txCenterFrequency; quint64 m_txCenterFrequency;
quint32 m_log2Interp; quint32 m_log2Interp;

View File

@ -26,7 +26,8 @@ BladeRF2MIThread::BladeRF2MIThread(struct bladerf* dev, QObject* parent) :
QThread(parent), QThread(parent),
m_running(false), m_running(false),
m_dev(dev), m_dev(dev),
m_sampleFifo(nullptr) m_sampleFifo(nullptr),
m_iqOrder(true)
{ {
qDebug("BladeRF2MIThread::BladeRF2MIThread"); qDebug("BladeRF2MIThread::BladeRF2MIThread");
m_buf = new qint16[2*DeviceBladeRF2::blockSize*2]; m_buf = new qint16[2*DeviceBladeRF2::blockSize*2];
@ -135,7 +136,12 @@ void BladeRF2MIThread::callback(const qint16* buf, qint32 samplesPerChannel)
for (unsigned int channel = 0; channel < 2; channel++) for (unsigned int channel = 0; channel < 2; channel++)
{ {
lengths[channel] = channelCallback(&buf[2*samplesPerChannel*channel], 2*samplesPerChannel, channel); if (m_iqOrder) {
lengths[channel] = channelCallbackIQ(&buf[2*samplesPerChannel*channel], 2*samplesPerChannel, channel);
} else {
lengths[channel] = channelCallbackQI(&buf[2*samplesPerChannel*channel], 2*samplesPerChannel, channel);
}
vbegin.push_back(m_convertBuffer[channel].begin()); vbegin.push_back(m_convertBuffer[channel].begin());
} }
@ -150,13 +156,13 @@ void BladeRF2MIThread::callback(const qint16* buf, qint32 samplesPerChannel)
} }
} }
int BladeRF2MIThread::channelCallback(const qint16* buf, qint32 len, int channel) int BladeRF2MIThread::channelCallbackIQ(const qint16* buf, qint32 len, int channel)
{ {
SampleVector::iterator it = m_convertBuffer[channel].begin(); SampleVector::iterator it = m_convertBuffer[channel].begin();
if (m_log2Decim == 0) if (m_log2Decim == 0)
{ {
m_decimators[channel].decimate1(&it, buf, len); m_decimatorsIQ[channel].decimate1(&it, buf, len);
} }
else else
{ {
@ -165,22 +171,22 @@ int BladeRF2MIThread::channelCallback(const qint16* buf, qint32 len, int channel
switch (m_log2Decim) switch (m_log2Decim)
{ {
case 1: case 1:
m_decimators[channel].decimate2_inf(&it, buf, len); m_decimatorsIQ[channel].decimate2_inf(&it, buf, len);
break; break;
case 2: case 2:
m_decimators[channel].decimate4_inf(&it, buf, len); m_decimatorsIQ[channel].decimate4_inf(&it, buf, len);
break; break;
case 3: case 3:
m_decimators[channel].decimate8_inf(&it, buf, len); m_decimatorsIQ[channel].decimate8_inf(&it, buf, len);
break; break;
case 4: case 4:
m_decimators[channel].decimate16_inf(&it, buf, len); m_decimatorsIQ[channel].decimate16_inf(&it, buf, len);
break; break;
case 5: case 5:
m_decimators[channel].decimate32_inf(&it, buf, len); m_decimatorsIQ[channel].decimate32_inf(&it, buf, len);
break; break;
case 6: case 6:
m_decimators[channel].decimate64_inf(&it, buf, len); m_decimatorsIQ[channel].decimate64_inf(&it, buf, len);
break; break;
default: default:
break; break;
@ -191,22 +197,22 @@ int BladeRF2MIThread::channelCallback(const qint16* buf, qint32 len, int channel
switch (m_log2Decim) switch (m_log2Decim)
{ {
case 1: case 1:
m_decimators[channel].decimate2_sup(&it, buf, len); m_decimatorsIQ[channel].decimate2_sup(&it, buf, len);
break; break;
case 2: case 2:
m_decimators[channel].decimate4_sup(&it, buf, len); m_decimatorsIQ[channel].decimate4_sup(&it, buf, len);
break; break;
case 3: case 3:
m_decimators[channel].decimate8_sup(&it, buf, len); m_decimatorsIQ[channel].decimate8_sup(&it, buf, len);
break; break;
case 4: case 4:
m_decimators[channel].decimate16_sup(&it, buf, len); m_decimatorsIQ[channel].decimate16_sup(&it, buf, len);
break; break;
case 5: case 5:
m_decimators[channel].decimate32_sup(&it, buf, len); m_decimatorsIQ[channel].decimate32_sup(&it, buf, len);
break; break;
case 6: case 6:
m_decimators[channel].decimate64_sup(&it, buf, len); m_decimatorsIQ[channel].decimate64_sup(&it, buf, len);
break; break;
default: default:
break; break;
@ -217,22 +223,115 @@ int BladeRF2MIThread::channelCallback(const qint16* buf, qint32 len, int channel
switch (m_log2Decim) switch (m_log2Decim)
{ {
case 1: case 1:
m_decimators[channel].decimate2_cen(&it, buf, len); m_decimatorsIQ[channel].decimate2_cen(&it, buf, len);
break; break;
case 2: case 2:
m_decimators[channel].decimate4_cen(&it, buf, len); m_decimatorsIQ[channel].decimate4_cen(&it, buf, len);
break; break;
case 3: case 3:
m_decimators[channel].decimate8_cen(&it, buf, len); m_decimatorsIQ[channel].decimate8_cen(&it, buf, len);
break; break;
case 4: case 4:
m_decimators[channel].decimate16_cen(&it, buf, len); m_decimatorsIQ[channel].decimate16_cen(&it, buf, len);
break; break;
case 5: case 5:
m_decimators[channel].decimate32_cen(&it, buf, len); m_decimatorsIQ[channel].decimate32_cen(&it, buf, len);
break; break;
case 6: case 6:
m_decimators[channel].decimate64_cen(&it, buf, len); m_decimatorsIQ[channel].decimate64_cen(&it, buf, len);
break;
default:
break;
}
}
}
return it - m_convertBuffer[channel].begin();
}
int BladeRF2MIThread::channelCallbackQI(const qint16* buf, qint32 len, int channel)
{
SampleVector::iterator it = m_convertBuffer[channel].begin();
if (m_log2Decim == 0)
{
m_decimatorsQI[channel].decimate1(&it, buf, len);
}
else
{
if (m_fcPos == 0) // Infra
{
switch (m_log2Decim)
{
case 1:
m_decimatorsQI[channel].decimate2_inf(&it, buf, len);
break;
case 2:
m_decimatorsQI[channel].decimate4_inf(&it, buf, len);
break;
case 3:
m_decimatorsQI[channel].decimate8_inf(&it, buf, len);
break;
case 4:
m_decimatorsQI[channel].decimate16_inf(&it, buf, len);
break;
case 5:
m_decimatorsQI[channel].decimate32_inf(&it, buf, len);
break;
case 6:
m_decimatorsQI[channel].decimate64_inf(&it, buf, len);
break;
default:
break;
}
}
else if (m_fcPos == 1) // Supra
{
switch (m_log2Decim)
{
case 1:
m_decimatorsQI[channel].decimate2_sup(&it, buf, len);
break;
case 2:
m_decimatorsQI[channel].decimate4_sup(&it, buf, len);
break;
case 3:
m_decimatorsQI[channel].decimate8_sup(&it, buf, len);
break;
case 4:
m_decimatorsQI[channel].decimate16_sup(&it, buf, len);
break;
case 5:
m_decimatorsQI[channel].decimate32_sup(&it, buf, len);
break;
case 6:
m_decimatorsQI[channel].decimate64_sup(&it, buf, len);
break;
default:
break;
}
}
else if (m_fcPos == 2) // Center
{
switch (m_log2Decim)
{
case 1:
m_decimatorsQI[channel].decimate2_cen(&it, buf, len);
break;
case 2:
m_decimatorsQI[channel].decimate4_cen(&it, buf, len);
break;
case 3:
m_decimatorsQI[channel].decimate8_cen(&it, buf, len);
break;
case 4:
m_decimatorsQI[channel].decimate16_cen(&it, buf, len);
break;
case 5:
m_decimatorsQI[channel].decimate32_cen(&it, buf, len);
break;
case 6:
m_decimatorsQI[channel].decimate64_cen(&it, buf, len);
break; break;
default: default:
break; break;

View File

@ -57,13 +57,16 @@ private:
qint16 *m_buf; qint16 *m_buf;
SampleVector m_convertBuffer[2]; SampleVector m_convertBuffer[2];
SampleMIFifo* m_sampleFifo; SampleMIFifo* m_sampleFifo;
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12> m_decimators[2]; Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12, true> m_decimatorsIQ[2];
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12, false> m_decimatorsQI[2];
unsigned int m_log2Decim; unsigned int m_log2Decim;
int m_fcPos; int m_fcPos;
bool m_iqOrder;
void run(); void run();
void callback(const qint16* buf, qint32 samplesPerChannel); void callback(const qint16* buf, qint32 samplesPerChannel);
int channelCallback(const qint16* buf, qint32 len, int channel); int channelCallbackIQ(const qint16* buf, qint32 len, int channel);
int channelCallbackQI(const qint16* buf, qint32 len, int channel);
}; };
#endif // PLUGINS_SAMPLEMIMO_BLADERF2MIMO_BLADERF2MITHREAD_H_ #endif // PLUGINS_SAMPLEMIMO_BLADERF2MIMO_BLADERF2MITHREAD_H_

View File

@ -296,6 +296,7 @@ bool LimeSDRMIMO::startRx()
m_sampleMIFifo.reset(); m_sampleMIFifo.reset();
m_sourceThread->setFifo(&m_sampleMIFifo); m_sourceThread->setFifo(&m_sampleMIFifo);
m_sourceThread->setLog2Decimation(m_settings.m_log2SoftDecim); m_sourceThread->setLog2Decimation(m_settings.m_log2SoftDecim);
m_sourceThread->setIQOrder(m_settings.m_iqOrder);
m_sourceThread->startWork(); m_sourceThread->startWork();
mutexLocker.unlock(); mutexLocker.unlock();
m_runningRx = true; m_runningRx = true;
@ -951,6 +952,15 @@ bool LimeSDRMIMO::applySettings(const LimeSDRMIMOSettings& settings, bool force)
} }
} }
if ((m_settings.m_iqOrder != settings.m_iqOrder) || force)
{
reverseAPIKeys.append("iqOrder");
if (m_sourceThread) {
m_sourceThread->setIQOrder(settings.m_iqOrder);
}
}
if ((m_settings.m_antennaPathRx0 != settings.m_antennaPathRx0) || force) if ((m_settings.m_antennaPathRx0 != settings.m_antennaPathRx0) || force)
{ {
reverseAPIKeys.append("antennaPathRx0"); reverseAPIKeys.append("antennaPathRx0");

View File

@ -44,6 +44,7 @@ void LimeSDRMIMOSettings::resetToDefaults()
m_iqCorrection = false; m_iqCorrection = false;
m_rxTransverterMode = false; m_rxTransverterMode = false;
m_rxTransverterDeltaFrequency = 0; m_rxTransverterDeltaFrequency = 0;
m_iqOrder = true;
m_ncoEnableRx = false; m_ncoEnableRx = false;
m_ncoFrequencyRx = 0; m_ncoFrequencyRx = 0;
@ -112,6 +113,7 @@ QByteArray LimeSDRMIMOSettings::serialize() const
s.writeS64(26, m_rxTransverterDeltaFrequency); s.writeS64(26, m_rxTransverterDeltaFrequency);
s.writeBool(27, m_ncoEnableRx); s.writeBool(27, m_ncoEnableRx);
s.writeS32(28, m_ncoFrequencyRx); s.writeS32(28, m_ncoFrequencyRx);
s.writeBool(29, m_iqOrder);
s.writeFloat(30, m_lpfBWRx0); s.writeFloat(30, m_lpfBWRx0);
s.writeBool(31, m_lpfFIREnableRx0); s.writeBool(31, m_lpfFIREnableRx0);
@ -201,6 +203,7 @@ bool LimeSDRMIMOSettings::deserialize(const QByteArray& data)
d.readS64(26, &m_rxTransverterDeltaFrequency, 0); d.readS64(26, &m_rxTransverterDeltaFrequency, 0);
d.readBool(27, &m_ncoEnableRx, false); d.readBool(27, &m_ncoEnableRx, false);
d.readS32(28, &m_ncoFrequencyRx, 0); d.readS32(28, &m_ncoFrequencyRx, 0);
d.readBool(29, &m_iqOrder, true);
d.readFloat(30, &m_lpfBWRx0, 1.5e6); d.readFloat(30, &m_lpfBWRx0, 1.5e6);
d.readBool(31, &m_lpfFIREnableRx0, false); d.readBool(31, &m_lpfFIREnableRx0, false);

View File

@ -71,6 +71,7 @@ struct LimeSDRMIMOSettings
bool m_iqCorrection; bool m_iqCorrection;
bool m_rxTransverterMode; bool m_rxTransverterMode;
qint64 m_rxTransverterDeltaFrequency; qint64 m_rxTransverterDeltaFrequency;
bool m_iqOrder;
bool m_ncoEnableRx; //!< Rx Enable TSP NCO and mixing bool m_ncoEnableRx; //!< Rx Enable TSP NCO and mixing
int m_ncoFrequencyRx; //!< Rx Actual NCO frequency (the resulting frequency with mixing is displayed) int m_ncoFrequencyRx; //!< Rx Actual NCO frequency (the resulting frequency with mixing is displayed)

View File

@ -24,7 +24,8 @@ LimeSDRMIThread::LimeSDRMIThread(lms_stream_t* stream0, lms_stream_t* stream1, Q
m_running(false), m_running(false),
m_stream0(stream0), m_stream0(stream0),
m_stream1(stream1), m_stream1(stream1),
m_sampleFifo(nullptr) m_sampleFifo(nullptr),
m_iqOrder(true)
{ {
qDebug("LimeSDRMIThread::LimeSDRMIThread"); qDebug("LimeSDRMIThread::LimeSDRMIThread");
@ -168,8 +169,17 @@ void LimeSDRMIThread::run()
res[1] = DeviceLimeSDR::blockSize; res[1] = DeviceLimeSDR::blockSize;
} }
lengths[0] = channelCallback(m_buf0, 2*res[0], 0); if (m_iqOrder)
lengths[1] = channelCallback(m_buf1, 2*res[1], 1); {
lengths[0] = channelCallbackIQ(m_buf0, 2*res[0], 0);
lengths[1] = channelCallbackIQ(m_buf1, 2*res[1], 1);
}
else
{
lengths[0] = channelCallbackQI(m_buf0, 2*res[0], 0);
lengths[1] = channelCallbackQI(m_buf1, 2*res[1], 1);
}
if (lengths[0] == lengths[1]) if (lengths[0] == lengths[1])
{ {
@ -186,35 +196,73 @@ void LimeSDRMIThread::run()
m_running = false; m_running = false;
} }
int LimeSDRMIThread::channelCallback(const qint16* buf, qint32 len, int channel) int LimeSDRMIThread::channelCallbackIQ(const qint16* buf, qint32 len, int channel)
{ {
SampleVector::iterator it = m_convertBuffer[channel].begin(); SampleVector::iterator it = m_convertBuffer[channel].begin();
if (m_log2Decim == 0) if (m_log2Decim == 0)
{ {
m_decimators[channel].decimate1(&it, buf, len); m_decimatorsIQ[channel].decimate1(&it, buf, len);
} }
else else
{ {
switch (m_log2Decim) switch (m_log2Decim)
{ {
case 1: case 1:
m_decimators[channel].decimate2_cen(&it, buf, len); m_decimatorsIQ[channel].decimate2_cen(&it, buf, len);
break; break;
case 2: case 2:
m_decimators[channel].decimate4_cen(&it, buf, len); m_decimatorsIQ[channel].decimate4_cen(&it, buf, len);
break; break;
case 3: case 3:
m_decimators[channel].decimate8_cen(&it, buf, len); m_decimatorsIQ[channel].decimate8_cen(&it, buf, len);
break; break;
case 4: case 4:
m_decimators[channel].decimate16_cen(&it, buf, len); m_decimatorsIQ[channel].decimate16_cen(&it, buf, len);
break; break;
case 5: case 5:
m_decimators[channel].decimate32_cen(&it, buf, len); m_decimatorsIQ[channel].decimate32_cen(&it, buf, len);
break; break;
case 6: case 6:
m_decimators[channel].decimate64_cen(&it, buf, len); m_decimatorsIQ[channel].decimate64_cen(&it, buf, len);
break;
default:
break;
}
}
return it - m_convertBuffer[channel].begin();
}
int LimeSDRMIThread::channelCallbackQI(const qint16* buf, qint32 len, int channel)
{
SampleVector::iterator it = m_convertBuffer[channel].begin();
if (m_log2Decim == 0)
{
m_decimatorsQI[channel].decimate1(&it, buf, len);
}
else
{
switch (m_log2Decim)
{
case 1:
m_decimatorsQI[channel].decimate2_cen(&it, buf, len);
break;
case 2:
m_decimatorsQI[channel].decimate4_cen(&it, buf, len);
break;
case 3:
m_decimatorsQI[channel].decimate8_cen(&it, buf, len);
break;
case 4:
m_decimatorsQI[channel].decimate16_cen(&it, buf, len);
break;
case 5:
m_decimatorsQI[channel].decimate32_cen(&it, buf, len);
break;
case 6:
m_decimatorsQI[channel].decimate64_cen(&it, buf, len);
break; break;
default: default:
break; break;

View File

@ -46,6 +46,7 @@ public:
unsigned int getLog2Decimation() const; unsigned int getLog2Decimation() const;
void setFifo(SampleMIFifo *sampleFifo) { m_sampleFifo = sampleFifo; } void setFifo(SampleMIFifo *sampleFifo) { m_sampleFifo = sampleFifo; }
SampleMIFifo *getFifo() { return m_sampleFifo; } SampleMIFifo *getFifo() { return m_sampleFifo; }
void setIQOrder(bool iqOrder) { m_iqOrder = iqOrder; }
private: private:
QMutex m_startWaitMutex; QMutex m_startWaitMutex;
@ -59,11 +60,14 @@ private:
SampleVector m_convertBuffer[2]; SampleVector m_convertBuffer[2];
std::vector<SampleVector::const_iterator> m_vBegin; std::vector<SampleVector::const_iterator> m_vBegin;
SampleMIFifo* m_sampleFifo; SampleMIFifo* m_sampleFifo;
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12> m_decimators[2]; Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12, true> m_decimatorsIQ[2];
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12, false> m_decimatorsQI[2];
unsigned int m_log2Decim; unsigned int m_log2Decim;
bool m_iqOrder;
void run(); void run();
int channelCallback(const qint16* buf, qint32 len, int channel); int channelCallbackIQ(const qint16* buf, qint32 len, int channel);
int channelCallbackQI(const qint16* buf, qint32 len, int channel);
}; };
#endif // PLUGINS_SAMPLEMIMO_LIMESDRMIMO_LIMESDRMITHREAD_H_ #endif // PLUGINS_SAMPLEMIMO_LIMESDRMIMO_LIMESDRMITHREAD_H_

View File

@ -131,9 +131,9 @@ private:
MessageQueue m_inputMessageQueue; MessageQueue m_inputMessageQueue;
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 8> m_decimators_8; Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 8, true> m_decimators_8;
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12> m_decimators_12; Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12, true> m_decimators_12;
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 16> m_decimators_16; Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 16, true> m_decimators_16;
void startWork(); void startWork();
void stopWork(); void stopWork();

View File

@ -137,6 +137,7 @@ bool XTRXMIMO::startRx()
m_sampleMIFifo.reset(); m_sampleMIFifo.reset();
m_sourceThread->setFifo(&m_sampleMIFifo); m_sourceThread->setFifo(&m_sampleMIFifo);
m_sourceThread->setLog2Decimation(m_settings.m_log2SoftDecim); m_sourceThread->setLog2Decimation(m_settings.m_log2SoftDecim);
m_sourceThread->setIQOrder(m_settings.m_iqOrder);
m_sourceThread->startWork(); m_sourceThread->startWork();
mutexLocker.unlock(); mutexLocker.unlock();
m_runningRx = true; m_runningRx = true;
@ -585,6 +586,15 @@ bool XTRXMIMO::applySettings(const XTRXMIMOSettings& settings, bool force)
} }
} }
if ((m_settings.m_iqOrder != settings.m_iqOrder) || force)
{
reverseAPIKeys.append("iqOrder");
if (m_sourceThread) {
m_sourceThread->setIQOrder(settings.m_iqOrder);
}
}
if ((m_settings.m_ncoFrequencyRx != settings.m_ncoFrequencyRx) || force) { if ((m_settings.m_ncoFrequencyRx != settings.m_ncoFrequencyRx) || force) {
reverseAPIKeys.append("ncoFrequencyRx"); reverseAPIKeys.append("ncoFrequencyRx");
} }

View File

@ -43,6 +43,7 @@ void XTRXMIMOSettings::resetToDefaults()
m_ncoEnableRx = false; m_ncoEnableRx = false;
m_ncoFrequencyRx = 0; m_ncoFrequencyRx = 0;
m_antennaPathRx = RXANT_LO; m_antennaPathRx = RXANT_LO;
m_iqOrder = true;
// Rx0 // Rx0
m_lpfBWRx0 = 4.5e6f; m_lpfBWRx0 = 4.5e6f;
m_gainRx0 = 50; m_gainRx0 = 50;
@ -98,6 +99,7 @@ QByteArray XTRXMIMOSettings::serialize() const
s.writeS32(25, m_ncoFrequencyRx); s.writeS32(25, m_ncoFrequencyRx);
s.writeS32(26, (int) m_antennaPathRx); s.writeS32(26, (int) m_antennaPathRx);
s.writeDouble(27, m_rxDevSampleRate); s.writeDouble(27, m_rxDevSampleRate);
s.writeBool(28, m_iqOrder);
// Rx0 // Rx0
s.writeFloat(30, m_lpfBWRx0); s.writeFloat(30, m_lpfBWRx0);
s.writeU32(31, m_gainRx0); s.writeU32(31, m_gainRx0);
@ -172,6 +174,7 @@ bool XTRXMIMOSettings::deserialize(const QByteArray& data)
d.readS32(26, &intval, 0); d.readS32(26, &intval, 0);
m_antennaPathRx = (RxAntenna) intval; m_antennaPathRx = (RxAntenna) intval;
d.readDouble(27, &m_rxDevSampleRate, 5e6); d.readDouble(27, &m_rxDevSampleRate, 5e6);
d.readBool(28, &m_iqOrder, true);
// Rx0 // Rx0
d.readFloat(30, &m_lpfBWRx0, 1.5e6); d.readFloat(30, &m_lpfBWRx0, 1.5e6);
d.readU32(31, &m_gainRx0, 50); d.readU32(31, &m_gainRx0, 50);

View File

@ -61,6 +61,7 @@ struct XTRXMIMOSettings
bool m_ncoEnableRx; //!< Enable TSP NCO and mixing bool m_ncoEnableRx; //!< Enable TSP NCO and mixing
int m_ncoFrequencyRx; //!< Actual NCO frequency (the resulting frequency with mixing is displayed) int m_ncoFrequencyRx; //!< Actual NCO frequency (the resulting frequency with mixing is displayed)
RxAntenna m_antennaPathRx; RxAntenna m_antennaPathRx;
bool m_iqOrder;
// Rx0 // Rx0
float m_lpfBWRx0; //!< LMS analog lowpass filter bandwidth (Hz) float m_lpfBWRx0; //!< LMS analog lowpass filter bandwidth (Hz)
uint32_t m_gainRx0; //!< Optimally distributed gain (dB) uint32_t m_gainRx0; //!< Optimally distributed gain (dB)

View File

@ -27,7 +27,8 @@ XTRXMIThread::XTRXMIThread(struct xtrx_dev *dev, QObject* parent) :
QThread(parent), QThread(parent),
m_running(false), m_running(false),
m_dev(dev), m_dev(dev),
m_sampleFifo(nullptr) m_sampleFifo(nullptr),
m_iqOrder(true)
{ {
qDebug("XTRXMIThread::XTRXMIThread"); qDebug("XTRXMIThread::XTRXMIThread");
@ -134,8 +135,17 @@ void XTRXMIThread::run()
qDebug("XTRXInputThread::run: overflow"); qDebug("XTRXInputThread::run: overflow");
} }
lengths[0] = callbackSI(0, (const qint16*) buffs[0], 2*nfo.out_samples); if (m_iqOrder)
lengths[1] = callbackSI(1, (const qint16*) buffs[1], 2*nfo.out_samples); {
lengths[0] = callbackSIIQ(0, (const qint16*) buffs[0], 2*nfo.out_samples);
lengths[1] = callbackSIIQ(1, (const qint16*) buffs[1], 2*nfo.out_samples);
}
else
{
lengths[0] = callbackSIQI(0, (const qint16*) buffs[0], 2*nfo.out_samples);
lengths[1] = callbackSIQI(1, (const qint16*) buffs[1], 2*nfo.out_samples);
}
if (lengths[0] == lengths[1]) if (lengths[0] == lengths[1])
{ {
@ -173,35 +183,73 @@ unsigned int XTRXMIThread::getLog2Decimation() const
return m_log2Decim; return m_log2Decim;
} }
int XTRXMIThread::callbackSI(unsigned int channel, const qint16* buf, qint32 len) int XTRXMIThread::callbackSIIQ(unsigned int channel, const qint16* buf, qint32 len)
{ {
SampleVector::iterator it = m_channels[channel].m_convertBuffer.begin(); SampleVector::iterator it = m_channels[channel].m_convertBuffer.begin();
if (m_log2Decim == 0) if (m_log2Decim == 0)
{ {
m_channels[channel].m_decimators.decimate1(&it, buf, len); m_channels[channel].m_decimatorsIQ.decimate1(&it, buf, len);
} }
else else
{ {
switch (m_log2Decim) switch (m_log2Decim)
{ {
case 1: case 1:
m_channels[channel].m_decimators.decimate2_cen(&it, buf, len); m_channels[channel].m_decimatorsIQ.decimate2_cen(&it, buf, len);
break; break;
case 2: case 2:
m_channels[channel].m_decimators.decimate4_cen(&it, buf, len); m_channels[channel].m_decimatorsIQ.decimate4_cen(&it, buf, len);
break; break;
case 3: case 3:
m_channels[channel].m_decimators.decimate8_cen(&it, buf, len); m_channels[channel].m_decimatorsIQ.decimate8_cen(&it, buf, len);
break; break;
case 4: case 4:
m_channels[channel].m_decimators.decimate16_cen(&it, buf, len); m_channels[channel].m_decimatorsIQ.decimate16_cen(&it, buf, len);
break; break;
case 5: case 5:
m_channels[channel].m_decimators.decimate32_cen(&it, buf, len); m_channels[channel].m_decimatorsIQ.decimate32_cen(&it, buf, len);
break; break;
case 6: case 6:
m_channels[channel].m_decimators.decimate64_cen(&it, buf, len); m_channels[channel].m_decimatorsIQ.decimate64_cen(&it, buf, len);
break;
default:
break;
}
}
return it - m_channels[channel].m_convertBuffer.begin();
}
int XTRXMIThread::callbackSIQI(unsigned int channel, const qint16* buf, qint32 len)
{
SampleVector::iterator it = m_channels[channel].m_convertBuffer.begin();
if (m_log2Decim == 0)
{
m_channels[channel].m_decimatorsQI.decimate1(&it, buf, len);
}
else
{
switch (m_log2Decim)
{
case 1:
m_channels[channel].m_decimatorsQI.decimate2_cen(&it, buf, len);
break;
case 2:
m_channels[channel].m_decimatorsQI.decimate4_cen(&it, buf, len);
break;
case 3:
m_channels[channel].m_decimatorsQI.decimate8_cen(&it, buf, len);
break;
case 4:
m_channels[channel].m_decimatorsQI.decimate16_cen(&it, buf, len);
break;
case 5:
m_channels[channel].m_decimatorsQI.decimate32_cen(&it, buf, len);
break;
case 6:
m_channels[channel].m_decimatorsQI.decimate64_cen(&it, buf, len);
break; break;
default: default:
break; break;

View File

@ -43,12 +43,14 @@ public:
unsigned int getLog2Decimation() const; unsigned int getLog2Decimation() const;
void setFifo(SampleMIFifo *sampleFifo) { m_sampleFifo = sampleFifo; } void setFifo(SampleMIFifo *sampleFifo) { m_sampleFifo = sampleFifo; }
SampleMIFifo *getFifo() { return m_sampleFifo; } SampleMIFifo *getFifo() { return m_sampleFifo; }
void setIQOrder(bool iqOrder) { m_iqOrder = iqOrder; }
private: private:
struct Channel struct Channel
{ {
SampleVector m_convertBuffer; SampleVector m_convertBuffer;
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12> m_decimators; Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12, true> m_decimatorsIQ;
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12, false> m_decimatorsQI;
}; };
QMutex m_startWaitMutex; QMutex m_startWaitMutex;
@ -61,9 +63,11 @@ private:
std::vector<SampleVector::const_iterator> m_vBegin; std::vector<SampleVector::const_iterator> m_vBegin;
SampleMIFifo* m_sampleFifo; SampleMIFifo* m_sampleFifo;
unsigned int m_log2Decim; unsigned int m_log2Decim;
bool m_iqOrder;
void run(); void run();
int callbackSI(unsigned int channel, const qint16* buf, qint32 len); int callbackSIIQ(unsigned int channel, const qint16* buf, qint32 len);
int callbackSIQI(unsigned int channel, const qint16* buf, qint32 len);
}; };
#endif // PLUGINS_SAMPLEMIMO_XTRXMIMO_XTRXMITHREAD_H_ #endif // PLUGINS_SAMPLEMIMO_XTRXMIMO_XTRXMITHREAD_H_