mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-09-28 15:56:33 -04:00
MIMO: test MI source: implemented file record
This commit is contained in:
parent
f9a8523714
commit
bb8366bfde
@ -49,11 +49,9 @@ TestMI::TestMI(DeviceAPI *deviceAPI) :
|
|||||||
m_running(false),
|
m_running(false),
|
||||||
m_masterTimer(deviceAPI->getMasterTimer())
|
m_masterTimer(deviceAPI->getMasterTimer())
|
||||||
{
|
{
|
||||||
m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID()));
|
|
||||||
m_deviceAPI->setNbSourceStreams(2);
|
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->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_sampleSinkFifos.push_back(SampleSinkFifo(96000 * 4));
|
m_sampleSinkFifos.push_back(SampleSinkFifo(96000 * 4));
|
||||||
m_networkManager = new QNetworkAccessManager();
|
m_networkManager = new QNetworkAccessManager();
|
||||||
@ -69,10 +67,17 @@ TestMI::~TestMI()
|
|||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_deviceAPI->removeAncillarySink(m_fileSink);
|
std::vector<FileRecord*>::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
|
||||||
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()
|
void TestMI::destroy()
|
||||||
@ -82,6 +87,11 @@ void TestMI::destroy()
|
|||||||
|
|
||||||
void TestMI::init()
|
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);
|
applySettings(m_settings, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,20 +226,21 @@ bool TestMI::handleMessage(const Message& message)
|
|||||||
{
|
{
|
||||||
MsgFileRecord& conf = (MsgFileRecord&) message;
|
MsgFileRecord& conf = (MsgFileRecord&) message;
|
||||||
qDebug() << "TestMI::handleMessage: MsgFileRecord: " << conf.getStartStop();
|
qDebug() << "TestMI::handleMessage: MsgFileRecord: " << conf.getStartStop();
|
||||||
|
int istream = conf.getStreamIndex();
|
||||||
|
|
||||||
if (conf.getStartStop())
|
if (conf.getStartStop())
|
||||||
{
|
{
|
||||||
if (m_settings.m_fileRecordName.size() != 0) {
|
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 {
|
} else {
|
||||||
m_fileSink->genUniqueFileName(m_deviceAPI->getDeviceUID());
|
m_fileSinks[istream]->genUniqueFileName(m_deviceAPI->getDeviceUID(), istream);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_fileSink->startRecording();
|
m_fileSinks[istream]->startRecording();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_fileSink->stopRecording();
|
m_fileSinks[istream]->stopRecording();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -421,7 +432,7 @@ bool TestMI::applySettings(const TestMISettings& settings, bool force)
|
|||||||
{
|
{
|
||||||
int sampleRate = settings.m_streams[istream].m_sampleRate/(1<<settings.m_streams[istream].m_log2Decim);
|
int sampleRate = settings.m_streams[istream].m_sampleRate/(1<<settings.m_streams[istream].m_log2Decim);
|
||||||
DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, settings.m_streams[istream].m_centerFrequency);
|
DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, settings.m_streams[istream].m_centerFrequency);
|
||||||
m_fileSink->handleMessage(*notif); // forward to file sink
|
m_fileSinks[istream]->handleMessage(*notif); // forward to file sink
|
||||||
DSPDeviceMIMOEngine::SignalNotification *engineNotif = new DSPDeviceMIMOEngine::SignalNotification(
|
DSPDeviceMIMOEngine::SignalNotification *engineNotif = new DSPDeviceMIMOEngine::SignalNotification(
|
||||||
sampleRate, settings.m_streams[istream].m_centerFrequency, true, 0);
|
sampleRate, settings.m_streams[istream].m_centerFrequency, true, 0);
|
||||||
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(engineNotif);
|
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(engineNotif);
|
||||||
@ -820,3 +831,12 @@ void TestMI::networkManagerFinished(QNetworkReply *reply)
|
|||||||
answer.chop(1); // remove last \n
|
answer.chop(1); // remove last \n
|
||||||
qDebug("TestMI::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -63,17 +63,20 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
bool getStartStop() const { return m_startStop; }
|
bool getStartStop() const { return m_startStop; }
|
||||||
|
int getStreamIndex() const { return m_streamIndex; }
|
||||||
|
|
||||||
static MsgFileRecord* create(bool startStop) {
|
static MsgFileRecord* create(bool startStop, int streamIndex) {
|
||||||
return new MsgFileRecord(startStop);
|
return new MsgFileRecord(startStop, streamIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool m_startStop;
|
bool m_startStop;
|
||||||
|
int m_streamIndex;
|
||||||
|
|
||||||
MsgFileRecord(bool startStop) :
|
MsgFileRecord(bool startStop, int streamIndex) :
|
||||||
Message(),
|
Message(),
|
||||||
m_startStop(startStop)
|
m_startStop(startStop),
|
||||||
|
m_streamIndex(streamIndex)
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -141,6 +144,8 @@ public:
|
|||||||
SWGSDRangel::SWGDeviceState& response,
|
SWGSDRangel::SWGDeviceState& response,
|
||||||
QString& errorMessage);
|
QString& errorMessage);
|
||||||
|
|
||||||
|
bool isRecording(unsigned int istream) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct DeviceSettingsKeys
|
struct DeviceSettingsKeys
|
||||||
{
|
{
|
||||||
@ -149,7 +154,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
DeviceAPI *m_deviceAPI;
|
DeviceAPI *m_deviceAPI;
|
||||||
FileRecord *m_fileSink; //!< File sink to record device I/Q output
|
std::vector<FileRecord *> m_fileSinks; //!< File sinks to record device I/Q output
|
||||||
QMutex m_mutex;
|
QMutex m_mutex;
|
||||||
TestMISettings m_settings;
|
TestMISettings m_settings;
|
||||||
std::vector<TestMIThread*> m_testSourceThreads;
|
std::vector<TestMIThread*> m_testSourceThreads;
|
||||||
|
@ -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 //
|
// 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 //
|
// 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)
|
void TestMIGui::on_streamIndex_currentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
m_streamIndex = index;
|
m_streamIndex = index;
|
||||||
|
updateFileRecordStatus();
|
||||||
displaySettings();
|
displaySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,7 +297,7 @@ void TestMIGui::on_record_toggled(bool checked)
|
|||||||
ui->record->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
|
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);
|
m_sampleMIMO->getInputMessageQueue()->push(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,6 +377,15 @@ void TestMIGui::updateFrequencyShiftLimit()
|
|||||||
ui->frequencyShift->setValueRange(false, 7, -sampleRate, sampleRate);
|
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()
|
void TestMIGui::displaySettings()
|
||||||
{
|
{
|
||||||
blockApplySettings(true);
|
blockApplySettings(true);
|
||||||
|
@ -77,6 +77,7 @@ private:
|
|||||||
void updateAmpCoarseLimit();
|
void updateAmpCoarseLimit();
|
||||||
void updateAmpFineLimit();
|
void updateAmpFineLimit();
|
||||||
void updateFrequencyShiftLimit();
|
void updateFrequencyShiftLimit();
|
||||||
|
void updateFileRecordStatus();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleInputMessages();
|
void handleInputMessages();
|
||||||
|
@ -86,22 +86,26 @@ void DeviceAPI::removeLastSinkStream()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceAPI::addAncillarySink(BasebandSampleSink *sink)
|
void DeviceAPI::addAncillarySink(BasebandSampleSink *sink, unsigned int index)
|
||||||
{
|
{
|
||||||
if (m_deviceSourceEngine) {
|
if (m_deviceSourceEngine) {
|
||||||
m_deviceSourceEngine->addSink(sink);
|
m_deviceSourceEngine->addSink(sink);
|
||||||
} else if (m_deviceSinkEngine) {
|
} else if (m_deviceSinkEngine) {
|
||||||
m_deviceSinkEngine->addSpectrumSink(sink);
|
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) {
|
if (m_deviceSourceEngine) {
|
||||||
m_deviceSourceEngine->removeSink(sink);
|
m_deviceSourceEngine->removeSink(sink);
|
||||||
} else if (m_deviceSinkEngine) {
|
} else if (m_deviceSinkEngine) {
|
||||||
m_deviceSinkEngine->removeSpectrumSink(sink);
|
m_deviceSinkEngine->removeSpectrumSink(sink);
|
||||||
} // TODO: MIMO
|
} else if (m_deviceMIMOEngine) {
|
||||||
|
m_deviceMIMOEngine->removeAncillarySink(sink, index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceAPI::setSpectrumSinkInput(bool sourceElseSink, unsigned int index)
|
void DeviceAPI::setSpectrumSinkInput(bool sourceElseSink, unsigned int index)
|
||||||
|
@ -72,8 +72,8 @@ public:
|
|||||||
void addSinkStream(bool connect);
|
void addSinkStream(bool connect);
|
||||||
void removeLastSinkStream();
|
void removeLastSinkStream();
|
||||||
|
|
||||||
void addAncillarySink(BasebandSampleSink* sink); //!< Adds a sink to receive full baseband and that is not a channel (e.g. spectrum)
|
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); //!< Removes it
|
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 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)
|
void addChannelSink(ThreadedBasebandSampleSink* sink, int streamIndex = 0); //!< Add a channel sink (Rx)
|
||||||
|
@ -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)
|
void FileRecord::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly)
|
||||||
|
@ -50,7 +50,7 @@ public:
|
|||||||
quint64 getByteCount() const { return m_byteCount; }
|
quint64 getByteCount() const { return m_byteCount; }
|
||||||
|
|
||||||
void setFileName(const QString& filename);
|
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 feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
|
||||||
virtual void start();
|
virtual void start();
|
||||||
@ -58,6 +58,7 @@ public:
|
|||||||
virtual bool handleMessage(const Message& message);
|
virtual bool handleMessage(const Message& message);
|
||||||
void startRecording();
|
void startRecording();
|
||||||
void stopRecording();
|
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 bool readHeader(std::ifstream& samplefile, Header& header); //!< returns true if CRC checksum is correct else false
|
||||||
static void writeHeader(std::ofstream& samplefile, Header& header);
|
static void writeHeader(std::ofstream& samplefile, Header& header);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user