From bb8366bfde04bed40b8bbbb056b607218e2d0462 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 28 May 2019 08:56:36 +0200 Subject: [PATCH] MIMO: test MI source: implemented file record --- plugins/samplemimo/testmi/testmi.cpp | 38 +++++++++++++++++++------ plugins/samplemimo/testmi/testmi.h | 15 ++++++---- plugins/samplemimo/testmi/testmigui.cpp | 14 +++++++-- plugins/samplemimo/testmi/testmigui.h | 1 + sdrbase/device/deviceapi.cpp | 12 +++++--- sdrbase/device/deviceapi.h | 4 +-- sdrbase/dsp/filerecord.cpp | 8 ++++-- sdrbase/dsp/filerecord.h | 3 +- 8 files changed, 70 insertions(+), 25 deletions(-) diff --git a/plugins/samplemimo/testmi/testmi.cpp b/plugins/samplemimo/testmi/testmi.cpp index d34039475..9c061adc9 100644 --- a/plugins/samplemimo/testmi/testmi.cpp +++ b/plugins/samplemimo/testmi/testmi.cpp @@ -49,11 +49,9 @@ TestMI::TestMI(DeviceAPI *deviceAPI) : m_running(false), m_masterTimer(deviceAPI->getMasterTimer()) { - m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID())); 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_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(); @@ -69,10 +67,17 @@ TestMI::~TestMI() stop(); } - m_deviceAPI->removeAncillarySink(m_fileSink); + std::vector::iterator it = m_fileSinks.begin(); + int istream = 0; + + for (; it != m_fileSinks.end(); ++it, istream++) + { + m_deviceAPI->removeAncillarySink(*it, istream); + delete *it; + } + m_deviceAPI->removeLastSourceStream(); // Remove the last source stream data set in the engine m_deviceAPI->removeLastSourceStream(); // Remove the last source stream data set in the engine - delete m_fileSink; } void TestMI::destroy() @@ -82,6 +87,11 @@ void TestMI::destroy() void TestMI::init() { + m_fileSinks.push_back(new FileRecord(QString("test_0_%1.sdriq").arg(m_deviceAPI->getDeviceUID()))); + m_fileSinks.push_back(new FileRecord(QString("test_1_%1.sdriq").arg(m_deviceAPI->getDeviceUID()))); + m_deviceAPI->addAncillarySink(m_fileSinks[0], 0); + m_deviceAPI->addAncillarySink(m_fileSinks[1], 1); + applySettings(m_settings, true); } @@ -216,20 +226,21 @@ bool TestMI::handleMessage(const Message& message) { MsgFileRecord& conf = (MsgFileRecord&) message; qDebug() << "TestMI::handleMessage: MsgFileRecord: " << conf.getStartStop(); + int istream = conf.getStreamIndex(); if (conf.getStartStop()) { if (m_settings.m_fileRecordName.size() != 0) { - m_fileSink->setFileName(m_settings.m_fileRecordName); + m_fileSinks[istream]->setFileName(m_settings.m_fileRecordName + "_0.sdriq"); } else { - m_fileSink->genUniqueFileName(m_deviceAPI->getDeviceUID()); + m_fileSinks[istream]->genUniqueFileName(m_deviceAPI->getDeviceUID(), istream); } - m_fileSink->startRecording(); + m_fileSinks[istream]->startRecording(); } else { - m_fileSink->stopRecording(); + m_fileSinks[istream]->stopRecording(); } return true; @@ -421,7 +432,7 @@ bool TestMI::applySettings(const TestMISettings& settings, bool force) { int sampleRate = settings.m_streams[istream].m_sampleRate/(1<handleMessage(*notif); // forward to file sink + m_fileSinks[istream]->handleMessage(*notif); // forward to file sink DSPDeviceMIMOEngine::SignalNotification *engineNotif = new DSPDeviceMIMOEngine::SignalNotification( sampleRate, settings.m_streams[istream].m_centerFrequency, true, 0); m_deviceAPI->getDeviceEngineInputMessageQueue()->push(engineNotif); @@ -820,3 +831,12 @@ void TestMI::networkManagerFinished(QNetworkReply *reply) answer.chop(1); // remove last \n qDebug("TestMI::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); } + +bool TestMI::isRecording(unsigned int istream) const +{ + if (istream < m_fileSinks.size()) { + return m_fileSinks[istream]->isRecording(); + } else { + return false; + } +} \ No newline at end of file diff --git a/plugins/samplemimo/testmi/testmi.h b/plugins/samplemimo/testmi/testmi.h index 2e5be0c7c..33e3eed35 100644 --- a/plugins/samplemimo/testmi/testmi.h +++ b/plugins/samplemimo/testmi/testmi.h @@ -63,17 +63,20 @@ public: public: bool getStartStop() const { return m_startStop; } + int getStreamIndex() const { return m_streamIndex; } - static MsgFileRecord* create(bool startStop) { - return new MsgFileRecord(startStop); + static MsgFileRecord* create(bool startStop, int streamIndex) { + return new MsgFileRecord(startStop, streamIndex); } protected: bool m_startStop; + int m_streamIndex; - MsgFileRecord(bool startStop) : + MsgFileRecord(bool startStop, int streamIndex) : Message(), - m_startStop(startStop) + m_startStop(startStop), + m_streamIndex(streamIndex) { } }; @@ -141,6 +144,8 @@ public: SWGSDRangel::SWGDeviceState& response, QString& errorMessage); + bool isRecording(unsigned int istream) const; + private: struct DeviceSettingsKeys { @@ -149,7 +154,7 @@ private: }; DeviceAPI *m_deviceAPI; - FileRecord *m_fileSink; //!< File sink to record device I/Q output + std::vector m_fileSinks; //!< File sinks to record device I/Q output QMutex m_mutex; TestMISettings m_settings; std::vector m_testSourceThreads; diff --git a/plugins/samplemimo/testmi/testmigui.cpp b/plugins/samplemimo/testmi/testmigui.cpp index 68d715b5b..9d5a2b4de 100644 --- a/plugins/samplemimo/testmi/testmigui.cpp +++ b/plugins/samplemimo/testmi/testmigui.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// Copyright (C) 2019 Edouard Griffiths, F4EXB // // // // This program is free software; you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // @@ -145,6 +145,7 @@ void TestMIGui::on_startStop_toggled(bool checked) void TestMIGui::on_streamIndex_currentIndexChanged(int index) { m_streamIndex = index; + updateFileRecordStatus(); displaySettings(); } @@ -296,7 +297,7 @@ void TestMIGui::on_record_toggled(bool checked) ui->record->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); } - TestMI::MsgFileRecord* message = TestMI::MsgFileRecord::create(checked); + TestMI::MsgFileRecord* message = TestMI::MsgFileRecord::create(checked, m_streamIndex); m_sampleMIMO->getInputMessageQueue()->push(message); } @@ -376,6 +377,15 @@ void TestMIGui::updateFrequencyShiftLimit() ui->frequencyShift->setValueRange(false, 7, -sampleRate, sampleRate); } +void TestMIGui::updateFileRecordStatus() +{ + if (((TestMI*) m_sampleMIMO)->isRecording(m_streamIndex)) { + ui->record->setStyleSheet("QToolButton { background-color : red; }"); + } else { + ui->record->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); + } +} + void TestMIGui::displaySettings() { blockApplySettings(true); diff --git a/plugins/samplemimo/testmi/testmigui.h b/plugins/samplemimo/testmi/testmigui.h index d50184047..5113ac959 100644 --- a/plugins/samplemimo/testmi/testmigui.h +++ b/plugins/samplemimo/testmi/testmigui.h @@ -77,6 +77,7 @@ private: void updateAmpCoarseLimit(); void updateAmpFineLimit(); void updateFrequencyShiftLimit(); + void updateFileRecordStatus(); private slots: void handleInputMessages(); diff --git a/sdrbase/device/deviceapi.cpp b/sdrbase/device/deviceapi.cpp index 9992ecc09..f40e72bdb 100644 --- a/sdrbase/device/deviceapi.cpp +++ b/sdrbase/device/deviceapi.cpp @@ -86,22 +86,26 @@ void DeviceAPI::removeLastSinkStream() } } -void DeviceAPI::addAncillarySink(BasebandSampleSink *sink) +void DeviceAPI::addAncillarySink(BasebandSampleSink *sink, unsigned int index) { if (m_deviceSourceEngine) { m_deviceSourceEngine->addSink(sink); } else if (m_deviceSinkEngine) { m_deviceSinkEngine->addSpectrumSink(sink); - } // TODO: MIMO + } else if (m_deviceMIMOEngine) { + m_deviceMIMOEngine->addAncillarySink(sink, index); + } } -void DeviceAPI::removeAncillarySink(BasebandSampleSink* sink) +void DeviceAPI::removeAncillarySink(BasebandSampleSink* sink, unsigned int index) { if (m_deviceSourceEngine) { m_deviceSourceEngine->removeSink(sink); } else if (m_deviceSinkEngine) { m_deviceSinkEngine->removeSpectrumSink(sink); - } // TODO: MIMO + } else if (m_deviceMIMOEngine) { + m_deviceMIMOEngine->removeAncillarySink(sink, index); + } } void DeviceAPI::setSpectrumSinkInput(bool sourceElseSink, unsigned int index) diff --git a/sdrbase/device/deviceapi.h b/sdrbase/device/deviceapi.h index 3aa63a0c1..ebb4ada00 100644 --- a/sdrbase/device/deviceapi.h +++ b/sdrbase/device/deviceapi.h @@ -72,8 +72,8 @@ public: 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) - void removeAncillarySink(BasebandSampleSink* sink); //!< Removes it + void addAncillarySink(BasebandSampleSink* sink, unsigned int index = 0); //!< Adds a sink to receive full baseband and that is not a channel (e.g. spectrum) + void removeAncillarySink(BasebandSampleSink* sink, unsigned int index = 0); //!< Removes it void setSpectrumSinkInput(bool sourceElseSink = true, unsigned int index = 0); //!< Used in the MIMO case to select which stream is used as input to main spectrum void addChannelSink(ThreadedBasebandSampleSink* sink, int streamIndex = 0); //!< Add a channel sink (Rx) diff --git a/sdrbase/dsp/filerecord.cpp b/sdrbase/dsp/filerecord.cpp index 6b0459b6c..3d7543512 100644 --- a/sdrbase/dsp/filerecord.cpp +++ b/sdrbase/dsp/filerecord.cpp @@ -64,9 +64,13 @@ void FileRecord::setFileName(const QString& filename) } } -void FileRecord::genUniqueFileName(uint deviceUID) +void FileRecord::genUniqueFileName(uint deviceUID, int istream) { - setFileName(QString("rec%1_%2.sdriq").arg(deviceUID).arg(QDateTime::currentDateTimeUtc().toString("yyyy-MM-ddTHH_mm_ss_zzz"))); + if (istream < 0) { + setFileName(QString("rec%1_%2.sdriq").arg(deviceUID).arg(QDateTime::currentDateTimeUtc().toString("yyyy-MM-ddTHH_mm_ss_zzz"))); + } else { + setFileName(QString("rec%1_%2_%3.sdriq").arg(deviceUID).arg(istream).arg(QDateTime::currentDateTimeUtc().toString("yyyy-MM-ddTHH_mm_ss_zzz"))); + } } void FileRecord::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly) diff --git a/sdrbase/dsp/filerecord.h b/sdrbase/dsp/filerecord.h index 1463edcf6..d0a855c0e 100644 --- a/sdrbase/dsp/filerecord.h +++ b/sdrbase/dsp/filerecord.h @@ -50,7 +50,7 @@ public: quint64 getByteCount() const { return m_byteCount; } void setFileName(const QString& filename); - void genUniqueFileName(uint deviceUID); + void genUniqueFileName(uint deviceUID, int istream = -1); virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly); virtual void start(); @@ -58,6 +58,7 @@ public: virtual bool handleMessage(const Message& message); void startRecording(); void stopRecording(); + bool isRecording() const { return m_recordOn; } static bool readHeader(std::ifstream& samplefile, Header& header); //!< returns true if CRC checksum is correct else false static void writeHeader(std::ofstream& samplefile, Header& header);