MIMO: add channel to testMI (2)

This commit is contained in:
f4exb 2019-05-27 02:52:33 +02:00
parent eff28e8b63
commit f9a8523714
10 changed files with 182 additions and 38 deletions

View File

@ -36,6 +36,7 @@
#include "dsp/dspengine.h"
#include "dsp/threadedbasebandsamplesink.h"
#include "dsp/dspcommands.h"
#include "dsp/devicesamplemimo.h"
#include "dsp/fftfilt.h"
#include "device/deviceapi.h"
#include "util/db.h"
@ -374,7 +375,7 @@ bool AMDemod::handleMessage(const Message& cmd)
void AMDemod::applyAudioSampleRate(int sampleRate)
{
qDebug("AMDemod::applyAudioSampleRate: %d", sampleRate);
qDebug("AMDemod::applyAudioSampleRate: sampleRate: %d m_inputSampleRate: %d", sampleRate, m_inputSampleRate);
MsgConfigureChannelizer* channelConfigMsg = MsgConfigureChannelizer::create(
sampleRate, m_settings.m_inputFrequencyOffset);
@ -408,7 +409,8 @@ void AMDemod::applyChannelSettings(int inputSampleRate, int inputFrequencyOffset
{
qDebug() << "AMDemod::applyChannelSettings:"
<< " inputSampleRate: " << inputSampleRate
<< " inputFrequencyOffset: " << inputFrequencyOffset;
<< " inputFrequencyOffset: " << inputFrequencyOffset
<< " m_audioSampleRate: " << m_audioSampleRate;
if ((m_inputFrequencyOffset != inputFrequencyOffset) ||
(m_inputSampleRate != inputSampleRate) || force)
@ -526,7 +528,18 @@ void AMDemod::applySettings(const AMDemodSettings& settings, bool force)
reverseAPIKeys.append("volume");
}
if ((m_settings.m_streamIndex != settings.m_streamIndex) || force) {
if (m_settings.m_streamIndex != settings.m_streamIndex)
{
if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only
{
m_deviceAPI->removeChannelSinkAPI(this, m_settings.m_streamIndex);
m_deviceAPI->removeChannelSink(m_threadedChannelizer, m_settings.m_streamIndex);
m_deviceAPI->addChannelSink(m_threadedChannelizer, settings.m_streamIndex);
m_deviceAPI->addChannelSinkAPI(this, settings.m_streamIndex);
// apply stream sample rate to itself
applyChannelSettings(m_deviceAPI->getSampleMIMO()->getSourceSampleRate(settings.m_streamIndex), m_inputFrequencyOffset);
}
reverseAPIKeys.append("streamIndex");
}

View File

@ -240,6 +240,7 @@ void AMDemodGUI::onMenuDialogCalled(const QPoint &p)
dialog.exec();
m_settings.m_streamIndex = dialog.getSelectedStreamIndex();
displayStreamIndex();
applySettings();
}

View File

@ -51,9 +51,9 @@ TestMI::TestMI(DeviceAPI *deviceAPI) :
{
m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID()));
m_deviceAPI->setNbSourceStreams(2);
m_deviceAPI->addSourceStream(); // Add a new source stream data set in the engine
m_deviceAPI->addSourceStream(); // Add a new source stream data set in the engine
m_deviceAPI->addAncillarySink(m_fileSink);
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_deviceAPI->addAncillarySink(m_fileSink); TODO: implement when active
m_sampleSinkFifos.push_back(SampleSinkFifo(96000 * 4));
m_sampleSinkFifos.push_back(SampleSinkFifo(96000 * 4));
m_networkManager = new QNetworkAccessManager();
@ -87,15 +87,18 @@ void TestMI::init()
bool TestMI::start()
{
qDebug("TestMI::start");
QMutexLocker mutexLocker(&m_mutex);
if (m_running) stop();
if (m_running) {
stop();
}
m_testSourceThreads.push_back(new TestMIThread(&m_sampleSinkFifos[0]));
m_testSourceThreads.push_back(new TestMIThread(&m_sampleSinkFifos[0], 0));
m_testSourceThreads.back()->setSamplerate(m_settings.m_streams[0].m_sampleRate);
m_testSourceThreads.back()->startStop(true);
m_testSourceThreads.push_back(new TestMIThread(&m_sampleSinkFifos[1]));
m_testSourceThreads.push_back(new TestMIThread(&m_sampleSinkFifos[1], 1));
m_testSourceThreads.back()->setSamplerate(m_settings.m_streams[1].m_sampleRate);
m_testSourceThreads.back()->startStop(true);
@ -109,6 +112,7 @@ bool TestMI::start()
void TestMI::stop()
{
qDebug("TestMI::stop");
QMutexLocker mutexLocker(&m_mutex);
std::vector<TestMIThread*>::iterator it = m_testSourceThreads.begin();
@ -263,12 +267,10 @@ bool TestMI::applySettings(const TestMISettings& settings, bool force)
{
DeviceSettingsKeys deviceSettingsKeys;
QList<QList<QString>> streamReverseAPIKeys; // FIXME: one set of keys per streams
for (unsigned int istream = 0; istream < m_settings.m_streams.size(); istream++)
{
deviceSettingsKeys.m_streamsSettingsKeys.push_back(QList<QString>());
QList<QString>& reverseAPIKeys = streamReverseAPIKeys.back();
QList<QString>& reverseAPIKeys = deviceSettingsKeys.m_streamsSettingsKeys.back();
if ((m_settings.m_streams[istream].m_autoCorrOptions != settings.m_streams[istream].m_autoCorrOptions) || force)
{
@ -296,7 +298,8 @@ bool TestMI::applySettings(const TestMISettings& settings, bool force)
if ((istream < m_testSourceThreads.size()) && (m_testSourceThreads[istream]))
{
m_testSourceThreads[istream]->setSamplerate(settings.m_streams[istream].m_sampleRate);
qDebug("TestMI::applySettings: sample rate set to %d", settings.m_streams[istream].m_sampleRate);
qDebug("TestMI::applySettings: thread on stream: %u sample rate set to %d",
istream, settings.m_streams[istream].m_sampleRate);
}
}
@ -307,7 +310,8 @@ bool TestMI::applySettings(const TestMISettings& settings, bool force)
if ((istream < m_testSourceThreads.size()) && (m_testSourceThreads[istream]))
{
m_testSourceThreads[istream]->setLog2Decimation(settings.m_streams[istream].m_log2Decim);
qDebug() << "TestMI::applySettings: set decimation to " << (1<<settings.m_streams[istream].m_log2Decim);
qDebug("TestMI::applySettings: thread on stream: %u set decimation to %d",
istream, (1<<settings.m_streams[istream].m_log2Decim));
}
}
@ -347,7 +351,7 @@ bool TestMI::applySettings(const TestMISettings& settings, bool force)
m_testSourceThreads[istream]->setFcPos((int) settings.m_streams[istream].m_fcPos);
m_testSourceThreads[istream]->setFrequencyShift(frequencyShift);
qDebug() << "TestMI::applySettings:"
<< " istream: " << istream
<< " thread on istream: " << istream
<< " center freq: " << settings.m_streams[istream].m_centerFrequency << " Hz"
<< " device center freq: " << deviceCenterFrequency << " Hz"
<< " device sample rate: " << devSampleRate << "Hz"

View File

@ -28,7 +28,7 @@
MESSAGE_CLASS_DEFINITION(TestMIThread::MsgStartStop, Message)
TestMIThread::TestMIThread(SampleSinkFifo* sampleFifo, QObject* parent) :
TestMIThread::TestMIThread(SampleSinkFifo* sampleFifo, int streamIndex, QObject* parent) :
QThread(parent),
m_running(false),
m_buf(0),
@ -36,6 +36,7 @@ TestMIThread::TestMIThread(SampleSinkFifo* sampleFifo, QObject* parent) :
m_chunksize(0),
m_convertBuffer(TESTMI_BLOCKSIZE),
m_sampleFifo(sampleFifo),
m_streamIndex(streamIndex),
m_frequencyShift(0),
m_toneFrequency(440),
m_modulation(TestMIStreamSettings::ModulationNone),

View File

@ -58,7 +58,7 @@ public:
{ }
};
TestMIThread(SampleSinkFifo* sampleFifo, QObject* parent = 0);
TestMIThread(SampleSinkFifo* sampleFifo, int streamIndex, QObject* parent = 0);
~TestMIThread();
void startStop(bool start);
@ -90,6 +90,7 @@ private:
quint32 m_chunksize;
SampleVector m_convertBuffer;
SampleSinkFifo* m_sampleFifo;
int m_streamIndex;
NCOF m_nco;
NCOF m_toneNco;
int m_frequencyShift;

View File

@ -58,10 +58,10 @@ DeviceAPI::~DeviceAPI()
{
}
void DeviceAPI::addSourceStream()
void DeviceAPI::addSourceStream(bool connect)
{
if (m_deviceMIMOEngine) {
m_deviceMIMOEngine->addSourceStream();
m_deviceMIMOEngine->addSourceStream(connect);
}
}
@ -72,10 +72,10 @@ void DeviceAPI::removeLastSourceStream()
}
}
void DeviceAPI::addSinkStream()
void DeviceAPI::addSinkStream(bool connect)
{
if (m_deviceMIMOEngine) {
m_deviceMIMOEngine->addSinkStream();
m_deviceMIMOEngine->addSinkStream(connect);
}
}
@ -92,7 +92,7 @@ void DeviceAPI::addAncillarySink(BasebandSampleSink *sink)
m_deviceSourceEngine->addSink(sink);
} else if (m_deviceSinkEngine) {
m_deviceSinkEngine->addSpectrumSink(sink);
}
} // TODO: MIMO
}
void DeviceAPI::removeAncillarySink(BasebandSampleSink* sink)
@ -101,7 +101,7 @@ void DeviceAPI::removeAncillarySink(BasebandSampleSink* sink)
m_deviceSourceEngine->removeSink(sink);
} else if (m_deviceSinkEngine) {
m_deviceSinkEngine->removeSpectrumSink(sink);
}
} // TODO: MIMO
}
void DeviceAPI::setSpectrumSinkInput(bool sourceElseSink, unsigned int index)
@ -126,6 +126,8 @@ void DeviceAPI::removeChannelSink(ThreadedBasebandSampleSink* sink, int streamIn
if (m_deviceSourceEngine) {
m_deviceSourceEngine->removeThreadedSink(sink);
} else if (m_deviceMIMOEngine) {
m_deviceMIMOEngine->removeChannelSink(sink, streamIndex);
}
}

