diff --git a/plugins/channelmimo/beamsteeringcwmod/CMakeLists.txt b/plugins/channelmimo/beamsteeringcwmod/CMakeLists.txt index 88b357292..1d2688a84 100644 --- a/plugins/channelmimo/beamsteeringcwmod/CMakeLists.txt +++ b/plugins/channelmimo/beamsteeringcwmod/CMakeLists.txt @@ -4,7 +4,7 @@ set(beamsteeringcwmod_SOURCES beamsteeringcwmodplugin.cpp beamsteeringcwmod.cpp beamsteeringcwmodsettings.cpp - beamsteeringcwmodsource.cpp + beamsteeringcwmodbaseband.cpp beamsteeringcwmodstreamsource.cpp beamsteeringcwmodwebapiadapter.cpp ) @@ -13,7 +13,7 @@ set(beamsteeringcwmod_HEADERS beamsteeringcwmodplugin.h beamsteeringcwmod.h beamsteeringcwmodsettings.h - beamsteeringcwmodsource.h + beamsteeringcwmodbaseband.h beamsteeringcwmodstreamsource.h beamsteeringcwmodwebapiadapter.h ) diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmod.cpp b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmod.cpp index 896f9ff77..f0412bd6f 100644 --- a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmod.cpp +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmod.cpp @@ -22,14 +22,12 @@ #include #include "device/deviceapi.h" -#include "dsp/upchannelizer.h" -#include "dsp/threadedbasebandsamplesource.h" #include "dsp/hbfilterchainconverter.h" #include "dsp/dspcommands.h" #include "SWGChannelSettings.h" -#include "beamsteeringcwmodsource.h" +#include "beamsteeringcwmodbaseband.h" #include "beamsteeringcwmod.h" MESSAGE_CLASS_DEFINITION(BeamSteeringCWMod::MsgConfigureBeamSteeringCWMod, Message) @@ -43,13 +41,13 @@ BeamSteeringCWMod::BeamSteeringCWMod(DeviceAPI *deviceAPI) : m_deviceAPI(deviceAPI), m_guiMessageQueue(nullptr), m_frequencyOffset(0), - m_deviceSampleRate(48000) + m_basebandSampleRate(48000) { setObjectName(m_channelId); m_thread = new QThread(this); - m_source = new BeamSteeringCWModSource(); - m_source->moveToThread(m_thread); + m_basebandSource = new BeamSteeringCWModBaseband(); + m_basebandSource->moveToThread(m_thread); m_deviceAPI->addMIMOChannel(this); m_deviceAPI->addMIMOChannelAPI(this); connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); @@ -65,25 +63,27 @@ BeamSteeringCWMod::~BeamSteeringCWMod() m_deviceAPI->removeChannelSinkAPI(this); m_deviceAPI->removeMIMOChannel(this); - delete m_source; + delete m_basebandSource; delete m_thread; } void BeamSteeringCWMod::startSources() { - m_source->reset(); + qDebug("BeamSteeringCWMod::startSources"); + m_basebandSource->reset(); m_thread->start(); } void BeamSteeringCWMod::stopSources() { + qDebug("BeamSteeringCWMod::stopSources"); m_thread->exit(); m_thread->wait(); } -void BeamSteeringCWMod::pull(const SampleVector::iterator& begin, unsigned int nbSamples, unsigned int sourceIndex) +void BeamSteeringCWMod::pull(SampleVector::iterator& begin, unsigned int nbSamples, unsigned int sourceIndex) { - m_source->pull(begin, nbSamples, sourceIndex); + m_basebandSource->pull(begin, nbSamples, sourceIndex); } void BeamSteeringCWMod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, unsigned int sinkIndex) @@ -107,28 +107,8 @@ void BeamSteeringCWMod::applySettings(const BeamSteeringCWModSettings& settings, << "m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex << "m_title: " << settings.m_title; - if ((m_settings.m_log2Interp != settings.m_log2Interp) - || (m_settings.m_filterChainHash != settings.m_filterChainHash) || force) - { - BeamSteeringCWModSource::MsgConfigureChannelizer *msg = BeamSteeringCWModSource::MsgConfigureChannelizer::create( - settings.m_log2Interp, settings.m_filterChainHash); - m_source->getInputMessageQueue()->push(msg); - } - - if ((m_settings.m_steerDegrees != settings.m_steerDegrees) || force) { - m_source->setSteeringDegrees(settings.m_steerDegrees); - } - - if ((m_settings.m_channelOutput != settings.m_channelOutput) || force) - { - if (settings.m_channelOutput == 0) { // A and B - m_source->muteChannel(false, false); - } else if (settings.m_channelOutput == 1) { // A only - m_source->muteChannel(false, true); - } else if (settings.m_channelOutput == 2) { // B only - m_source->muteChannel(true, false); - } - } + BeamSteeringCWModBaseband::MsgConfigureBeamSteeringCWModBaseband *msg = BeamSteeringCWModBaseband::MsgConfigureBeamSteeringCWModBaseband::create(settings, force); + m_basebandSource->getInputMessageQueue()->push(msg); m_settings = settings; } @@ -160,28 +140,21 @@ bool BeamSteeringCWMod::handleMessage(const Message& cmd) DSPMIMOSignalNotification& notif = (DSPMIMOSignalNotification&) cmd; qDebug() << "BeamSteeringCWMod::handleMessage: DSPMIMOSignalNotification:" - << " outputSampleRate: " << notif.getSampleRate() + << " basebandSampleRate: " << notif.getSampleRate() << " centerFrequency: " << notif.getCenterFrequency() << " sourceElseSink: " << notif.getSourceOrSink() << " streamIndex: " << notif.getIndex(); if (!notif.getSourceOrSink()) // deals with sink messages only { - m_deviceSampleRate = notif.getSampleRate(); + m_basebandSampleRate = notif.getSampleRate(); calculateFrequencyOffset(); // This is when device sample rate changes // Notify source of input sample rate change - BeamSteeringCWModSource::MsgSignalNotification *sig = BeamSteeringCWModSource::MsgSignalNotification::create( - m_deviceSampleRate, notif.getCenterFrequency() - ); + BeamSteeringCWModBaseband::MsgSignalNotification *sig = BeamSteeringCWModBaseband::MsgSignalNotification::create( + m_basebandSampleRate); qDebug() << "BeamSteeringCWMod::handleMessage: DSPMIMOSignalNotification: push to source"; - m_source->getInputMessageQueue()->push(sig); - - // Redo the channelizer stuff with the new sample rate to re-synchronize everything - BeamSteeringCWModSource::MsgConfigureChannelizer *msg = BeamSteeringCWModSource::MsgConfigureChannelizer::create( - m_settings.m_log2Interp, - m_settings.m_filterChainHash); - m_source->getInputMessageQueue()->push(msg); + m_basebandSource->getInputMessageQueue()->push(sig); if (m_guiMessageQueue) { @@ -237,13 +210,7 @@ void BeamSteeringCWMod::validateFilterChainHash(BeamSteeringCWModSettings& setti void BeamSteeringCWMod::calculateFrequencyOffset() { double shiftFactor = HBFilterChainConverter::getShiftFactor(m_settings.m_log2Interp, m_settings.m_filterChainHash); - m_frequencyOffset = m_deviceSampleRate * shiftFactor; -} - -void BeamSteeringCWMod::applyChannelSettings(uint32_t log2Interp, uint32_t filterChainHash) -{ - BeamSteeringCWModSource::MsgConfigureChannelizer *msg = BeamSteeringCWModSource::MsgConfigureChannelizer::create(log2Interp, filterChainHash); - m_source->getInputMessageQueue()->push(msg); + m_frequencyOffset = m_basebandSampleRate * shiftFactor; } int BeamSteeringCWMod::webapiSettingsGet( @@ -379,13 +346,14 @@ void BeamSteeringCWMod::webapiReverseSendSettings(QList& channelSetting m_networkRequest.setUrl(QUrl(channelSettingsURL)); m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - QBuffer *buffer=new QBuffer(); + QBuffer *buffer = new QBuffer(); buffer->open((QBuffer::ReadWrite)); buffer->write(swgChannelSettings->asJson().toUtf8()); buffer->seek(0); // Always use PATCH to avoid passing reverse API settings - m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + QNetworkReply *reply = m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + buffer->setParent(reply); delete swgChannelSettings; } @@ -400,10 +368,13 @@ void BeamSteeringCWMod::networkManagerFinished(QNetworkReply *reply) << " error(" << (int) replyError << "): " << replyError << ": " << reply->errorString(); - return; + } + else + { + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("BeamSteeringCWMod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); } - QString answer = reply->readAll(); - answer.chop(1); // remove last \n - qDebug("BeamSteeringCWMod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); + reply->deleteLater(); } diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmod.h b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmod.h index bd2d79080..784d65fec 100644 --- a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmod.h +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmod.h @@ -30,7 +30,7 @@ class QThread; class DeviceAPI; -class BeamSteeringCWModSource; +class BeamSteeringCWModBaseband; class QNetworkReply; class QNetworkAccessManager; class BasebandSampleSink; @@ -94,13 +94,13 @@ public: virtual void startSources(); //!< thread start() virtual void stopSources(); //!< thread exit() and wait() virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, unsigned int sinkIndex); - virtual void pull(const SampleVector::iterator& begin, unsigned int nbSamples, unsigned int sourceIndex); + virtual void pull(SampleVector::iterator& begin, unsigned int nbSamples, unsigned int sourceIndex); virtual bool handleMessage(const Message& cmd); //!< Processing of a message. Returns true if message has actually been processed virtual void getIdentifier(QString& id) { id = objectName(); } virtual void getTitle(QString& title) { title = "BeamSteeringCWMod"; } virtual qint64 getCenterFrequency() const { return m_frequencyOffset; } - uint32_t getDeviceSampleRate() const { return m_deviceSampleRate; } + uint32_t getBasebandSampleRate() const { return m_basebandSampleRate; } virtual QByteArray serialize() const; virtual bool deserialize(const QByteArray& data); @@ -119,8 +119,6 @@ public: virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; } MessageQueue *getMessageQueueToGUI() { return m_guiMessageQueue; } - void applyChannelSettings(uint32_t log2Decim, uint32_t filterChainHash); - virtual int webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, QString& errorMessage); @@ -147,7 +145,7 @@ public: private: DeviceAPI *m_deviceAPI; QThread *m_thread; - BeamSteeringCWModSource* m_source; + BeamSteeringCWModBaseband* m_basebandSource; BasebandSampleSink* m_spectrumSink; BasebandSampleSink* m_scopeSink; BeamSteeringCWModSettings m_settings; @@ -158,7 +156,7 @@ private: QNetworkRequest m_networkRequest; int64_t m_frequencyOffset; - uint32_t m_deviceSampleRate; + uint32_t m_basebandSampleRate; int m_count0, m_count1; void applySettings(const BeamSteeringCWModSettings& settings, bool force = false); diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodbaseband.h b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodbaseband.h new file mode 100644 index 000000000..99c879e20 --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodbaseband.h @@ -0,0 +1,105 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_BEAMSTEERINGCWMODBASEBAND_H +#define INCLUDE_BEAMSTEERINGCWMODBASEBAND_H + +#include +#include + +#include "dsp/samplemofifo.h" +#include "util/message.h" +#include "util/messagequeue.h" +#include "beamsteeringcwmodstreamsource.h" +#include "beamsteeringcwmodsettings.h" + +class UpSampleChannelizer; + +class BeamSteeringCWModBaseband : public QObject +{ + Q_OBJECT +public: + class MsgConfigureBeamSteeringCWModBaseband : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const BeamSteeringCWModSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureBeamSteeringCWModBaseband* create(const BeamSteeringCWModSettings& settings, bool force) + { + return new MsgConfigureBeamSteeringCWModBaseband(settings, force); + } + + private: + BeamSteeringCWModSettings m_settings; + bool m_force; + + MsgConfigureBeamSteeringCWModBaseband(const BeamSteeringCWModSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + class MsgSignalNotification : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getBasebandSampleRate() const { return m_basebandSampleRate; } + + static MsgSignalNotification* create(int basebandSampleRate) { + return new MsgSignalNotification(basebandSampleRate); + } + private: + int m_basebandSampleRate; + + MsgSignalNotification(int basebandSampleRate) : + Message(), + m_basebandSampleRate(basebandSampleRate) + { } + }; + + BeamSteeringCWModBaseband(); + ~BeamSteeringCWModBaseband(); + void reset(); + + MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication + + void pull(SampleVector::iterator& begin, unsigned int nbSamples, unsigned int streamIndex); + +private: + void processFifo(std::vector& data, unsigned int ibegin, unsigned int iend); + bool handleMessage(const Message& cmd); + void applySettings(const BeamSteeringCWModSettings& settings, bool force = false); + + BeamSteeringCWModSettings m_settings; + SampleMOFifo m_sampleMOFifo; + std::vector m_vbegin; + int m_sizes[2]; + UpSampleChannelizer *m_channelizers[2]; + BeamSteeringCWModStreamSource m_streamSources[2]; + MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication + QMutex m_mutex; + unsigned int m_lastStream; + +private slots: + void handleInputMessages(); + void handleData(); //!< Handle data when samples have to be processed +}; + + +#endif // INCLUDE_BEAMSTEERINGCWMODBASEBAND_H \ No newline at end of file diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.cpp b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.cpp index af9b7cafd..44c198fec 100644 --- a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.cpp +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.cpp @@ -85,7 +85,7 @@ bool BeamSteeringCWModGUI::handleMessage(const Message& message) if (BeamSteeringCWMod::MsgBasebandNotification::match(message)) { BeamSteeringCWMod::MsgBasebandNotification& notif = (BeamSteeringCWMod::MsgBasebandNotification&) message; - m_sampleRate = notif.getSampleRate(); + m_basebandSampleRate = notif.getSampleRate(); m_centerFrequency = notif.getCenterFrequency(); displayRateAndShift(); return true; @@ -110,7 +110,7 @@ BeamSteeringCWModGUI::BeamSteeringCWModGUI(PluginAPI* pluginAPI, DeviceUISet *de ui(new Ui::BeamSteeringCWModGUI), m_pluginAPI(pluginAPI), m_deviceUISet(deviceUISet), - m_sampleRate(48000), + m_basebandSampleRate(48000), m_centerFrequency(435000000), m_tickCount(0) { @@ -123,7 +123,7 @@ BeamSteeringCWModGUI::BeamSteeringCWModGUI(PluginAPI* pluginAPI, DeviceUISet *de m_bsCWSource = (BeamSteeringCWMod*) mimoChannel; m_bsCWSource->setMessageQueueToGUI(getInputMessageQueue()); - m_sampleRate = m_bsCWSource->getDeviceSampleRate(); + m_basebandSampleRate = m_bsCWSource->getBasebandSampleRate(); connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); @@ -178,7 +178,7 @@ void BeamSteeringCWModGUI::displaySettings() m_channelMarker.blockSignals(true); m_channelMarker.setCenterFrequency(0); m_channelMarker.setTitle(m_settings.m_title); - m_channelMarker.setBandwidth(m_sampleRate); + m_channelMarker.setBandwidth(m_basebandSampleRate); m_channelMarker.setMovable(false); // do not let user move the center arbitrarily m_channelMarker.blockSignals(false); m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only @@ -195,8 +195,8 @@ void BeamSteeringCWModGUI::displaySettings() void BeamSteeringCWModGUI::displayRateAndShift() { - int shift = m_shiftFrequencyFactor * m_sampleRate; - double channelSampleRate = ((double) m_sampleRate) / (1<offsetFrequencyText->setText(tr("%1 Hz").arg(loc.toString(shift))); ui->channelRateText->setText(tr("%1k").arg(QString::number(channelSampleRate / 1000.0, 'g', 5))); diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.h b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.h index ccb635035..eef3b71c4 100644 --- a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.h +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.h @@ -60,7 +60,7 @@ private: DeviceUISet* m_deviceUISet; ChannelMarker m_channelMarker; BeamSteeringCWModSettings m_settings; - int m_sampleRate; + int m_basebandSampleRate; qint64 m_centerFrequency; double m_shiftFrequencyFactor; //!< Channel frequency shift factor bool m_doApplySettings; diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsource.cpp b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsource.cpp deleted file mode 100644 index e9baa602b..000000000 --- a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsource.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// 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 // -// the Free Software Foundation as version 3 of the License, or // -// (at your option) any later version. // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License V3 for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program. If not, see . // -/////////////////////////////////////////////////////////////////////////////////// - -#include -#include - -#include "dsp/upsamplechannelizer.h" -#include "dsp/dspcommands.h" - -#include "beamsteeringcwmodsource.h" - - -MESSAGE_CLASS_DEFINITION(BeamSteeringCWModSource::MsgConfigureChannelizer, Message) -MESSAGE_CLASS_DEFINITION(BeamSteeringCWModSource::MsgSignalNotification, Message) -MESSAGE_CLASS_DEFINITION(BeamSteeringCWModSource::MsgConfigureSteeringAngle, Message) -MESSAGE_CLASS_DEFINITION(BeamSteeringCWModSource::MsgConfigureChannelMute, Message) - -BeamSteeringCWModSource::BeamSteeringCWModSource() : - m_steeringDegrees(90), - m_mutex(QMutex::Recursive) -{ - m_sampleMOFifo.init(2, 1200*64); - m_vbegin.resize(2); - - for (int i = 0; i < 2; i++) - { - m_streamSources[i].setStreamIndex(i); - m_channelizers[i] = new UpSampleChannelizer(&m_streamSources[i]); - m_sizes[i] = 0; - } - - QObject::connect( - &m_sampleMOFifo, - &SampleMOFifo::dataSyncRead, - this, - &BeamSteeringCWModSource::handleData, - Qt::QueuedConnection - ); - - connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); - m_lastStream = 0; -} - -BeamSteeringCWModSource::~BeamSteeringCWModSource() -{ - for (int i = 0; i < 2; i++) { - delete m_channelizers[i]; - } -} - -void BeamSteeringCWModSource::reset() -{ - QMutexLocker mutexLocker(&m_mutex); - m_sampleMOFifo.reset(); - - for (int i = 0; i < 2; i++) { - m_streamSources[i].reset(); - } -} - -void BeamSteeringCWModSource::setSteeringDegrees(int steeringDegrees) -{ - m_steeringDegrees = steeringDegrees < -180 ? -180 : steeringDegrees > 180 ? 180 : steeringDegrees; - MsgConfigureSteeringAngle *msg = MsgConfigureSteeringAngle::create((m_steeringDegrees/180.0f)*M_PI); - m_inputMessageQueue.push(msg); -} - -void BeamSteeringCWModSource::muteChannel(bool mute0, bool mute1) -{ - MsgConfigureChannelMute *msg = MsgConfigureChannelMute::create(mute0, mute1); - m_inputMessageQueue.push(msg); -} - -void BeamSteeringCWModSource::pull(const SampleVector::iterator& begin, unsigned int nbSamples, unsigned int streamIndex) -{ - if (streamIndex > 1) { - return; - } - - if (streamIndex == m_lastStream) { - qWarning("BeamSteeringCWModSource::pull: twice same stream in a row: %u", streamIndex); - } - - m_lastStream = streamIndex; - m_vbegin[streamIndex] = begin; - m_sizes[streamIndex] = nbSamples; - - if (streamIndex == 1) - { - unsigned int part1Begin, part1End, part2Begin, part2End, size; - - if (m_sizes[0] != m_sizes[1]) - { - qWarning("BeamSteeringCWModSource::pull: unequal sizes: [0]: %d [1]: %d", m_sizes[0], m_sizes[1]); - size = std::min(m_sizes[0], m_sizes[1]); - } - else - { - size = m_sizes[0]; - } - - std::vector& data = m_sampleMOFifo.getData(); - m_sampleMOFifo.readSync(size, part1Begin, part1End, part2Begin, part2End); - - if (part1Begin != part1End) - { - std::copy(data[0].begin() + part1Begin, data[0].begin() + part1End, m_vbegin[0]); - std::copy(data[1].begin() + part1Begin, data[1].begin() + part1End, m_vbegin[1]); - } - - if (part2Begin != part2End) - { - std::copy(data[0].begin() + part2Begin, data[0].begin() + part2End, m_vbegin[0]); - std::copy(data[1].begin() + part2Begin, data[1].begin() + part2End, m_vbegin[1]); - } - } -} - -void BeamSteeringCWModSource::handleData() -{ - QMutexLocker mutexLocker(&m_mutex); - - std::vector& data = m_sampleMOFifo.getData(); - - unsigned int ipart1begin; - unsigned int ipart1end; - unsigned int ipart2begin; - unsigned int ipart2end; - unsigned int remainder = m_sampleMOFifo.remainderSync(); - - while ((remainder > 0) && (m_inputMessageQueue.size() == 0)) - { - m_sampleMOFifo.writeSync(ipart1begin, ipart1end, ipart2begin, ipart2end); - - if (ipart1begin != ipart1end) { // first part of FIFO data - processFifo(data, ipart1begin, ipart1end); - } - - if (ipart2begin != ipart2end) { // second part of FIFO data (used when block wraps around) - processFifo(data, ipart2begin, ipart2end); - } - - remainder = m_sampleMOFifo.remainderSync(); - } -} - -void BeamSteeringCWModSource::processFifo(std::vector& data, unsigned int ibegin, unsigned int iend) -{ - for (unsigned int stream = 0; stream < 2; stream++) { - m_channelizers[stream]->pull(data[stream].begin() + ibegin, iend - ibegin); - } -} - -void BeamSteeringCWModSource::handleInputMessages() -{ - Message* message; - - while ((message = m_inputMessageQueue.pop()) != nullptr) - { - if (handleMessage(*message)) { - delete message; - } - } -} - -bool BeamSteeringCWModSource::handleMessage(const Message& cmd) -{ - if (MsgConfigureChannelizer::match(cmd)) - { - QMutexLocker mutexLocker(&m_mutex); - MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd; - int log2Interp = cfg.getLog2Interp(); - int filterChainHash = cfg.getFilterChainHash(); - - qDebug() << "BeamSteeringCWModSource::handleMessage: MsgConfigureChannelizer:" - << " log2Interp: " << log2Interp - << " filterChainHash: " << filterChainHash; - - for (int i = 0; i < 2; i++) - { - m_channelizers[i]->setInterpolation(log2Interp, filterChainHash); - m_streamSources[i].reset(); - } - - return true; - } - else if (MsgSignalNotification::match(cmd)) - { - QMutexLocker mutexLocker(&m_mutex); - MsgSignalNotification& cfg = (MsgSignalNotification&) cmd; - int outputSampleRate = cfg.getOutputSampleRate(); - - qDebug() << "BeamSteeringCWModSource::handleMessage: MsgSignalNotification:" - << " outputSampleRate: " << outputSampleRate - << " centerFrequency: " << cfg.getCenterFrequency(); - - m_sampleMOFifo.resize((outputSampleRate/40)*64); - - for (int i = 0; i < 2; i++) - { - m_channelizers[i]->setOutputSampleRate(outputSampleRate); - m_streamSources[i].reset(); - } - - return true; - } - else if (MsgConfigureSteeringAngle::match(cmd)) - { - QMutexLocker mutexLocker(&m_mutex); - MsgConfigureSteeringAngle& cfg = (MsgConfigureSteeringAngle&) cmd; - float steeringAngle = cfg.getSteeringAngle(); - steeringAngle = steeringAngle < -M_PI ? -M_PI : steeringAngle > M_PI ? M_PI : steeringAngle; - - qDebug() << "BeamSteeringCWModSource::handleMessage: MsgConfigureSteeringAngle:" - << " steeringAngle: " << steeringAngle; - - m_streamSources[1].setPhase(M_PI*cos(steeringAngle)); - - return true; - } - else if (MsgConfigureChannelMute::match(cmd)) - { - QMutexLocker mutexLocker(&m_mutex); - MsgConfigureChannelMute& cfg = (MsgConfigureChannelMute&) cmd; - m_streamSources[0].muteChannel(cfg.getMute0()); - m_streamSources[1].muteChannel(cfg.getMute1()); - - qDebug() << "BeamSteeringCWModSource::handleMessage: MsgConfigureChannelMute:" - << " mute0: " << cfg.getMute0() - << " mute1: " << cfg.getMute1(); - - return true; - } - else - { - qDebug("BeamSteeringCWModSource::handleMessage: unhandled: %s", cmd.getIdentifier()); - return false; - } -} \ No newline at end of file diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsource.h b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsource.h deleted file mode 100644 index e9aaff33a..000000000 --- a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsource.h +++ /dev/null @@ -1,147 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// 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 // -// the Free Software Foundation as version 3 of the License, or // -// (at your option) any later version. // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License V3 for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program. If not, see . // -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef INCLUDE_BEAMSTEERINGCWMODSOURCE_H -#define INCLUDE_BEAMSTEERINGCWMODSOURCE_H - -#include -#include - -#include "dsp/samplemofifo.h" -#include "util/message.h" -#include "util/messagequeue.h" -#include "beamsteeringcwmodstreamsource.h" - -class UpSampleChannelizer; - -class BeamSteeringCWModSource : public QObject -{ - Q_OBJECT -public: - class MsgConfigureChannelizer : public Message { - MESSAGE_CLASS_DECLARATION - - public: - int getLog2Interp() const { return m_log2Interp; } - int getFilterChainHash() const { return m_filterChainHash; } - - static MsgConfigureChannelizer* create(unsigned int log2Interp, unsigned int filterChainHash) { - return new MsgConfigureChannelizer(log2Interp, filterChainHash); - } - - private: - unsigned int m_log2Interp; - unsigned int m_filterChainHash; - - MsgConfigureChannelizer(unsigned int log2Interp, unsigned int filterChainHash) : - Message(), - m_log2Interp(log2Interp), - m_filterChainHash(filterChainHash) - { } - }; - - class MsgSignalNotification : public Message { - MESSAGE_CLASS_DECLARATION - - public: - int getOutputSampleRate() const { return m_outputSampleRate; } - qint64 getCenterFrequency() const { return m_centerFrequency; } - - static MsgSignalNotification* create(int outputSampleRate, qint64 centerFrequency) { - return new MsgSignalNotification(outputSampleRate, centerFrequency); - } - private: - int m_outputSampleRate; - qint64 m_centerFrequency; - - MsgSignalNotification(int outputSampleRate, qint64 centerFrequency) : - Message(), - m_outputSampleRate(outputSampleRate), - m_centerFrequency(centerFrequency) - { } - }; - - class MsgConfigureSteeringAngle : public Message { - MESSAGE_CLASS_DECLARATION - - public: - float getSteeringAngle() const { return m_steeringAngle; } - - static MsgConfigureSteeringAngle* create(float steeringAngle) { - return new MsgConfigureSteeringAngle(steeringAngle); - } - private: - float m_steeringAngle; - - MsgConfigureSteeringAngle(float steeringAngle) : - Message(), - m_steeringAngle(steeringAngle) - {} - }; - - class MsgConfigureChannelMute : public Message { - MESSAGE_CLASS_DECLARATION - - public: - bool getMute0() const { return m_mute0; } - bool getMute1() const { return m_mute1; } - - static MsgConfigureChannelMute* create(bool mute0, bool mute1) { - return new MsgConfigureChannelMute(mute0, mute1); - } - private: - bool m_mute0; - bool m_mute1; - - MsgConfigureChannelMute(bool mute0, bool mute1) : - Message(), - m_mute0(mute0), - m_mute1(mute1) - {} - }; - - BeamSteeringCWModSource(); - ~BeamSteeringCWModSource(); - void reset(); - - MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication - - void setSteeringDegrees(int steeringDegrees); - void muteChannel(bool mute0, bool mute1); - void pull(const SampleVector::iterator& begin, unsigned int nbSamples, unsigned int streamIndex); - -private: - void processFifo(std::vector& data, unsigned int ibegin, unsigned int iend); - bool handleMessage(const Message& cmd); - - int m_steeringDegrees; - SampleMOFifo m_sampleMOFifo; - std::vector m_vbegin; - int m_sizes[2]; - UpSampleChannelizer *m_channelizers[2]; - BeamSteeringCWModStreamSource m_streamSources[2]; - MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication - QMutex m_mutex; - unsigned int m_lastStream; - -private slots: - void handleInputMessages(); - void handleData(); //!< Handle data when samples have to be processed -}; - - -#endif // INCLUDE_BEAMSTEERINGCWMODSOURCE_H \ No newline at end of file diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.cpp b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.cpp index b4f79658b..b3c4604b7 100644 --- a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.cpp +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.cpp @@ -52,7 +52,7 @@ void BeamSteeringCWModStreamSource::setPhase(float phase) void BeamSteeringCWModStreamSource::pull(SampleVector::iterator begin, unsigned int nbSamples) { - std::fill(begin, begin + nbSamples, Sample{(int) m_real, m_imag}); + std::fill(begin, begin + nbSamples, Sample{m_real, m_imag}); } void BeamSteeringCWModStreamSource::pullOne(Sample& sample) diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.h b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.h index fbc1579c6..d189a4064 100644 --- a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.h +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.h @@ -28,6 +28,7 @@ public: virtual void pull(SampleVector::iterator begin, unsigned int nbSamples); virtual void pullOne(Sample& sample); + virtual void prefetch(unsigned int nbSamples) {} // prefetching of samples is not implemented void reset(); void setPhase(float phase); @@ -43,6 +44,4 @@ private: FixReal m_imag; }; - - #endif // INCLUDE_BEAMSTEERINGCWMODSTREAMSOURCE_H diff --git a/plugins/channelmimo/interferometer/interferometer.cpp b/plugins/channelmimo/interferometer/interferometer.cpp index eb86f3a0a..0beade475 100644 --- a/plugins/channelmimo/interferometer/interferometer.cpp +++ b/plugins/channelmimo/interferometer/interferometer.cpp @@ -101,7 +101,7 @@ void Interferometer::feed(const SampleVector::const_iterator& begin, const Sampl m_sink->feed(begin, end, sinkIndex); } -void Interferometer::pull(const SampleVector::iterator& begin, unsigned int nbSamples, unsigned int sourceIndex) +void Interferometer::pull(SampleVector::iterator& begin, unsigned int nbSamples, unsigned int sourceIndex) { (void) begin; (void) nbSamples; @@ -383,13 +383,14 @@ void Interferometer::webapiReverseSendSettings(QList& channelSettingsKe m_networkRequest.setUrl(QUrl(channelSettingsURL)); m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - QBuffer *buffer=new QBuffer(); + QBuffer *buffer = new QBuffer(); buffer->open((QBuffer::ReadWrite)); buffer->write(swgChannelSettings->asJson().toUtf8()); buffer->seek(0); // Always use PATCH to avoid passing reverse API settings - m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + QNetworkReply *reply = m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + reply->setParent(buffer); delete swgChannelSettings; } @@ -404,10 +405,13 @@ void Interferometer::networkManagerFinished(QNetworkReply *reply) << " error(" << (int) replyError << "): " << replyError << ": " << reply->errorString(); - return; + } + else + { + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("Interferometer::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); } - QString answer = reply->readAll(); - answer.chop(1); // remove last \n - qDebug("Interferometer::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); + reply->deleteLater(); } diff --git a/plugins/channelmimo/interferometer/interferometer.h b/plugins/channelmimo/interferometer/interferometer.h index 1bc95db8d..6aa439c34 100644 --- a/plugins/channelmimo/interferometer/interferometer.h +++ b/plugins/channelmimo/interferometer/interferometer.h @@ -94,7 +94,7 @@ public: virtual void startSources() {} virtual void stopSources() {} virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, unsigned int sinkIndex); - virtual void pull(const SampleVector::iterator& begin, unsigned int nbSamples, unsigned int sourceIndex); + virtual void pull(SampleVector::iterator& begin, unsigned int nbSamples, unsigned int sourceIndex); virtual bool handleMessage(const Message& cmd); //!< Processing of a message. Returns true if message has actually been processed virtual void getIdentifier(QString& id) { id = objectName(); } diff --git a/plugins/samplemimo/bladerf2mimo/bladerf2mimo.cpp b/plugins/samplemimo/bladerf2mimo/bladerf2mimo.cpp index e9db33b75..6523b1974 100644 --- a/plugins/samplemimo/bladerf2mimo/bladerf2mimo.cpp +++ b/plugins/samplemimo/bladerf2mimo/bladerf2mimo.cpp @@ -1297,13 +1297,14 @@ void BladeRF2MIMO::webapiReverseSendSettings(QList& deviceSettingsKeys, m_networkRequest.setUrl(QUrl(deviceSettingsURL)); m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - QBuffer *buffer=new QBuffer(); + QBuffer *buffer = new QBuffer(); buffer->open((QBuffer::ReadWrite)); buffer->write(swgDeviceSettings->asJson().toUtf8()); buffer->seek(0); // Always use PATCH to avoid passing reverse API settings - m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + QNetworkReply *reply = m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + buffer->setParent(reply); delete swgDeviceSettings; } @@ -1322,17 +1323,19 @@ void BladeRF2MIMO::webapiReverseSendStartStop(bool start) m_networkRequest.setUrl(QUrl(deviceSettingsURL)); m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - QBuffer *buffer=new QBuffer(); + QBuffer *buffer = new QBuffer(); buffer->open((QBuffer::ReadWrite)); buffer->write(swgDeviceSettings->asJson().toUtf8()); buffer->seek(0); + QNetworkReply *reply; if (start) { - m_networkManager->sendCustomRequest(m_networkRequest, "POST", buffer); + reply = m_networkManager->sendCustomRequest(m_networkRequest, "POST", buffer); } else { - m_networkManager->sendCustomRequest(m_networkRequest, "DELETE", buffer); + reply = m_networkManager->sendCustomRequest(m_networkRequest, "DELETE", buffer); } + buffer->setParent(reply); delete swgDeviceSettings; } @@ -1346,10 +1349,13 @@ void BladeRF2MIMO::networkManagerFinished(QNetworkReply *reply) << " error(" << (int) replyError << "): " << replyError << ": " << reply->errorString(); - return; + } + else + { + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("BladeRF2MIMO::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); } - QString answer = reply->readAll(); - answer.chop(1); // remove last \n - qDebug("BladeRF2MIMO::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); + reply->deleteLater(); } diff --git a/plugins/samplemimo/testmosync/testmosync.cpp b/plugins/samplemimo/testmosync/testmosync.cpp index 7bf1e044f..a41f753de 100644 --- a/plugins/samplemimo/testmosync/testmosync.cpp +++ b/plugins/samplemimo/testmosync/testmosync.cpp @@ -48,7 +48,7 @@ TestMOSync::TestMOSync(DeviceAPI *deviceAPI) : m_feedSpectrumIndex(0) { m_mimoType = MIMOHalfSynchronous; - m_sampleMOFifo.init(2, 4096*64); + m_sampleMOFifo.init(2, SampleMOFifo::getSizePolicy(m_settings.m_sampleRate)); m_deviceAPI->setNbSourceStreams(0); m_deviceAPI->setNbSinkStreams(2); } @@ -254,6 +254,12 @@ bool TestMOSync::applySettings(const TestMOSyncSettings& settings, bool force) forwardChangeTxDSP = true; } + if ((m_settings.m_sampleRate != settings.m_sampleRate) + || (m_settings.m_log2Interp != settings.m_log2Interp) || force) + { + m_sampleMOFifo.resize(SampleMOFifo::getSizePolicy(m_settings.m_sampleRate)); + } + if ((m_settings.m_sampleRate != settings.m_sampleRate) || force) { if (m_sinkThread) { diff --git a/plugins/samplemimo/testmosync/testmosyncsettings.cpp b/plugins/samplemimo/testmosync/testmosyncsettings.cpp index a09b4960d..596f90432 100644 --- a/plugins/samplemimo/testmosync/testmosyncsettings.cpp +++ b/plugins/samplemimo/testmosync/testmosyncsettings.cpp @@ -19,7 +19,6 @@ #include "testmosyncsettings.h" const unsigned int TestMOSyncSettings::m_msThrottle = 50U; -const unsigned int TestMOSyncSettings::m_blockSize = 16384U; TestMOSyncSettings::TestMOSyncSettings() { diff --git a/plugins/samplemimo/testmosync/testmosyncsettings.h b/plugins/samplemimo/testmosync/testmosyncsettings.h index 74210f4c9..dc40e9c5a 100644 --- a/plugins/samplemimo/testmosync/testmosyncsettings.h +++ b/plugins/samplemimo/testmosync/testmosyncsettings.h @@ -33,7 +33,6 @@ struct TestMOSyncSettings { fcPos_t m_fcPosTx; static const unsigned int m_msThrottle; - static const unsigned int m_blockSize; TestMOSyncSettings(); void resetToDefaults(); diff --git a/plugins/samplemimo/testmosync/testmosyncthread.cpp b/plugins/samplemimo/testmosync/testmosyncthread.cpp index 91441b49b..7aae77565 100644 --- a/plugins/samplemimo/testmosync/testmosyncthread.cpp +++ b/plugins/samplemimo/testmosync/testmosyncthread.cpp @@ -27,16 +27,17 @@ TestMOSyncThread::TestMOSyncThread(QObject* parent) : QThread(parent), m_running(false), + m_buf(nullptr), m_log2Interp(0), m_throttlems(TestMOSyncSettings::m_msThrottle), m_throttleToggle(false), - m_blockSize(TestMOSyncSettings::m_blockSize), m_samplesRemainder(0), + m_samplerate(0), m_feedSpectrumIndex(0), m_spectrumSink(nullptr) { qDebug("TestMOSyncThread::TestMOSyncThread"); - m_buf = new qint16[2*m_blockSize*2]; + setSamplerate(48000); } TestMOSyncThread::~TestMOSyncThread() @@ -52,6 +53,7 @@ TestMOSyncThread::~TestMOSyncThread() void TestMOSyncThread::startWork() { + qDebug("TestMOSyncThread::startWork"); m_startWaitMutex.lock(); m_elapsedTimer.start(); start(); @@ -65,6 +67,7 @@ void TestMOSyncThread::startWork() void TestMOSyncThread::stopWork() { + qDebug("TestMOSyncThread::stopWork"); m_running = false; wait(); } @@ -107,7 +110,11 @@ void TestMOSyncThread::setSamplerate(int samplerate) m_samplerate = samplerate; m_samplesChunkSize = (m_samplerate * m_throttlems) / 1000; m_blockSize = (m_samplerate * 50) / 1000; - delete[] m_buf; + + if (m_buf) { + delete[] m_buf; + } + m_buf = new qint16[2*m_blockSize*2]; if (wasRunning) { @@ -181,7 +188,14 @@ void TestMOSyncThread::callbackPart(qint16* buf, qint32 nSamples, int iBegin) { for (unsigned int channel = 0; channel < 2; channel++) { + qDebug("TestMOSyncThread::callbackPart: nSamples: %d channel: %u", nSamples, channel); SampleVector::iterator begin = m_sampleFifo->getData(channel).begin() + iBegin; + // m_testVector.allocate(nSamples/(1<= m_blockSize) { @@ -306,6 +321,7 @@ void TestMOSyncThread::feedSpectrum(int16_t *buf, unsigned int bufSize) return; } + qDebug("TestMOSyncThread::feedSpectrum: bufSize: %u", bufSize); m_samplesVector.allocate(bufSize/2); Sample16 *s16Buf = (Sample16*) buf; diff --git a/plugins/samplemimo/testmosync/testmosyncthread.h b/plugins/samplemimo/testmosync/testmosyncthread.h index 65967468a..56cd930c9 100644 --- a/plugins/samplemimo/testmosync/testmosyncthread.h +++ b/plugins/samplemimo/testmosync/testmosyncthread.h @@ -84,6 +84,7 @@ private: unsigned int m_feedSpectrumIndex; BasebandSampleSink* m_spectrumSink; IncrementalVector m_samplesVector; + IncrementalVector m_testVector; void run(); unsigned int getNbFifos();