From 41f640bd633b2f69876cddfce506a2c2a8e6aec2 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 14 Aug 2019 02:56:15 +0200 Subject: [PATCH] MIMO simplification --- plugins/samplemimo/testmi/testmi.cpp | 7 +- sdrbase/device/deviceapi.cpp | 8 +- sdrbase/device/deviceapi.h | 4 +- sdrbase/dsp/devicesamplemimo.h | 9 ++ sdrbase/dsp/dspdevicemimoengine.cpp | 176 ++++++++------------------- sdrbase/dsp/dspdevicemimoengine.h | 22 +--- 6 files changed, 77 insertions(+), 149 deletions(-) diff --git a/plugins/samplemimo/testmi/testmi.cpp b/plugins/samplemimo/testmi/testmi.cpp index 8a6fb176a..cae59c3ab 100644 --- a/plugins/samplemimo/testmi/testmi.cpp +++ b/plugins/samplemimo/testmi/testmi.cpp @@ -49,11 +49,10 @@ TestMI::TestMI(DeviceAPI *deviceAPI) : m_running(false), m_masterTimer(deviceAPI->getMasterTimer()) { + m_mimoType = MIMOAsynchronous; + m_sampleSinkFifos.push_back(SampleSinkFifo(96000 * 4)); + m_sampleSinkFifos.push_back(SampleSinkFifo(96000 * 4)); m_deviceAPI->setNbSourceStreams(2); - m_deviceAPI->addSourceStream(true); // Add a new source stream data set in the engine - asynchronous handling of FIFOs - m_deviceAPI->addSourceStream(true); // Add a new source stream data set in the engine - asynchronous handling of FIFOs - m_sampleSinkFifos.push_back(SampleSinkFifo(96000 * 4)); - m_sampleSinkFifos.push_back(SampleSinkFifo(96000 * 4)); m_networkManager = new QNetworkAccessManager(); connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); } diff --git a/sdrbase/device/deviceapi.cpp b/sdrbase/device/deviceapi.cpp index 9116b9861..a41e7806c 100644 --- a/sdrbase/device/deviceapi.cpp +++ b/sdrbase/device/deviceapi.cpp @@ -58,10 +58,10 @@ DeviceAPI::~DeviceAPI() { } -void DeviceAPI::addSourceStream(bool connect) +void DeviceAPI::addSourceStream() { if (m_deviceMIMOEngine) { - m_deviceMIMOEngine->addSourceStream(connect); + m_deviceMIMOEngine->addSourceStream(); } } @@ -72,10 +72,10 @@ void DeviceAPI::removeLastSourceStream() } } -void DeviceAPI::addSinkStream(bool connect) +void DeviceAPI::addSinkStream() { if (m_deviceMIMOEngine) { - m_deviceMIMOEngine->addSinkStream(connect); + m_deviceMIMOEngine->addSinkStream(); } } diff --git a/sdrbase/device/deviceapi.h b/sdrbase/device/deviceapi.h index 5e5536dea..60b4afc84 100644 --- a/sdrbase/device/deviceapi.h +++ b/sdrbase/device/deviceapi.h @@ -67,9 +67,9 @@ public: ~DeviceAPI(); // MIMO Engine baseband / channel lists management - void addSourceStream(bool connect); + void addSourceStream(); void removeLastSourceStream(); - void addSinkStream(bool connect); + void addSinkStream(); void removeLastSinkStream(); void addAncillarySink(BasebandSampleSink* sink, unsigned int index = 0); //!< Adds a sink to receive full baseband and that is not a channel (e.g. spectrum) diff --git a/sdrbase/dsp/devicesamplemimo.h b/sdrbase/dsp/devicesamplemimo.h index 54dcbc0ab..6dd597a3c 100644 --- a/sdrbase/dsp/devicesamplemimo.h +++ b/sdrbase/dsp/devicesamplemimo.h @@ -37,6 +37,13 @@ namespace SWGSDRangel class SDRBASE_API DeviceSampleMIMO : public QObject { Q_OBJECT public: + enum MIMOType //!< Type of MIMO + { + MIMOAsynchronous, //!< All streams are asynchronous (false MIMO) + MIMOHalfSynchronous, //!< MI + MO (synchronous inputs on one side and synchronous outputs on the other side) + MIMOFullSynchronous, //!< True MIMO (all streams synchronous) + }; + typedef enum { FC_POS_INFRA = 0, FC_POS_SUPRA, @@ -118,6 +125,7 @@ public: return 501; } + MIMOType getMIMOType() const { return m_mimoType; } MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual void setMessageQueueToGUI(MessageQueue *queue) = 0; // pure virtual so that child classes must have to deal with this MessageQueue *getMessageQueueToGUI() { return m_guiMessageQueue; } @@ -136,6 +144,7 @@ protected slots: void handleInputMessages(); protected: + MIMOType m_mimoType; std::vector m_sampleSourceFifos; //!< Tx FIFOs std::vector m_sampleSinkFifos; //!< Rx FIFOs MessageQueue m_inputMessageQueue; //!< Input queue to the sink diff --git a/sdrbase/dsp/dspdevicemimoengine.cpp b/sdrbase/dsp/dspdevicemimoengine.cpp index 75fbed646..42920e34d 100644 --- a/sdrbase/dsp/dspdevicemimoengine.cpp +++ b/sdrbase/dsp/dspdevicemimoengine.cpp @@ -121,10 +121,10 @@ void DSPDeviceMIMOEngine::setMIMOSequence(int sequence) m_sampleMIMOSequence = sequence; } -void DSPDeviceMIMOEngine::addSourceStream(bool connect) +void DSPDeviceMIMOEngine::addSourceStream() { qDebug("DSPDeviceMIMOEngine::addSourceStream"); - AddSourceStream cmd(connect); + AddSourceStream cmd; m_syncMessenger.sendWait(cmd); } @@ -135,10 +135,10 @@ void DSPDeviceMIMOEngine::removeLastSourceStream() m_syncMessenger.sendWait(cmd); } -void DSPDeviceMIMOEngine::addSinkStream(bool connect) +void DSPDeviceMIMOEngine::addSinkStream() { qDebug("DSPDeviceMIMOEngine::addSinkStream"); - AddSinkStream cmd(connect); + AddSinkStream cmd; m_syncMessenger.sendWait(cmd); } @@ -252,94 +252,8 @@ QString DSPDeviceMIMOEngine::deviceDescription() * Routes samples from device source FIFO to sink channels that are registered for the FIFO * Routes samples from source channels registered for the FIFO to the device sink FIFO */ -void DSPDeviceMIMOEngine::work(int nbWriteSamples) -{ - (void) nbWriteSamples; - // Sources - for (unsigned int isource = 0; isource < m_deviceSampleMIMO->getNbSourceStreams(); isource++) - { - SampleSinkFifo* sampleFifo = m_deviceSampleMIMO->getSampleSinkFifo(isource); // sink FIFO is for Rx - int samplesDone = 0; - bool positiveOnly = false; - - while ((sampleFifo->fill() > 0) && (m_inputMessageQueue.size() == 0) && (samplesDone < m_deviceSampleMIMO->getSourceSampleRate(isource))) - { - SampleVector::iterator part1begin; - SampleVector::iterator part1end; - SampleVector::iterator part2begin; - SampleVector::iterator part2end; - - std::size_t count = sampleFifo->readBegin(sampleFifo->fill(), &part1begin, &part1end, &part2begin, &part2end); - - // first part of FIFO data - if (part1begin != part1end) - { - // TODO: DC and IQ corrections - - // feed data to direct sinks - if (isource < m_basebandSampleSinks.size()) - { - for (BasebandSampleSinks::const_iterator it = m_basebandSampleSinks[isource].begin(); it != m_basebandSampleSinks[isource].end(); ++it) { - (*it)->feed(part1begin, part1end, positiveOnly); - } - } - - // possibly feed data to spectrum sink - if ((m_spectrumSink) && (m_spectrumInputSourceElseSink) && (isource == m_spectrumInputIndex)) { - m_spectrumSink->feed(part1begin, part1end, positiveOnly); - } - - // feed data to threaded sinks - if (isource < m_threadedBasebandSampleSinks.size()) - { - for (ThreadedBasebandSampleSinks::const_iterator it = m_threadedBasebandSampleSinks[isource].begin(); it != m_threadedBasebandSampleSinks[isource].end(); ++it) { - (*it)->feed(part1begin, part1end, positiveOnly); - } - } - } - - // second part of FIFO data (used when block wraps around) - if(part2begin != part2end) - { - // TODO: DC and IQ corrections - - // feed data to direct sinks - if (isource < m_basebandSampleSinks.size()) - { - for (BasebandSampleSinks::const_iterator it = m_basebandSampleSinks[isource].begin(); it != m_basebandSampleSinks[isource].end(); ++it) { - (*it)->feed(part2begin, part2end, positiveOnly); - } - } - - // possibly feed data to spectrum sink - if ((m_spectrumSink) && (m_spectrumInputSourceElseSink) && (isource == m_spectrumInputIndex)) { - m_spectrumSink->feed(part2begin, part2end, positiveOnly); - } - - // feed data to threaded sinks - if (isource < m_threadedBasebandSampleSinks.size()) - { - for (ThreadedBasebandSampleSinks::const_iterator it = m_threadedBasebandSampleSinks[isource].begin(); it != m_threadedBasebandSampleSinks[isource].end(); ++it) { - (*it)->feed(part2begin, part2end, positiveOnly); - } - } - } - - // adjust FIFO pointers - sampleFifo->readCommit((unsigned int) count); - samplesDone += count; - } // while stream FIFO - } // for stream source - - // TODO: sinks -} - void DSPDeviceMIMOEngine::workSampleSink(unsigned int sinkIndex) { - if (m_state != StRunning) { - return; - } - SampleSinkFifo* sampleFifo = m_deviceSampleMIMO->getSampleSinkFifo(sinkIndex); int samplesDone = 0; bool positiveOnly = false; @@ -622,11 +536,21 @@ DSPDeviceMIMOEngine::State DSPDeviceMIMOEngine::gotoError(const QString& errorMe return StError; } -void DSPDeviceMIMOEngine::handleData() +void DSPDeviceMIMOEngine::handleDataRxSync() { if (m_state == StRunning) - { - work(0); // TODO: implement Tx side + { + // Sources (move their samples into sinks) + for (unsigned int isource = 0; isource < m_deviceSampleMIMO->getNbSourceStreams(); isource++) { + workSampleSink(isource); + } + } +} + +void DSPDeviceMIMOEngine::handleDataRxAsync(unsigned int sinkIndex) +{ + if (m_state == StRunning) { + workSampleSink(sinkIndex); } } @@ -634,34 +558,52 @@ void DSPDeviceMIMOEngine::handleSetMIMO(DeviceSampleMIMO* mimo) { m_deviceSampleMIMO = mimo; - if (mimo) + if (!mimo) { // Early leave + return; + } + + for (int i = 0; i < m_deviceSampleMIMO->getNbSinkFifos(); i++) { - if ((m_sampleSinkConnectionIndexes.size() == 1) && (m_sampleSourceConnectionIndexes.size() == 0)) // true MIMO (synchronous FIFOs) + m_basebandSampleSinks.push_back(BasebandSampleSinks()); + m_threadedBasebandSampleSinks.push_back(ThreadedBasebandSampleSinks()); + m_sourcesCorrections.push_back(SourceCorrection()); + } + + for (int i = 0; i < m_deviceSampleMIMO->getNbSourceFifos(); i++) { + m_threadedBasebandSampleSources.push_back(ThreadedBasebandSampleSources()); + } + + if (m_deviceSampleMIMO->getMIMOType() == DeviceSampleMIMO::MIMOHalfSynchronous) // synchronous FIFOs on Rx and not with Tx + { + qDebug("DSPDeviceMIMOEngine::handleSetMIMO: synchronous sources set %s", qPrintable(mimo->getDeviceDescription())); + // connect(m_deviceSampleMIMO->getSampleSinkFifo(m_sampleSinkConnectionIndexes[0]), SIGNAL(dataReady()), this, SLOT(handleData()), Qt::QueuedConnection); + for (unsigned int isink = 0; isink < m_deviceSampleMIMO->getNbSinkFifos(); isink++) { - qDebug("DSPDeviceMIMOEngine::handleSetMIMO: synchronous set %s", qPrintable(mimo->getDeviceDescription())); - // connect(m_deviceSampleMIMO->getSampleSinkFifo(m_sampleSinkConnectionIndexes[0]), SIGNAL(dataReady()), this, SLOT(handleData()), Qt::QueuedConnection); + qDebug("DSPDeviceMIMOEngine::handleSetMIMO: synchronous sources set %s channel %u", + qPrintable(mimo->getDeviceDescription()), isink); QObject::connect( - m_deviceSampleMIMO->getSampleSinkFifo(m_sampleSinkConnectionIndexes[0]), + m_deviceSampleMIMO->getSampleSinkFifo(isink), &SampleSinkFifo::dataReady, this, - [=](){ this->handleData(); }, // lambda function is not strictly needed here + [=](){ this->handleDataRxSync(); }, // lambda function is not strictly needed here Qt::QueuedConnection ); + break; // use first available FIFO for sync signal } - else if (m_sampleSinkConnectionIndexes.size() != 0) // asynchronous FIFOs + } + else if (m_deviceSampleMIMO->getMIMOType() == DeviceSampleMIMO::MIMOAsynchronous) // asynchronous FIFOs + { + for (unsigned int isink = 0; isink < m_deviceSampleMIMO->getNbSinkFifos(); isink++) { - for (unsigned int isink = 0; isink < m_sampleSinkConnectionIndexes.size(); isink++) - { - qDebug("DSPDeviceMIMOEngine::handleSetMIMO: asynchronous sources set %s channel %u", - qPrintable(mimo->getDeviceDescription()), isink); - QObject::connect( - m_deviceSampleMIMO->getSampleSinkFifo(m_sampleSinkConnectionIndexes[isink]), - &SampleSinkFifo::dataReady, - this, - [=](){ this->workSampleSink(isink); }, - Qt::QueuedConnection - ); - } + qDebug("DSPDeviceMIMOEngine::handleSetMIMO: asynchronous sources set %s channel %u", + qPrintable(mimo->getDeviceDescription()), isink); + QObject::connect( + m_deviceSampleMIMO->getSampleSinkFifo(isink), + &SampleSinkFifo::dataReady, + this, + [=](){ this->handleDataRxAsync(isink); }, + Qt::QueuedConnection + ); } } @@ -705,13 +647,8 @@ void DSPDeviceMIMOEngine::handleSynchronousMessages() else if (AddSourceStream::match(*message)) { m_basebandSampleSinks.push_back(BasebandSampleSinks()); - int currentIndex = m_threadedBasebandSampleSinks.size(); m_threadedBasebandSampleSinks.push_back(ThreadedBasebandSampleSinks()); m_sourcesCorrections.push_back(SourceCorrection()); - - if (((AddSourceStream *) message)->getConnect()) { - m_sampleSinkConnectionIndexes.push_back(currentIndex); - } } else if (RemoveLastSourceStream::match(*message)) { @@ -720,12 +657,7 @@ void DSPDeviceMIMOEngine::handleSynchronousMessages() } else if (AddSinkStream::match(*message)) { - int currentIndex = m_threadedBasebandSampleSources.size(); m_threadedBasebandSampleSources.push_back(ThreadedBasebandSampleSources()); - - if (((AddSinkStream *) message)->getConnect()) { - m_sampleSourceConnectionIndexes.push_back(currentIndex); - } } else if (RemoveLastSinkStream::match(*message)) { diff --git a/sdrbase/dsp/dspdevicemimoengine.h b/sdrbase/dsp/dspdevicemimoengine.h index 742156057..c142195b3 100644 --- a/sdrbase/dsp/dspdevicemimoengine.h +++ b/sdrbase/dsp/dspdevicemimoengine.h @@ -63,11 +63,6 @@ public: class AddSourceStream : public Message { MESSAGE_CLASS_DECLARATION - public: - AddSourceStream(bool connect) : Message(), m_connect(connect) { } - bool getConnect() const { return m_connect; } - private: - bool m_connect; }; class RemoveLastSourceStream : public Message { @@ -76,11 +71,6 @@ public: class AddSinkStream : public Message { MESSAGE_CLASS_DECLARATION - public: - AddSinkStream(bool connect) : Message(), m_connect(connect) { } - bool getConnect() const { return m_connect; } - private: - bool m_connect; }; class RemoveLastSinkStream : public Message { @@ -256,9 +246,9 @@ public: void setMIMOSequence(int sequence); //!< Set the sample MIMO sequence in type uint getUID() const { return m_uid; } - void addSourceStream(bool connect); + void addSourceStream(); void removeLastSourceStream(); - void addSinkStream(bool connect); + void addSinkStream(); void removeLastSinkStream(); void addChannelSource(ThreadedBasebandSampleSource* source, int index = 0); //!< Add a channel source that will run on its own thread @@ -348,11 +338,9 @@ private: typedef std::list ThreadedBasebandSampleSinks; std::vector m_threadedBasebandSampleSinks; //!< channel sample sinks on their own thread (per input stream) - std::vector m_sampleSinkConnectionIndexes; typedef std::list ThreadedBasebandSampleSources; std::vector m_threadedBasebandSampleSources; //!< channel sample sources on their own threads (per output stream) - std::vector m_sampleSourceConnectionIndexes; std::vector m_sourcesCorrections; @@ -361,7 +349,7 @@ private: unsigned int m_spectrumInputIndex; //!< Index of the stream to be used as spectrum sink input void run(); - void work(int nbWriteSamples); //!< transfer samples if in running state + void workSampleSink(unsigned int sinkIndex); //!< transfer samples of one sink (asynchronously) State gotoIdle(); //!< Go to the idle state State gotoInit(); //!< Go to the acquisition init state from idle @@ -372,8 +360,8 @@ private: void iqCorrections(SampleVector::iterator begin, SampleVector::iterator end, int isource, bool imbalanceCorrection); private slots: - void handleData(); //!< Handle data when samples have to be processed - void workSampleSink(unsigned int sinkIndex); + void handleDataRxSync(); //!< Handle data when Rx samples have to be processed synchronously + void handleDataRxAsync(unsigned int sinkIndex); //!< Handle data when Rx samples have to be processed asynchronously void handleSynchronousMessages(); //!< Handle synchronous messages with the thread void handleInputMessages(); //!< Handle input message queue void handleForwardToSpectrumSink(int nbSamples);