View File

@ -67,9 +67,9 @@ public:
~DeviceAPI();
// MIMO Engine baseband / channel lists management
void addSourceStream();
void addSourceStream(bool connect);
void removeLastSourceStream();
void addSinkStream();
void addSinkStream(bool connect);
void removeLastSinkStream();
void addAncillarySink(BasebandSampleSink* sink); //!< Adds a sink to receive full baseband and that is not a channel (e.g. spectrum)

View File

@ -122,10 +122,10 @@ void DSPDeviceMIMOEngine::setMIMOSequence(int sequence)
m_sampleMIMOSequence = sequence;
}
void DSPDeviceMIMOEngine::addSourceStream()
void DSPDeviceMIMOEngine::addSourceStream(bool connect)
{
qDebug("DSPDeviceMIMOEngine::addSourceStream");
AddSourceStream cmd;
AddSourceStream cmd(connect);
m_syncMessenger.sendWait(cmd);
}
@ -136,10 +136,10 @@ void DSPDeviceMIMOEngine::removeLastSourceStream()
m_syncMessenger.sendWait(cmd);
}
void DSPDeviceMIMOEngine::addSinkStream()
void DSPDeviceMIMOEngine::addSinkStream(bool connect)
{
qDebug("DSPDeviceMIMOEngine::addSinkStream");
AddSinkStream cmd;
AddSinkStream cmd(connect);
m_syncMessenger.sendWait(cmd);
}
@ -335,6 +335,81 @@ void DSPDeviceMIMOEngine::work(int nbWriteSamples)
// 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;
while ((sampleFifo->fill() > 0) && (m_inputMessageQueue.size() == 0) && (samplesDone < m_deviceSampleMIMO->getSourceSampleRate(sinkIndex)))
{
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 (sinkIndex < m_basebandSampleSinks.size())
{
for (BasebandSampleSinks::const_iterator it = m_basebandSampleSinks[sinkIndex].begin(); it != m_basebandSampleSinks[sinkIndex].end(); ++it) {
(*it)->feed(part1begin, part1end, positiveOnly);
}
}
// possibly feed data to spectrum sink
if ((m_spectrumSink) && (m_spectrumInputSourceElseSink) && (sinkIndex == m_spectrumInputIndex)) {
m_spectrumSink->feed(part1begin, part1end, positiveOnly);
}
// feed data to threaded sinks
for (ThreadedBasebandSampleSinks::const_iterator it = m_threadedBasebandSampleSinks[sinkIndex].begin(); it != m_threadedBasebandSampleSinks[sinkIndex].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 (sinkIndex < m_basebandSampleSinks.size())
{
for (BasebandSampleSinks::const_iterator it = m_basebandSampleSinks[sinkIndex].begin(); it != m_basebandSampleSinks[sinkIndex].end(); ++it) {
(*it)->feed(part2begin, part2end, positiveOnly);
}
}
// possibly feed data to spectrum sink
if ((m_spectrumSink) && (m_spectrumInputSourceElseSink) && (sinkIndex == m_spectrumInputIndex)) {
m_spectrumSink->feed(part2begin, part2end, positiveOnly);
}
// feed data to threaded sinks
for (ThreadedBasebandSampleSinks::const_iterator it = m_threadedBasebandSampleSinks[sinkIndex].begin(); it != m_threadedBasebandSampleSinks[sinkIndex].end(); ++it)
{
(*it)->feed(part2begin, part2end, positiveOnly);
}
}
// adjust FIFO pointers
sampleFifo->readCommit((unsigned int) count);
samplesDone += count;
}
}
// notStarted -> idle -> init -> running -+
// ^ |
// +-----------------------+
@ -544,7 +619,7 @@ DSPDeviceMIMOEngine::State DSPDeviceMIMOEngine::gotoError(const QString& errorMe
void DSPDeviceMIMOEngine::handleData()
{
if(m_state == StRunning)
if (m_state == StRunning)
{
work(0); // TODO: implement Tx side
}
@ -554,14 +629,38 @@ void DSPDeviceMIMOEngine::handleSetMIMO(DeviceSampleMIMO* mimo)
{
m_deviceSampleMIMO = mimo;
if (mimo && (mimo->getNbSinkFifos() > 0))
if (mimo)
{
// if there is at least one Rx then the first Rx drives the FIFOs
qDebug("DSPDeviceMIMOEngine::handleSetMIMO: set %s", qPrintable(mimo->getDeviceDescription()));
connect(m_deviceSampleMIMO->getSampleSinkFifo(0), SIGNAL(dataReady()), this, SLOT(handleData()), Qt::QueuedConnection);
if ((m_sampleSinkConnectionIndexes.size() == 1) && (m_sampleSourceConnectionIndexes.size() == 0)) // true MIMO (synchronous FIFOs)
{
qDebug("DSPDeviceMIMOEngine::handleSetMIMO: synchronous set %s", qPrintable(mimo->getDeviceDescription()));
// connect(m_deviceSampleMIMO->getSampleSinkFifo(m_sampleSinkConnectionIndexes[0]), SIGNAL(dataReady()), this, SLOT(handleData()), Qt::QueuedConnection);
QObject::connect(
m_deviceSampleMIMO->getSampleSinkFifo(m_sampleSinkConnectionIndexes[0]),
&SampleSinkFifo::dataReady,
this,
[=](){ this->handleData(); }, // lambda function is not strictly needed here
Qt::QueuedConnection
);
}
else if (m_sampleSinkConnectionIndexes.size() != 0) // asynchronous FIFOs
{
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
);
}
}
}
// TODO: only Tx
// TODO: Tx
}
void DSPDeviceMIMOEngine::handleSynchronousMessages()
@ -601,8 +700,13 @@ 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))
{
@ -611,7 +715,12 @@ 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))
{

View File

@ -62,6 +62,11 @@ 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 {
@ -70,6 +75,11 @@ 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 {
@ -266,9 +276,9 @@ public:
void setMIMOSequence(int sequence); //!< Set the sample MIMO sequence in type
uint getUID() const { return m_uid; }
void addSourceStream();
void addSourceStream(bool connect);
void removeLastSourceStream();
void addSinkStream();
void addSinkStream(bool connect);
void removeLastSinkStream();
void addChannelSource(ThreadedBasebandSampleSource* source, int index = 0); //!< Add a channel source that will run on its own thread
@ -358,9 +368,11 @@ 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;
@ -380,6 +392,7 @@ private:
private slots:
void handleData(); //!< Handle data when samples have to be processed
void workSampleSink(unsigned int sinkIndex);
void handleSynchronousMessages(); //!< Handle synchronous messages with the thread
void handleInputMessages(); //!< Handle input message queue
void handleForwardToSpectrumSink(int nbSamples);

View File

@ -1837,7 +1837,7 @@ void MainWindow::sampleMIMOChanged()
deviceUI->m_deviceAPI->setSamplingDevicePluginInterface(
DeviceEnumerator::instance()->getMIMOPluginInterface(deviceUI->m_samplingDeviceControl->getSelectedDeviceIndex()));
// constructs new GUI and output object
// constructs new GUI and MIMO object
DeviceSampleMIMO *mimo = deviceUI->m_deviceAPI->getPluginInterface()->createSampleMIMOPluginInstance(
deviceUI->m_deviceAPI->getSamplingDeviceId(), deviceUI->m_deviceAPI);
deviceUI->m_deviceAPI->setSampleMIMO(mimo);