mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 13:00:26 -04:00 
			
		
		
		
	MIMO simplification
This commit is contained in:
		
							parent
							
								
									ec22056cbf
								
							
						
					
					
						commit
						41f640bd63
					
				| @ -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*))); | ||||
| } | ||||
|  | ||||
| @ -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(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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)
 | ||||
|  | ||||
| @ -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<SampleSourceFifo> m_sampleSourceFifos; //!< Tx FIFOs
 | ||||
|     std::vector<SampleSinkFifo> m_sampleSinkFifos;     //!< Rx FIFOs
 | ||||
| 	MessageQueue m_inputMessageQueue; //!< Input queue to the sink
 | ||||
|  | ||||
| @ -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)) | ||||
|     { | ||||
|  | ||||
| @ -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<ThreadedBasebandSampleSink*> ThreadedBasebandSampleSinks; | ||||
| 	std::vector<ThreadedBasebandSampleSinks> m_threadedBasebandSampleSinks; //!< channel sample sinks on their own thread (per input stream)
 | ||||
|     std::vector<int> m_sampleSinkConnectionIndexes; | ||||
| 
 | ||||
| 	typedef std::list<ThreadedBasebandSampleSource*> ThreadedBasebandSampleSources; | ||||
| 	std::vector<ThreadedBasebandSampleSources> m_threadedBasebandSampleSources; //!< channel sample sources on their own threads (per output stream)
 | ||||
|     std::vector<int> m_sampleSourceConnectionIndexes; | ||||
| 
 | ||||
|     std::vector<SourceCorrection> 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); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user