From f1544852b9811410d81e32f8f02300d914ac01da Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 10 Nov 2020 21:49:43 +0100 Subject: [PATCH] Beam steering CW channel --- plugins/channelmimo/CMakeLists.txt | 2 + .../beamsteeringcwmod/CMakeLists.txt | 60 +++ .../beamsteeringcwmod/beamsteeringcwmod.cpp | 457 ++++++++++++++++++ .../beamsteeringcwmod/beamsteeringcwmod.h | 180 +++++++ .../beamsteeringcwmodbaseband.cpp | 247 ++++++++++ .../beamsteeringcwmodbaseband.h | 105 ++++ .../beamsteeringcwmodgui.cpp | 299 ++++++++++++ .../beamsteeringcwmod/beamsteeringcwmodgui.h | 95 ++++ .../beamsteeringcwmod/beamsteeringcwmodgui.ui | 342 +++++++++++++ .../beamsteeringcwmodplugin.cpp | 91 ++++ .../beamsteeringcwmodplugin.h | 49 ++ .../beamsteeringcwmodsettings.cpp | 117 +++++ .../beamsteeringcwmodsettings.h | 49 ++ .../beamsteeringcwmodstreamsource.cpp | 67 +++ .../beamsteeringcwmodstreamsource.h | 47 ++ .../beamsteeringcwmodwebapiadapter.cpp | 50 ++ .../beamsteeringcwmodwebapiadapter.h | 49 ++ .../channelmimo/beamsteeringcwmod/readme.md | 56 +++ sdrbase/resources/webapi.qrc | 1 + sdrbase/resources/webapi/doc/html2/index.html | 41 +- .../swagger/include/BeamSteeringCWMod.yaml | 24 + .../doc/swagger/include/ChannelSettings.yaml | 2 + sdrbase/webapi/webapirequestmapper.cpp | 5 + .../swagger/include/BeamSteeringCWMod.yaml | 24 + .../api/swagger/include/ChannelSettings.yaml | 2 + swagger/sdrangel/code/html2/index.html | 41 +- .../client/SWGBeamSteeringCWModSettings.cpp | 319 ++++++++++++ .../qt5/client/SWGBeamSteeringCWModSettings.h | 113 +++++ .../code/qt5/client/SWGChannelSettings.cpp | 25 + .../code/qt5/client/SWGChannelSettings.h | 7 + .../code/qt5/client/SWGModelFactory.h | 4 + 31 files changed, 2968 insertions(+), 2 deletions(-) create mode 100644 plugins/channelmimo/beamsteeringcwmod/CMakeLists.txt create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmod.cpp create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmod.h create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodbaseband.cpp create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodbaseband.h create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.cpp create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.h create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.ui create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodplugin.cpp create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodplugin.h create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsettings.cpp create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsettings.h create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.cpp create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.h create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodwebapiadapter.cpp create mode 100644 plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodwebapiadapter.h create mode 100644 plugins/channelmimo/beamsteeringcwmod/readme.md create mode 100644 sdrbase/resources/webapi/doc/swagger/include/BeamSteeringCWMod.yaml create mode 100644 swagger/sdrangel/api/swagger/include/BeamSteeringCWMod.yaml create mode 100644 swagger/sdrangel/code/qt5/client/SWGBeamSteeringCWModSettings.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGBeamSteeringCWModSettings.h diff --git a/plugins/channelmimo/CMakeLists.txt b/plugins/channelmimo/CMakeLists.txt index 1f153b8d3..5b951ebc6 100644 --- a/plugins/channelmimo/CMakeLists.txt +++ b/plugins/channelmimo/CMakeLists.txt @@ -1,5 +1,7 @@ project(channelmimo) +add_subdirectory(beamsteeringcwmod) + if (NOT SERVER_MODE) add_subdirectory(interferometer) endif() diff --git a/plugins/channelmimo/beamsteeringcwmod/CMakeLists.txt b/plugins/channelmimo/beamsteeringcwmod/CMakeLists.txt new file mode 100644 index 000000000..42a36de53 --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/CMakeLists.txt @@ -0,0 +1,60 @@ +project(beamsteeringcwmod) + +set(beamsteeringcwmod_SOURCES + beamsteeringcwmod.cpp + beamsteeringcwmodsettings.cpp + beamsteeringcwmodbaseband.cpp + beamsteeringcwmodstreamsource.cpp + beamsteeringcwmodplugin.cpp + beamsteeringcwmodwebapiadapter.cpp +) + +set(beamsteeringcwmod_HEADERS + beamsteeringcwmod.h + beamsteeringcwmodsettings.h + beamsteeringcwmodbaseband.h + beamsteeringcwmodstreamsource.h + beamsteeringcwmodplugin.h + beamsteeringcwmodwebapiadapter.h +) + +include_directories( + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${Boost_INCLUDE_DIR} +) + +if (NOT SERVER_MODE) + set(beamsteeringcwmod_SOURCES + ${beamsteeringcwmod_SOURCES} + beamsteeringcwmodgui.cpp + beamsteeringcwmodgui.ui + ) + set(beamsteeringcwmod_HEADERS + ${beamsteeringcwmod_HEADERS} + beamsteeringcwmodgui.h + ) + + set(TARGET_NAME beamsteeringcwmod) + set(TARGET_LIB "Qt5::Widgets") + set(TARGET_LIB_GUI "sdrgui") + set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) +else() + set(TARGET_NAME beamsteeringcwmodsrv) + set(TARGET_LIB "") + set(TARGET_LIB_GUI "") + set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR}) +endif() + +add_library(${TARGET_NAME} SHARED + ${beamsteeringcwmod_SOURCES} +) + +target_link_libraries(${TARGET_NAME} + Qt5::Core + ${TARGET_LIB} + sdrbase + ${TARGET_LIB_GUI} + swagger +) + +install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER}) diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmod.cpp b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmod.cpp new file mode 100644 index 000000000..72288cd4f --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmod.cpp @@ -0,0 +1,457 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 +#include +#include + +#include "SWGChannelSettings.h" + +#include "device/deviceapi.h" +#include "dsp/hbfilterchainconverter.h" +#include "dsp/dspcommands.h" +#include "feature/feature.h" +#include "maincore.h" + +#include "beamsteeringcwmodbaseband.h" +#include "beamsteeringcwmod.h" + +MESSAGE_CLASS_DEFINITION(BeamSteeringCWMod::MsgConfigureBeamSteeringCWMod, Message) +MESSAGE_CLASS_DEFINITION(BeamSteeringCWMod::MsgBasebandNotification, Message) + +const QString BeamSteeringCWMod::m_channelIdURI = "sdrangel.channel.beamsteeringcwmod"; +const QString BeamSteeringCWMod::m_channelId = "BeamSteeringCWMod"; + +BeamSteeringCWMod::BeamSteeringCWMod(DeviceAPI *deviceAPI) : + ChannelAPI(m_channelIdURI, ChannelAPI::StreamMIMO), + m_deviceAPI(deviceAPI), + m_guiMessageQueue(nullptr), + m_frequencyOffset(0), + m_basebandSampleRate(48000) +{ + setObjectName(m_channelId); + + m_thread = new QThread(this); + 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())); + + m_networkManager = new QNetworkAccessManager(); + connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); +} + +BeamSteeringCWMod::~BeamSteeringCWMod() +{ + disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); + delete m_networkManager; + + m_deviceAPI->removeChannelSinkAPI(this); + m_deviceAPI->removeMIMOChannel(this); + delete m_basebandSource; + delete m_thread; +} + +void BeamSteeringCWMod::startSources() +{ + qDebug("BeamSteeringCWMod::startSources"); + m_basebandSource->reset(); + m_thread->start(); + + BeamSteeringCWModBaseband::MsgSignalNotification *sig = BeamSteeringCWModBaseband::MsgSignalNotification::create( + m_basebandSampleRate); + m_basebandSource->getInputMessageQueue()->push(sig); + + BeamSteeringCWModBaseband::MsgConfigureBeamSteeringCWModBaseband *msg = BeamSteeringCWModBaseband::MsgConfigureBeamSteeringCWModBaseband::create( + m_settings, true); + m_basebandSource->getInputMessageQueue()->push(msg); +} + +void BeamSteeringCWMod::stopSources() +{ + qDebug("BeamSteeringCWMod::stopSources"); + m_thread->exit(); + m_thread->wait(); +} + +void BeamSteeringCWMod::pull(SampleVector::iterator& begin, unsigned int nbSamples, unsigned int sourceIndex) +{ + m_basebandSource->pull(begin, nbSamples, sourceIndex); +} + +void BeamSteeringCWMod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, unsigned int sinkIndex) +{ + (void) begin; + (void) end; + (void) sinkIndex; +} + +void BeamSteeringCWMod::applySettings(const BeamSteeringCWModSettings& settings, bool force) +{ + qDebug() << "BeamSteeringCWMod::applySettings: " + << "m_steerDegrees: " << settings.m_steerDegrees + << "m_channelOutput: " << settings.m_channelOutput + << "m_filterChainHash: " << settings.m_filterChainHash + << "m_log2Interp: " << settings.m_log2Interp + << "m_filterChainHash: " << settings.m_filterChainHash + << "m_useReverseAPI: " << settings.m_useReverseAPI + << "m_reverseAPIAddress: " << settings.m_reverseAPIAddress + << "m_reverseAPIPort: " << settings.m_reverseAPIPort + << "m_reverseAPIDeviceIndex: " << settings.m_reverseAPIDeviceIndex + << "m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex + << "m_title: " << settings.m_title; + + QList reverseAPIKeys; + + if ((m_settings.m_steerDegrees != settings.m_steerDegrees) || force) { + reverseAPIKeys.append("steerDegrees"); + } + if ((m_settings.m_channelOutput != settings.m_channelOutput) || force) { + reverseAPIKeys.append("channelOutput"); + } + if ((m_settings.m_filterChainHash != settings.m_filterChainHash) || force) { + reverseAPIKeys.append("filterChainHash"); + } + if ((m_settings.m_log2Interp != settings.m_log2Interp) || force) { + reverseAPIKeys.append("log2Interp"); + } + if ((m_settings.m_filterChainHash != settings.m_filterChainHash) || force) { + reverseAPIKeys.append("filterChainHash"); + } + + BeamSteeringCWModBaseband::MsgConfigureBeamSteeringCWModBaseband *msg = BeamSteeringCWModBaseband::MsgConfigureBeamSteeringCWModBaseband::create(settings, force); + m_basebandSource->getInputMessageQueue()->push(msg); + + if (m_featuresSettingsFeedback.size() > 0) { + featuresSendSettings(reverseAPIKeys, settings, force); + } + + m_settings = settings; +} + +void BeamSteeringCWMod::handleInputMessages() +{ + Message* message; + + while ((message = m_inputMessageQueue.pop()) != 0) + { + if (handleMessage(*message)) + { + delete message; + } + } +} + +bool BeamSteeringCWMod::handleMessage(const Message& cmd) +{ + if (MsgConfigureBeamSteeringCWMod::match(cmd)) + { + MsgConfigureBeamSteeringCWMod& cfg = (MsgConfigureBeamSteeringCWMod&) cmd; + qDebug() << "BeamSteeringCWMod::handleMessage: MsgConfigureBeamSteeringCWMod"; + applySettings(cfg.getSettings(), cfg.getForce()); + return true; + } + else if (DSPMIMOSignalNotification::match(cmd)) + { + DSPMIMOSignalNotification& notif = (DSPMIMOSignalNotification&) cmd; + + qDebug() << "BeamSteeringCWMod::handleMessage: DSPMIMOSignalNotification:" + << " basebandSampleRate: " << notif.getSampleRate() + << " centerFrequency: " << notif.getCenterFrequency() + << " sourceElseSink: " << notif.getSourceOrSink() + << " streamIndex: " << notif.getIndex(); + + if (!notif.getSourceOrSink()) // deals with sink messages only + { + m_basebandSampleRate = notif.getSampleRate(); + calculateFrequencyOffset(); // This is when device sample rate changes + + // Notify source of input sample rate change + BeamSteeringCWModBaseband::MsgSignalNotification *sig = BeamSteeringCWModBaseband::MsgSignalNotification::create( + m_basebandSampleRate); + qDebug() << "BeamSteeringCWMod::handleMessage: DSPMIMOSignalNotification: push to source"; + m_basebandSource->getInputMessageQueue()->push(sig); + + if (m_guiMessageQueue) + { + qDebug() << "BeamSteeringCWMod::handleMessage: DSPMIMOSignalNotification: push to GUI"; + MsgBasebandNotification *msg = MsgBasebandNotification::create( + notif.getSampleRate(), notif.getCenterFrequency()); + m_guiMessageQueue->push(msg); + } + } + + return true; + } + else + { + return false; + } +} + +QByteArray BeamSteeringCWMod::serialize() const +{ + return m_settings.serialize(); +} + +bool BeamSteeringCWMod::deserialize(const QByteArray& data) +{ + (void) data; + if (m_settings.deserialize(data)) + { + MsgConfigureBeamSteeringCWMod *msg = MsgConfigureBeamSteeringCWMod::create(m_settings, true); + m_inputMessageQueue.push(msg); + return true; + } + else + { + m_settings.resetToDefaults(); + MsgConfigureBeamSteeringCWMod *msg = MsgConfigureBeamSteeringCWMod::create(m_settings, true); + m_inputMessageQueue.push(msg); + return false; + } +} + +void BeamSteeringCWMod::validateFilterChainHash(BeamSteeringCWModSettings& settings) +{ + unsigned int s = 1; + + for (unsigned int i = 0; i < settings.m_log2Interp; i++) { + s *= 3; + } + + settings.m_filterChainHash = settings.m_filterChainHash >= s ? s-1 : settings.m_filterChainHash; +} + +void BeamSteeringCWMod::calculateFrequencyOffset() +{ + double shiftFactor = HBFilterChainConverter::getShiftFactor(m_settings.m_log2Interp, m_settings.m_filterChainHash); + m_frequencyOffset = m_basebandSampleRate * shiftFactor; +} + +int BeamSteeringCWMod::webapiSettingsGet( + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setBeamSteeringCwModSettings(new SWGSDRangel::SWGBeamSteeringCWModSettings()); + response.getBeamSteeringCwModSettings()->init(); + webapiFormatChannelSettings(response, m_settings); + return 200; +} + +int BeamSteeringCWMod::webapiSettingsPutPatch( + bool force, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + BeamSteeringCWModSettings settings = m_settings; + webapiUpdateChannelSettings(settings, channelSettingsKeys, response); + + MsgConfigureBeamSteeringCWMod *msg = MsgConfigureBeamSteeringCWMod::create(settings, force); + m_inputMessageQueue.push(msg); + + if (getMessageQueueToGUI()) // forward to GUI if any + { + MsgConfigureBeamSteeringCWMod *msgToGUI = MsgConfigureBeamSteeringCWMod::create(settings, force); + getMessageQueueToGUI()->push(msgToGUI); + } + + webapiFormatChannelSettings(response, settings); + + return 200; +} + +void BeamSteeringCWMod::webapiUpdateChannelSettings( + BeamSteeringCWModSettings& settings, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response) +{ + if (channelSettingsKeys.contains("steerDegrees")) { + settings.m_rgbColor = response.getBeamSteeringCwModSettings()->getSteerDegrees(); + } + + if (channelSettingsKeys.contains("rgbColor")) { + settings.m_rgbColor = response.getBeamSteeringCwModSettings()->getRgbColor(); + } + if (channelSettingsKeys.contains("title")) { + settings.m_title = *response.getBeamSteeringCwModSettings()->getTitle(); + } + if (channelSettingsKeys.contains("log2Interp")) { + settings.m_log2Interp = response.getBeamSteeringCwModSettings()->getLog2Interp(); + } + + if (channelSettingsKeys.contains("filterChainHash")) + { + settings.m_filterChainHash = response.getBeamSteeringCwModSettings()->getFilterChainHash(); + validateFilterChainHash(settings); + } + + if (channelSettingsKeys.contains("useReverseAPI")) { + settings.m_useReverseAPI = response.getBeamSteeringCwModSettings()->getUseReverseApi() != 0; + } + if (channelSettingsKeys.contains("reverseAPIAddress")) { + settings.m_reverseAPIAddress = *response.getBeamSteeringCwModSettings()->getReverseApiAddress(); + } + if (channelSettingsKeys.contains("reverseAPIPort")) { + settings.m_reverseAPIPort = response.getBeamSteeringCwModSettings()->getReverseApiPort(); + } + if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) { + settings.m_reverseAPIDeviceIndex = response.getBeamSteeringCwModSettings()->getReverseApiDeviceIndex(); + } + if (channelSettingsKeys.contains("reverseAPIChannelIndex")) { + settings.m_reverseAPIChannelIndex = response.getBeamSteeringCwModSettings()->getReverseApiChannelIndex(); + } +} + +void BeamSteeringCWMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const BeamSteeringCWModSettings& settings) +{ + response.getBeamSteeringCwModSettings()->setSteerDegrees(settings.m_steerDegrees); + response.getBeamSteeringCwModSettings()->setRgbColor(settings.m_rgbColor); + + if (response.getBeamSteeringCwModSettings()->getTitle()) { + *response.getBeamSteeringCwModSettings()->getTitle() = settings.m_title; + } else { + response.getBeamSteeringCwModSettings()->setTitle(new QString(settings.m_title)); + } + + response.getBeamSteeringCwModSettings()->setLog2Interp(settings.m_log2Interp); + response.getBeamSteeringCwModSettings()->setFilterChainHash(settings.m_filterChainHash); + response.getBeamSteeringCwModSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); + + if (response.getBeamSteeringCwModSettings()->getReverseApiAddress()) { + *response.getBeamSteeringCwModSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress; + } else { + response.getBeamSteeringCwModSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress)); + } + + response.getBeamSteeringCwModSettings()->setReverseApiPort(settings.m_reverseAPIPort); + response.getBeamSteeringCwModSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex); + response.getBeamSteeringCwModSettings()->setReverseApiChannelIndex(settings.m_reverseAPIChannelIndex); +} + +void BeamSteeringCWMod::webapiReverseSendSettings(QList& channelSettingsKeys, const BeamSteeringCWModSettings& settings, bool force) +{ + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + m_networkRequest.setUrl(QUrl(channelSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + 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 + QNetworkReply *reply = m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + buffer->setParent(reply); + + delete swgChannelSettings; +} + +void BeamSteeringCWMod::featuresSendSettings(QList& channelSettingsKeys, const BeamSteeringCWModSettings& settings, bool force) +{ + QList::iterator it = m_featuresSettingsFeedback.begin(); + MainCore *mainCore = MainCore::instance(); + + for (; it != m_featuresSettingsFeedback.end(); ++it) + { + if (mainCore->existsFeature(*it)) + { + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + Feature::MsgChannelSettings *msg = Feature::MsgChannelSettings::create( + this, + channelSettingsKeys, + swgChannelSettings, + force + ); + + (*it)->getInputMessageQueue()->push(msg); + } + else + { + m_featuresSettingsFeedback.removeOne(*it); + } + } +} + +void BeamSteeringCWMod::webapiFormatChannelSettings( + QList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const BeamSteeringCWModSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(2); // MIMO sink + swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); + swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); + swgChannelSettings->setChannelType(new QString("BeamSteeringCWSource")); + swgChannelSettings->setBeamSteeringCwModSettings(new SWGSDRangel::SWGBeamSteeringCWModSettings()); + SWGSDRangel::SWGBeamSteeringCWModSettings *swgBeamSteeringCWSettings = swgChannelSettings->getBeamSteeringCwModSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (channelSettingsKeys.contains("steerDegrees") || force) { + swgBeamSteeringCWSettings->setSteerDegrees(settings.m_steerDegrees); + } + if (channelSettingsKeys.contains("rgbColor") || force) { + swgBeamSteeringCWSettings->setRgbColor(settings.m_rgbColor); + } + if (channelSettingsKeys.contains("title") || force) { + swgBeamSteeringCWSettings->setTitle(new QString(settings.m_title)); + } + if (channelSettingsKeys.contains("log2Decim") || force) { + swgBeamSteeringCWSettings->setLog2Interp(settings.m_log2Interp); + } + if (channelSettingsKeys.contains("filterChainHash") || force) { + swgBeamSteeringCWSettings->setFilterChainHash(settings.m_filterChainHash); + } +} + +void BeamSteeringCWMod::networkManagerFinished(QNetworkReply *reply) +{ + QNetworkReply::NetworkError replyError = reply->error(); + + if (replyError) + { + qWarning() << "BeamSteeringCWMod::networkManagerFinished:" + << " error(" << (int) replyError + << "): " << replyError + << ": " << reply->errorString(); + } + else + { + 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 new file mode 100644 index 000000000..45c1507e1 --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmod.h @@ -0,0 +1,180 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_BEAMSTEERINGCWMOD_H +#define INCLUDE_BEAMSTEERINGCWMOD_H + +#include +#include + +#include "dsp/mimochannel.h" +#include "channel/channelapi.h" +#include "util/messagequeue.h" +#include "util/message.h" + +#include "beamsteeringcwmodsettings.h" + +class QThread; +class DeviceAPI; +class BeamSteeringCWModBaseband; +class QNetworkReply; +class QNetworkAccessManager; +class BasebandSampleSink; + +class BeamSteeringCWMod: public MIMOChannel, public ChannelAPI +{ + Q_OBJECT +public: + class MsgConfigureBeamSteeringCWMod : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const BeamSteeringCWModSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureBeamSteeringCWMod* create(const BeamSteeringCWModSettings& settings, bool force) + { + return new MsgConfigureBeamSteeringCWMod(settings, force); + } + + private: + BeamSteeringCWModSettings m_settings; + bool m_force; + + MsgConfigureBeamSteeringCWMod(const BeamSteeringCWModSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + class MsgBasebandNotification : public Message { + MESSAGE_CLASS_DECLARATION + + public: + static MsgBasebandNotification* create(int sampleRate, qint64 centerFrequency) { + return new MsgBasebandNotification(sampleRate, centerFrequency); + } + + int getSampleRate() const { return m_sampleRate; } + qint64 getCenterFrequency() const { return m_centerFrequency; } + + private: + + MsgBasebandNotification(int sampleRate, qint64 centerFrequency) : + Message(), + m_sampleRate(sampleRate), + m_centerFrequency(centerFrequency) + { } + + int m_sampleRate; + qint64 m_centerFrequency; + }; + + BeamSteeringCWMod(DeviceAPI *deviceAPI); + virtual ~BeamSteeringCWMod(); + virtual void destroy() { delete this; } + + virtual void startSinks() {} + virtual void stopSinks() {} + 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(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 = m_channelId; } + virtual const QString& getURI() const { return m_channelIdURI; } + virtual void getTitle(QString& title) { title = "BeamSteeringCWMod"; } + virtual qint64 getCenterFrequency() const { return m_frequencyOffset; } + uint32_t getBasebandSampleRate() const { return m_basebandSampleRate; } + + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); + + virtual int getNbSinkStreams() const { return 0; } + virtual int getNbSourceStreams() const { return 2; } + + virtual qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const + { + (void) streamIndex; + (void) sinkElseSource; + return m_frequencyOffset; + } + + MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication + virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; } + MessageQueue *getMessageQueueToGUI() { return m_guiMessageQueue; } + + virtual int webapiSettingsGet( + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage); + + static void webapiFormatChannelSettings( + SWGSDRangel::SWGChannelSettings& response, + const BeamSteeringCWModSettings& settings); + + static void webapiUpdateChannelSettings( + BeamSteeringCWModSettings& settings, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response); + + static const QString m_channelIdURI; + static const QString m_channelId; + static const int m_fftSize; + +private: + DeviceAPI *m_deviceAPI; + QThread *m_thread; + BeamSteeringCWModBaseband* m_basebandSource; + BasebandSampleSink* m_spectrumSink; + BasebandSampleSink* m_scopeSink; + BeamSteeringCWModSettings m_settings; + MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication + MessageQueue *m_guiMessageQueue; //!< Input message queue to the GUI + + QNetworkAccessManager *m_networkManager; + QNetworkRequest m_networkRequest; + + int64_t m_frequencyOffset; + uint32_t m_basebandSampleRate; + int m_count0, m_count1; + + void applySettings(const BeamSteeringCWModSettings& settings, bool force = false); + static void validateFilterChainHash(BeamSteeringCWModSettings& settings); + void calculateFrequencyOffset(); + void webapiReverseSendSettings(QList& channelSettingsKeys, const BeamSteeringCWModSettings& settings, bool force); + void featuresSendSettings(QList& channelSettingsKeys, const BeamSteeringCWModSettings& settings, bool force); + void webapiFormatChannelSettings( + QList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const BeamSteeringCWModSettings& settings, + bool force + ); + +private slots: + void handleInputMessages(); + void networkManagerFinished(QNetworkReply *reply); +}; + +#endif // INCLUDE_BEAMSTEERINGCWSOURCE_H diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodbaseband.cpp b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodbaseband.cpp new file mode 100644 index 000000000..25ddfcf92 --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodbaseband.cpp @@ -0,0 +1,247 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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/upchannelizer.h" +#include "dsp/dspcommands.h" + +#include "beamsteeringcwmodbaseband.h" + + +MESSAGE_CLASS_DEFINITION(BeamSteeringCWModBaseband::MsgConfigureBeamSteeringCWModBaseband, Message) +MESSAGE_CLASS_DEFINITION(BeamSteeringCWModBaseband::MsgSignalNotification, Message) + +BeamSteeringCWModBaseband::BeamSteeringCWModBaseband() : + m_mutex(QMutex::Recursive) +{ + m_sampleMOFifo.init(2, SampleMOFifo::getSizePolicy(48000)); + m_vbegin.resize(2); + + for (int i = 0; i < 2; i++) + { + m_streamSources[i].setStreamIndex(i); + m_channelizers[i] = new UpChannelizer(&m_streamSources[i]); + m_sizes[i] = 0; + } + + QObject::connect( + &m_sampleMOFifo, + &SampleMOFifo::dataReadSync, + this, + &BeamSteeringCWModBaseband::handleData, + Qt::QueuedConnection + ); + + connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + m_lastStream = 0; +} + +BeamSteeringCWModBaseband::~BeamSteeringCWModBaseband() +{ + for (int i = 0; i < 2; i++) { + delete m_channelizers[i]; + } +} + +void BeamSteeringCWModBaseband::reset() +{ + QMutexLocker mutexLocker(&m_mutex); + m_sampleMOFifo.reset(); + + for (int i = 0; i < 2; i++) + { + m_streamSources[i].reset(); + m_sizes[i] = 0; + } +} + +void BeamSteeringCWModBaseband::pull(SampleVector::iterator& begin, unsigned int nbSamples, unsigned int streamIndex) +{ + if (streamIndex > 1) { + return; + } + + if (streamIndex == m_lastStream) { + qWarning("BeamSteeringCWModBaseband::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("BeamSteeringCWModBaseband::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 BeamSteeringCWModBaseband::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(remainder, 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 BeamSteeringCWModBaseband::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 BeamSteeringCWModBaseband::handleInputMessages() +{ + Message* message; + + while ((message = m_inputMessageQueue.pop()) != nullptr) + { + if (handleMessage(*message)) { + delete message; + } + } +} + +bool BeamSteeringCWModBaseband::handleMessage(const Message& cmd) +{ + if (MsgConfigureBeamSteeringCWModBaseband::match(cmd)) + { + QMutexLocker mutexLocker(&m_mutex); + MsgConfigureBeamSteeringCWModBaseband& cfg = (MsgConfigureBeamSteeringCWModBaseband&) cmd; + qDebug() << "BeamSteeringCWModBaseband::handleMessage: MsgConfigureBeamSteeringCWModBaseband"; + + applySettings(cfg.getSettings(), cfg.getForce()); + + return true; + } + else if (MsgSignalNotification::match(cmd)) + { + QMutexLocker mutexLocker(&m_mutex); + MsgSignalNotification& cfg = (MsgSignalNotification&) cmd; + int basebandSampleRate = cfg.getBasebandSampleRate(); + + qDebug() << "BeamSteeringCWModBaseband::handleMessage: MsgSignalNotification:" + << " basebandSampleRate: " << basebandSampleRate; + + m_sampleMOFifo.resize(SampleMOFifo::getSizePolicy(basebandSampleRate)); + + for (int i = 0; i < 2; i++) + { + m_channelizers[i]->setBasebandSampleRate(basebandSampleRate, true); + m_streamSources[i].reset(); + } + + return true; + } + else + { + qDebug("BeamSteeringCWModBaseband::handleMessage: unhandled: %s", cmd.getIdentifier()); + return false; + } +} + +void BeamSteeringCWModBaseband::applySettings(const BeamSteeringCWModSettings& settings, bool force) +{ + if ((m_settings.m_filterChainHash != settings.m_filterChainHash) || (m_settings.m_log2Interp != settings.m_log2Interp) || force) + { + for (int i = 0; i < 2; i++) + { + m_channelizers[i]->setInterpolation(settings.m_log2Interp, settings.m_filterChainHash); + m_streamSources[i].reset(); + } + } + + if ((m_settings.m_steerDegrees != settings.m_steerDegrees) || force) + { + float steeringAngle = settings.m_steerDegrees / 180.0f; + steeringAngle = steeringAngle < -M_PI ? -M_PI : steeringAngle > M_PI ? M_PI : steeringAngle; + m_streamSources[1].setPhase(M_PI*cos(steeringAngle)); + } + + if ((m_settings.m_channelOutput != settings.m_channelOutput) || force) + { + if (settings.m_channelOutput == 0) + { + m_streamSources[0].muteChannel(false); + m_streamSources[1].muteChannel(false); + } + else if (settings.m_channelOutput == 1) + { + m_streamSources[0].muteChannel(false); + m_streamSources[1].muteChannel(true); + } + else if (settings.m_channelOutput == 2) + { + m_streamSources[0].muteChannel(true); + m_streamSources[1].muteChannel(false); + } + else + { + m_streamSources[0].muteChannel(false); + m_streamSources[1].muteChannel(false); + } + } + + m_settings = settings; +} \ No newline at end of file diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodbaseband.h b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodbaseband.h new file mode 100644 index 000000000..94f51cd5f --- /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 UpChannelizer; + +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]; + UpChannelizer *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 new file mode 100644 index 000000000..8e6569b25 --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.cpp @@ -0,0 +1,299 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 "device/deviceuiset.h" +#include "gui/basicchannelsettingsdialog.h" +#include "dsp/hbfilterchainconverter.h" +#include "maincore.h" + +#include "beamsteeringcwmodgui.h" +#include "beamsteeringcwmod.h" +#include "ui_beamsteeringcwmodgui.h" + +BeamSteeringCWModGUI* BeamSteeringCWModGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, MIMOChannel *mimoChannel) +{ + BeamSteeringCWModGUI* gui = new BeamSteeringCWModGUI(pluginAPI, deviceUISet, mimoChannel); + return gui; +} + +void BeamSteeringCWModGUI::destroy() +{ + delete this; +} + +void BeamSteeringCWModGUI::resetToDefaults() +{ + m_settings.resetToDefaults(); + displaySettings(); + applySettings(true); +} + +QByteArray BeamSteeringCWModGUI::serialize() const +{ + return m_settings.serialize(); +} + +bool BeamSteeringCWModGUI::deserialize(const QByteArray& data) +{ + if(m_settings.deserialize(data)) { + displaySettings(); + applySettings(true); + return true; + } else { + resetToDefaults(); + return false; + } +} + +bool BeamSteeringCWModGUI::handleMessage(const Message& message) +{ + if (BeamSteeringCWMod::MsgBasebandNotification::match(message)) + { + BeamSteeringCWMod::MsgBasebandNotification& notif = (BeamSteeringCWMod::MsgBasebandNotification&) message; + m_basebandSampleRate = notif.getSampleRate(); + m_centerFrequency = notif.getCenterFrequency(); + displayRateAndShift(); + return true; + } + else if (BeamSteeringCWMod::MsgConfigureBeamSteeringCWMod::match(message)) + { + const BeamSteeringCWMod::MsgConfigureBeamSteeringCWMod& cfg = (BeamSteeringCWMod::MsgConfigureBeamSteeringCWMod&) message; + m_settings = cfg.getSettings(); + blockApplySettings(true); + displaySettings(); + blockApplySettings(false); + return true; + } + else + { + return false; + } +} + +BeamSteeringCWModGUI::BeamSteeringCWModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, MIMOChannel *mimoChannel, QWidget* parent) : + ChannelGUI(parent), + ui(new Ui::BeamSteeringCWModGUI), + m_pluginAPI(pluginAPI), + m_deviceUISet(deviceUISet), + m_basebandSampleRate(48000), + m_centerFrequency(435000000), + m_tickCount(0) +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, true); + setStreamIndicator("M"); + + connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &))); + + m_bsCWSource = (BeamSteeringCWMod*) mimoChannel; + m_bsCWSource->setMessageQueueToGUI(getInputMessageQueue()); + m_basebandSampleRate = m_bsCWSource->getBasebandSampleRate(); + + connect(&MainCore::instance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); + + m_channelMarker.blockSignals(true); + m_channelMarker.addStreamIndex(1); + m_channelMarker.setColor(m_settings.m_rgbColor); + m_channelMarker.setCenterFrequency(0); + m_channelMarker.setTitle("Beam Steering CW Source"); + m_channelMarker.setSourceOrSinkStream(false); + m_channelMarker.blockSignals(false); + m_channelMarker.setVisible(true); // activate signal on the last setting only + + m_settings.setChannelMarker(&m_channelMarker); + + m_deviceUISet->addChannelMarker(&m_channelMarker); + m_deviceUISet->addRollupWidget(this); + + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); + + displaySettings(); + displayRateAndShift(); + applySettings(true); +} + +BeamSteeringCWModGUI::~BeamSteeringCWModGUI() +{ + delete ui; +} + +void BeamSteeringCWModGUI::blockApplySettings(bool block) +{ + m_doApplySettings = !block; +} + +void BeamSteeringCWModGUI::applySettings(bool force) +{ + if (m_doApplySettings) + { + setTitleColor(m_channelMarker.getColor()); + + BeamSteeringCWMod::MsgConfigureBeamSteeringCWMod* message = BeamSteeringCWMod::MsgConfigureBeamSteeringCWMod::create(m_settings, force); + m_bsCWSource->getInputMessageQueue()->push(message); + } +} + +void BeamSteeringCWModGUI::displaySettings() +{ + m_channelMarker.blockSignals(true); + m_channelMarker.setCenterFrequency(0); + m_channelMarker.setTitle(m_settings.m_title); + 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 + + setTitleColor(m_settings.m_rgbColor); + setWindowTitle(m_channelMarker.getTitle()); + + blockApplySettings(true); + ui->interpolationFactor->setCurrentIndex(m_settings.m_log2Interp); + applyInterpolation(); + ui->steeringDegreesText->setText(tr("%1").arg(m_settings.m_steerDegrees)); + blockApplySettings(false); +} + +void BeamSteeringCWModGUI::displayRateAndShift() +{ + int shift = m_shiftFrequencyFactor * m_basebandSampleRate; + double channelSampleRate = ((double) m_basebandSampleRate) / (1<offsetFrequencyText->setText(tr("%1 Hz").arg(loc.toString(shift))); + ui->channelRateText->setText(tr("%1k").arg(QString::number(channelSampleRate / 1000.0, 'g', 5))); + m_channelMarker.setCenterFrequency(shift); + m_channelMarker.setBandwidth(channelSampleRate); +} + +void BeamSteeringCWModGUI::leaveEvent(QEvent*) +{ + m_channelMarker.setHighlighted(false); +} + +void BeamSteeringCWModGUI::enterEvent(QEvent*) +{ + m_channelMarker.setHighlighted(true); +} + +void BeamSteeringCWModGUI::handleSourceMessages() +{ + Message* message; + + while ((message = getInputMessageQueue()->pop()) != 0) + { + if (handleMessage(*message)) + { + delete message; + } + } +} + +void BeamSteeringCWModGUI::onWidgetRolled(QWidget* widget, bool rollDown) +{ + (void) widget; + (void) rollDown; +} + +void BeamSteeringCWModGUI::onMenuDialogCalled(const QPoint &p) +{ + if (m_contextMenuType == ContextMenuChannelSettings) + { + BasicChannelSettingsDialog dialog(&m_channelMarker, this); + dialog.setUseReverseAPI(m_settings.m_useReverseAPI); + dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); + dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); + dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex); + dialog.setReverseAPIChannelIndex(m_settings.m_reverseAPIChannelIndex); + + dialog.move(p); + dialog.exec(); + + m_settings.m_rgbColor = m_channelMarker.getColor().rgb(); + m_settings.m_title = m_channelMarker.getTitle(); + m_settings.m_useReverseAPI = dialog.useReverseAPI(); + m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); + m_settings.m_reverseAPIPort = dialog.getReverseAPIPort(); + m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex(); + m_settings.m_reverseAPIChannelIndex = dialog.getReverseAPIChannelIndex(); + + setWindowTitle(m_settings.m_title); + setTitleColor(m_settings.m_rgbColor); + + applySettings(); + } + + resetContextMenuType(); +} + +void BeamSteeringCWModGUI::on_channelOutput_currentIndexChanged(int index) +{ + m_settings.m_channelOutput = index; + applySettings(); +} + +void BeamSteeringCWModGUI::on_interpolationFactor_currentIndexChanged(int index) +{ + m_settings.m_log2Interp = index; + applyInterpolation(); +} + +void BeamSteeringCWModGUI::on_position_valueChanged(int value) +{ + m_settings.m_filterChainHash = value; + applyPosition(); +} + +void BeamSteeringCWModGUI::on_steeringDegrees_valueChanged(int value) +{ + m_settings.m_steerDegrees = value; + ui->steeringDegreesText->setText(tr("%1").arg(m_settings.m_steerDegrees)); + applySettings(); +} + +void BeamSteeringCWModGUI::applyInterpolation() +{ + uint32_t maxHash = 1; + + for (uint32_t i = 0; i < m_settings.m_log2Interp; i++) { + maxHash *= 3; + } + + ui->position->setMaximum(maxHash-1); + ui->position->setValue(m_settings.m_filterChainHash); + m_settings.m_filterChainHash = ui->position->value(); + applyPosition(); +} + +void BeamSteeringCWModGUI::applyPosition() +{ + ui->filterChainIndex->setText(tr("%1").arg(m_settings.m_filterChainHash)); + QString s; + m_shiftFrequencyFactor = HBFilterChainConverter::convertToString(m_settings.m_log2Interp, m_settings.m_filterChainHash, s); + ui->filterChainText->setText(s); + + displayRateAndShift(); + applySettings(); +} + +void BeamSteeringCWModGUI::tick() +{ + if (++m_tickCount == 20) { // once per second + m_tickCount = 0; + } +} diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.h b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.h new file mode 100644 index 000000000..70beabe43 --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.h @@ -0,0 +1,95 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_BEAMSTEERINGCWMODGUI_H_ +#define INCLUDE_BEAMSTEERINGCWMODGUI_H_ + +#include + +#include + +#include "dsp/channelmarker.h" +#include "channel/channelgui.h" +#include "util/messagequeue.h" + +#include "beamsteeringcwmodsettings.h" + +class PluginAPI; +class DeviceUISet; +class BeamSteeringCWMod; +class MIMOChannel; + +namespace Ui { + class BeamSteeringCWModGUI; +} + +class BeamSteeringCWModGUI : public ChannelGUI { + Q_OBJECT +public: + static BeamSteeringCWModGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, MIMOChannel *mimoChannel); + + virtual void destroy(); + virtual void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + +private: + Ui::BeamSteeringCWModGUI* ui; + PluginAPI* m_pluginAPI; + DeviceUISet* m_deviceUISet; + ChannelMarker m_channelMarker; + BeamSteeringCWModSettings m_settings; + int m_basebandSampleRate; + qint64 m_centerFrequency; + double m_shiftFrequencyFactor; //!< Channel frequency shift factor + bool m_doApplySettings; + + BeamSteeringCWMod* m_bsCWSource; + MessageQueue m_inputMessageQueue; + + uint32_t m_tickCount; + + explicit BeamSteeringCWModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, MIMOChannel *mimoChannel, QWidget* parent = nullptr); + virtual ~BeamSteeringCWModGUI(); + + void blockApplySettings(bool block); + void applySettings(bool force = false); + void displaySettings(); + void displayRateAndShift(); + bool handleMessage(const Message& message); + + void leaveEvent(QEvent*); + void enterEvent(QEvent*); + + void applyInterpolation(); + void applyPosition(); + +private slots: + void handleSourceMessages(); + void on_channelOutput_currentIndexChanged(int index); + void on_interpolationFactor_currentIndexChanged(int index); + void on_position_valueChanged(int value); + void on_steeringDegrees_valueChanged(int value); + void onWidgetRolled(QWidget* widget, bool rollDown); + void onMenuDialogCalled(const QPoint& p); + void tick(); +}; + + + +#endif /* INCLUDE_BEAMSTEERINGCWSOURCEGUI_H_ */ diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.ui b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.ui new file mode 100644 index 000000000..a361c589d --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodgui.ui @@ -0,0 +1,342 @@ + + + BeamSteeringCWModGUI + + + + 0 + 0 + 320 + 102 + + + + + 0 + 0 + + + + + 320 + 100 + + + + + 320 + 16777215 + + + + + Liberation Sans + 9 + + + + Beam steering CW source + + + Beam steering CW source + + + + + 10 + 10 + 301 + 91 + + + + Settings + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + 3 + + + + + + + Channel output + + + + A,B + + + + + A + + + + + B + + + + + + + + Int + + + + + + + + 55 + 16777215 + + + + Decimation factor + + + + 1 + + + + + 2 + + + + + 4 + + + + + 8 + + + + + 16 + + + + + 32 + + + + + 64 + + + + + + + + + 50 + 0 + + + + Effective channel rate (kS/s) + + + 0000k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + 0 + + + + Filter chain stages left to right (L: low, C: center, H: high) + + + LLLLLL + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 85 + 0 + + + + Offset frequency with thousands separator (Hz) + + + -9,999,999 Hz + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + 10 + + + + + Pos + + + + + + + Center frequency position + + + 2 + + + 1 + + + Qt::Horizontal + + + + + + + + 24 + 0 + + + + Filter chain hash code + + + 000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Steer + + + + + + + Steering angle vs antennas axis + + + 0 + + + 180 + + + 1 + + + 90 + + + Qt::Horizontal + + + + + + + + 25 + 0 + + + + Steering angle vs antennas axis in degrees + + + 180 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + RollupWidget + QWidget +
gui/rollupwidget.h
+ 1 +
+
+ + + + +
diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodplugin.cpp b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodplugin.cpp new file mode 100644 index 000000000..0364ba77f --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodplugin.cpp @@ -0,0 +1,91 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 "plugin/pluginapi.h" + +#ifndef SERVER_MODE +#include "beamsteeringcwmodgui.h" +#endif +#include "beamsteeringcwmod.h" +#include "beamsteeringcwmodwebapiadapter.h" +#include "beamsteeringcwmodplugin.h" + +const PluginDescriptor BeamSteeringCWModPlugin::m_pluginDescriptor = { + QString(BeamSteeringCWMod::m_channelId), + QString("BeamSteeringCWMod"), + QString("5.13.0"), + QString("(c) Edouard Griffiths, F4EXB"), + QString("https://github.com/f4exb/sdrangel"), + true, + QString("https://github.com/f4exb/sdrangel") +}; + +BeamSteeringCWModPlugin::BeamSteeringCWModPlugin(QObject* parent) : + QObject(parent), + m_pluginAPI(nullptr) +{ +} + +const PluginDescriptor& BeamSteeringCWModPlugin::getPluginDescriptor() const +{ + return m_pluginDescriptor; +} + +void BeamSteeringCWModPlugin::initPlugin(PluginAPI* pluginAPI) +{ + m_pluginAPI = pluginAPI; + + // register channel MIMO + m_pluginAPI->registerMIMOChannel(BeamSteeringCWMod::m_channelIdURI, BeamSteeringCWMod::m_channelId, this); +} + +void BeamSteeringCWModPlugin::createMIMOChannel(DeviceAPI *deviceAPI, MIMOChannel **bs, ChannelAPI **cs) const +{ + if (bs || cs) + { + BeamSteeringCWMod *instance = new BeamSteeringCWMod(deviceAPI); + + if (bs) { + *bs = instance; + } + + if (cs) { + *cs = instance; + } + } +} + +#ifdef SERVER_MODE +ChannelGUI* BeamSteeringCWModPlugin::createMIMOChannelGUI( + DeviceUISet *deviceUISet, + MIMOChannel *mimoChannel) const +{ + return nullptr; +} +#else +ChannelGUI* BeamSteeringCWModPlugin::createMIMOChannelGUI(DeviceUISet *deviceUISet, MIMOChannel *mimoChannel) const +{ + return BeamSteeringCWModGUI::create(m_pluginAPI, deviceUISet, mimoChannel); +} +#endif + +ChannelWebAPIAdapter* BeamSteeringCWModPlugin::createChannelWebAPIAdapter() const +{ + return new BeamSteeringCWModWebAPIAdapter(); +} diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodplugin.h b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodplugin.h new file mode 100644 index 000000000..c366d212e --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodplugin.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_BEAMSTEERINGCWMODPLUGIN_H_ +#define INCLUDE_BEAMSTEERINGCWMODPLUGIN_H_ + + +#include +#include "plugin/plugininterface.h" + +class DeviceUISet; +class MIMOChannel; + +class BeamSteeringCWModPlugin : public QObject, PluginInterface { + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID "sdrangel.channelmimo.beamsteeringcwmod") + +public: + explicit BeamSteeringCWModPlugin(QObject* parent = nullptr); + + const PluginDescriptor& getPluginDescriptor() const; + void initPlugin(PluginAPI* pluginAPI); + + virtual void createMIMOChannel(DeviceAPI *deviceAPI, MIMOChannel **bs, ChannelAPI **cs) const; + virtual ChannelGUI* createMIMOChannelGUI(DeviceUISet *deviceUISet, MIMOChannel *mimoChannel) const; + virtual ChannelWebAPIAdapter* createChannelWebAPIAdapter() const; + +private: + static const PluginDescriptor m_pluginDescriptor; + + PluginAPI* m_pluginAPI; +}; + +#endif /* INCLUDE_BEAMSTEERINGCWMODPLUGIN_H_ */ diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsettings.cpp b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsettings.cpp new file mode 100644 index 000000000..6b20efe1d --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsettings.cpp @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 "beamsteeringcwmodsettings.h" + +#include + +#include "util/simpleserializer.h" +#include "settings/serializable.h" + + +BeamSteeringCWModSettings::BeamSteeringCWModSettings() +{ + resetToDefaults(); +} + +void BeamSteeringCWModSettings::resetToDefaults() +{ + m_steerDegrees = 90; + m_rgbColor = QColor(140, 4, 4).rgb(); + m_title = "Beam Steering CW Modulator"; + m_log2Interp = 0; + m_filterChainHash = 0; + m_channelOutput = 0; + m_channelMarker = nullptr; + m_useReverseAPI = false; + m_reverseAPIAddress = "127.0.0.1"; + m_reverseAPIPort = 8888; + m_reverseAPIDeviceIndex = 0; + m_reverseAPIChannelIndex = 0; +} + +QByteArray BeamSteeringCWModSettings::serialize() const +{ + SimpleSerializer s(1); + s.writeS32(1, m_steerDegrees); + s.writeU32(5, m_rgbColor); + s.writeString(6, m_title); + s.writeBool(7, m_useReverseAPI); + s.writeString(8, m_reverseAPIAddress); + s.writeU32(9, m_reverseAPIPort); + s.writeU32(10, m_reverseAPIDeviceIndex); + s.writeU32(11, m_reverseAPIChannelIndex); + s.writeU32(12, m_log2Interp); + s.writeU32(13, m_filterChainHash); + s.writeS32(14, m_channelOutput); + + return s.final(); +} + +bool BeamSteeringCWModSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if(!d.isValid()) + { + resetToDefaults(); + return false; + } + + if(d.getVersion() == 1) + { + uint32_t tmp; + int stmp; + QString strtmp; + + d.readS32(1, &stmp, 90); + m_steerDegrees = stmp < 0 ? -0 : stmp > 180 ? 180 : stmp; + d.readU32(5, &m_rgbColor, QColor(0, 255, 255).rgb()); + d.readString(6, &m_title, "Local sink"); + d.readBool(7, &m_useReverseAPI, false); + d.readString(8, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(9, &tmp, 0); + + if ((tmp > 1023) && (tmp < 65535)) { + m_reverseAPIPort = tmp; + } else { + m_reverseAPIPort = 8888; + } + + d.readU32(10, &tmp, 0); + m_reverseAPIDeviceIndex = tmp > 99 ? 99 : tmp; + d.readU32(11, &tmp, 0); + m_reverseAPIChannelIndex = tmp > 99 ? 99 : tmp; + d.readU32(12, &tmp, 0); + m_log2Interp = tmp > 6 ? 6 : tmp; + d.readU32(13, &m_filterChainHash, 0); + d.readS32(14, &stmp, 0); + m_channelOutput = tmp < 0 ? 0 : tmp > 2 ? 2 : tmp; + + return true; + } + else + { + resetToDefaults(); + return false; + } +} + + + + + diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsettings.h b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsettings.h new file mode 100644 index 000000000..6adbc27c0 --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsettings.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_BEAMSTEERINGCWMODSETTINGS_H_ +#define INCLUDE_BEAMSTEERINGCWMODSETTINGS_H_ + +#include +#include + +class Serializable; + +struct BeamSteeringCWModSettings +{ + int m_steerDegrees; + quint32 m_rgbColor; + QString m_title; + uint32_t m_log2Interp; + uint32_t m_filterChainHash; + int m_channelOutput; //!< 0: 1&2, 1: 1, 2: 2 + bool m_useReverseAPI; + QString m_reverseAPIAddress; + uint16_t m_reverseAPIPort; + uint16_t m_reverseAPIDeviceIndex; + uint16_t m_reverseAPIChannelIndex; + + Serializable *m_channelMarker; + + BeamSteeringCWModSettings(); + void resetToDefaults(); + void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; } + QByteArray serialize() const; + bool deserialize(const QByteArray& data); +}; + +#endif /* INCLUDE_BEAMSTEERINGCWMODSETTINGS_H_ */ diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.cpp b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.cpp new file mode 100644 index 000000000..3d232d06e --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.cpp @@ -0,0 +1,67 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 "dsp/dsptypes.h" +#include "beamsteeringcwmodstreamsource.h" + +BeamSteeringCWModStreamSource::BeamSteeringCWModStreamSource() : + m_amp(SDR_TX_SCALEF/sqrt(2.0f)), + m_phase(0) +{ + m_real = m_amp; + m_imag = 0.0f; +} + +BeamSteeringCWModStreamSource::~BeamSteeringCWModStreamSource() +{} + +void BeamSteeringCWModStreamSource::muteChannel(bool mute) +{ + if (mute) + { + m_real = 0; + m_imag = 0; + } + else + { + setPhase(m_phase); + } +} + +void BeamSteeringCWModStreamSource::setPhase(float phase) +{ + float normPhase = phase < -M_PI ? -M_PI : phase > M_PI ? M_PI : phase; + m_real = m_amp * cos(normPhase); + m_imag = m_amp * sin(normPhase); + m_phase = phase; +} + +void BeamSteeringCWModStreamSource::pull(SampleVector::iterator begin, unsigned int nbSamples) +{ + std::fill(begin, begin + nbSamples, Sample{m_real, m_imag}); +} + +void BeamSteeringCWModStreamSource::pullOne(Sample& sample) +{ + sample.setReal(m_real); + sample.setImag(m_imag); +} + +void BeamSteeringCWModStreamSource::reset() +{} diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.h b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.h new file mode 100644 index 000000000..d189a4064 --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodstreamsource.h @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_BEAMSTEERINGCWMODSTREAMSOURCE_H +#define INCLUDE_BEAMSTEERINGCWMODSTREAMSOURCE_H + +#include "dsp/channelsamplesource.h" + +class BeamSteeringCWModStreamSource : public ChannelSampleSource +{ +public: + BeamSteeringCWModStreamSource(); + virtual ~BeamSteeringCWModStreamSource(); + + 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); + unsigned int getStreamIndex() const { return m_streamIndex; } + void setStreamIndex(unsigned int streamIndex) { m_streamIndex = streamIndex; } + void muteChannel(bool mute); + +private: + unsigned int m_streamIndex; + float m_amp; + float m_phase; + FixReal m_real; + FixReal m_imag; +}; + +#endif // INCLUDE_BEAMSTEERINGCWMODSTREAMSOURCE_H diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodwebapiadapter.cpp b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodwebapiadapter.cpp new file mode 100644 index 000000000..faf74b1da --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodwebapiadapter.cpp @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 "SWGChannelSettings.h" +#include "beamsteeringcwmod.h" +#include "beamsteeringcwmodwebapiadapter.h" + +BeamSteeringCWModWebAPIAdapter::BeamSteeringCWModWebAPIAdapter() +{} + +BeamSteeringCWModWebAPIAdapter::~BeamSteeringCWModWebAPIAdapter() +{} + +int BeamSteeringCWModWebAPIAdapter::webapiSettingsGet( + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setBeamSteeringCwModSettings(new SWGSDRangel::SWGBeamSteeringCWModSettings()); + response.getBeamSteeringCwModSettings()->init(); + BeamSteeringCWMod::webapiFormatChannelSettings(response, m_settings); + + return 200; +} + +int BeamSteeringCWModWebAPIAdapter::webapiSettingsPutPatch( + bool force, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + BeamSteeringCWMod::webapiUpdateChannelSettings(m_settings, channelSettingsKeys, response); + + return 200; +} diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodwebapiadapter.h b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodwebapiadapter.h new file mode 100644 index 000000000..6844c0900 --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodwebapiadapter.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_BEAMSTEERINGCWMO_WEBAPIADAPTER_H +#define INCLUDE_BEAMSTEERINGCWMO_WEBAPIADAPTER_H + +#include "channel/channelwebapiadapter.h" +#include "beamsteeringcwmodsettings.h" + +/** + * Standalone API adapter only for the settings + */ +class BeamSteeringCWModWebAPIAdapter : public ChannelWebAPIAdapter { +public: + BeamSteeringCWModWebAPIAdapter(); + virtual ~BeamSteeringCWModWebAPIAdapter(); + + virtual QByteArray serialize() const { return m_settings.serialize(); } + virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); } + + virtual int webapiSettingsGet( + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage); + +private: + BeamSteeringCWModSettings m_settings; +}; + +#endif // INCLUDE_BEAMSTEERINGCWMO_WEBAPIADAPTER_H diff --git a/plugins/channelmimo/beamsteeringcwmod/readme.md b/plugins/channelmimo/beamsteeringcwmod/readme.md new file mode 100644 index 000000000..193e91d4d --- /dev/null +++ b/plugins/channelmimo/beamsteeringcwmod/readme.md @@ -0,0 +1,56 @@ +

Beam Steering Continuous Wave plugin

+ +

Introduction

+ +This is a v5 only plugin. + +This MIMO transmission only (MO) plugin can be used to drive a 2 channel MO device in order to produce a continuous wave signal (CW) with a control of hte phase between the two streams. When the MO device is connected to a two antenna system the resulting beam can be steered in direction using the phase difference. Control is made directly in angle units. + +; This was designed more as a proof of concept of multiple output plugin rather than something really useful. + +

Interface

+ +![Beam steering CW plugin GUI](../../../doc/img/BeamsteeringCWMod_plugin.png) + +

1: Channel output

+ +The two channels A and B are connected to device output streams 0 and 1 respectively. The device must expose these channels. + +Use this combo box to select channel output: + - **A,B**: output A and B channels + - **A**: output A channel only + - **B**: output B channel only + +

2: Interpolation factor

+ +The channel sample rate is interpolated by a power of two to feed the channels at baseband sample rate. + +

3: Channel sample rate

+ +This is the channel sample rate in kilo or mega samples per second indicated by the `k` or `M` letter. + +

4: Half-band filter chain sequence display

+ +This string represents the sequence of half-band filters used in the interpolation from channel to device baseband. Each character represents a filter type: + + - **L**: lower half-band + - **H**: higher half-band + - **C**: centered + +

5: Center frequency shift

+ +This is the shift of the channel center frequency from the device center frequency. Its value is driven by the baseband sample rate, the interpolation factor (2) and the filter chain sequence (4). + +

6: Half-band filter chain sequence adjust

+ +The slider moves the channel center frequency roughly from the lower to the higher frequency in the device baseband. The number on the right represents the filter sequence as the decimal value of a base 3 number. Each base 3 digit represents the filter type and its sequence from MSB to LSB in the filter chain: + + - **0**: lower half-band + - **1**: centered + - **2**: higher half-band + +

7: Steering angle

+ +This slider controls the beam steering angle θ in degrees when the configuration of antennas is made like this: + +![Beam steering CW plugin GUI](../../../doc/img/beamsteeringcw_angle.png) \ No newline at end of file diff --git a/sdrbase/resources/webapi.qrc b/sdrbase/resources/webapi.qrc index e13023d3a..f26f1ee60 100644 --- a/sdrbase/resources/webapi.qrc +++ b/sdrbase/resources/webapi.qrc @@ -10,6 +10,7 @@ webapi/doc/swagger/include/AMMod.yaml webapi/doc/swagger/include/ATVDemod.yaml webapi/doc/swagger/include/ATVMod.yaml + webapi/doc/swagger/include/BeamSteeringCWMod.yaml webapi/doc/swagger/include/BFMDemod.yaml webapi/doc/swagger/include/BladeRF1.yaml webapi/doc/swagger/include/BladeRF2.yaml diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 7d1698367..a26c78484 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -1771,6 +1771,42 @@ margin-bottom: 20px; } }, "description" : "A bandwidth expressed in Hertz (Hz)" +}; + defs.BeamSteeringCWModSettings = { + "properties" : { + "steerDegrees" : { + "type" : "integer" + }, + "rgbColor" : { + "type" : "integer" + }, + "title" : { + "type" : "string" + }, + "log2Interp" : { + "type" : "integer" + }, + "filterChainHash" : { + "type" : "integer" + }, + "useReverseAPI" : { + "type" : "integer", + "description" : "Synchronize with reverse API (1 for yes, 0 for no)" + }, + "reverseAPIAddress" : { + "type" : "string" + }, + "reverseAPIPort" : { + "type" : "integer" + }, + "reverseAPIDeviceIndex" : { + "type" : "integer" + }, + "reverseAPIChannelIndex" : { + "type" : "integer" + } + }, + "description" : "BeamSteeringCWMod" }; defs.BladeRF1InputSettings = { "properties" : { @@ -2548,6 +2584,9 @@ margin-bottom: 20px; "ATVModSettings" : { "$ref" : "#/definitions/ATVModSettings" }, + "BeamSteeringCWModSettings" : { + "$ref" : "#/definitions/BeamSteeringCWModSettings" + }, "BFMDemodSettings" : { "$ref" : "#/definitions/BFMDemodSettings" }, @@ -41110,7 +41149,7 @@ except ApiException as e:
- Generated 2020-11-10T19:50:40.958+01:00 + Generated 2020-11-10T21:31:22.328+01:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/BeamSteeringCWMod.yaml b/sdrbase/resources/webapi/doc/swagger/include/BeamSteeringCWMod.yaml new file mode 100644 index 000000000..dfa50c861 --- /dev/null +++ b/sdrbase/resources/webapi/doc/swagger/include/BeamSteeringCWMod.yaml @@ -0,0 +1,24 @@ +BeamSteeringCWModSettings: + description: BeamSteeringCWMod + properties: + steerDegrees: + type: integer + rgbColor: + type: integer + title: + type: string + log2Interp: + type: integer + filterChainHash: + type: integer + useReverseAPI: + description: Synchronize with reverse API (1 for yes, 0 for no) + type: integer + reverseAPIAddress: + type: string + reverseAPIPort: + type: integer + reverseAPIDeviceIndex: + type: integer + reverseAPIChannelIndex: + type: integer diff --git a/sdrbase/resources/webapi/doc/swagger/include/ChannelSettings.yaml b/sdrbase/resources/webapi/doc/swagger/include/ChannelSettings.yaml index 312101552..f93b6d694 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/ChannelSettings.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/ChannelSettings.yaml @@ -27,6 +27,8 @@ ChannelSettings: $ref: "/doc/swagger/include/ATVDemod.yaml#/ATVDemodSettings" ATVModSettings: $ref: "/doc/swagger/include/ATVMod.yaml#/ATVModSettings" + BeamSteeringCWModSettings: + $ref: "/doc/swagger/include/BeamSteeringCWMod.yaml#/BeamSteeringCWModSettings" BFMDemodSettings: $ref: "/doc/swagger/include/BFMDemod.yaml#/BFMDemodSettings" ChannelAnalyzerSettings: diff --git a/sdrbase/webapi/webapirequestmapper.cpp b/sdrbase/webapi/webapirequestmapper.cpp index a92e9ac84..40e86e28b 100644 --- a/sdrbase/webapi/webapirequestmapper.cpp +++ b/sdrbase/webapi/webapirequestmapper.cpp @@ -3550,6 +3550,11 @@ bool WebAPIRequestMapper::getChannelSettings( channelSettings->setAtvModSettings(new SWGSDRangel::SWGATVModSettings()); channelSettings->getAtvModSettings()->fromJsonObject(settingsJsonObject); } + else if (channelSettingsKey == "BeamSteeringCWModSettings") + { + channelSettings->setBeamSteeringCwModSettings(new SWGSDRangel::SWGBeamSteeringCWModSettings()); + channelSettings->getBeamSteeringCwModSettings()->fromJsonObject(settingsJsonObject); + } else if (channelSettingsKey == "BFMDemodSettings") { channelSettings->setBfmDemodSettings(new SWGSDRangel::SWGBFMDemodSettings()); diff --git a/swagger/sdrangel/api/swagger/include/BeamSteeringCWMod.yaml b/swagger/sdrangel/api/swagger/include/BeamSteeringCWMod.yaml new file mode 100644 index 000000000..dfa50c861 --- /dev/null +++ b/swagger/sdrangel/api/swagger/include/BeamSteeringCWMod.yaml @@ -0,0 +1,24 @@ +BeamSteeringCWModSettings: + description: BeamSteeringCWMod + properties: + steerDegrees: + type: integer + rgbColor: + type: integer + title: + type: string + log2Interp: + type: integer + filterChainHash: + type: integer + useReverseAPI: + description: Synchronize with reverse API (1 for yes, 0 for no) + type: integer + reverseAPIAddress: + type: string + reverseAPIPort: + type: integer + reverseAPIDeviceIndex: + type: integer + reverseAPIChannelIndex: + type: integer diff --git a/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml b/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml index a613062c2..988a60704 100644 --- a/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml +++ b/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml @@ -27,6 +27,8 @@ ChannelSettings: $ref: "http://swgserver:8081/api/swagger/include/ATVDemod.yaml#/ATVDemodSettings" ATVModSettings: $ref: "http://swgserver:8081/api/swagger/include/ATVMod.yaml#/ATVModSettings" + BeamSteeringCWModSettings: + $ref: "http://swgserver:8081/api/swagger/include/BeamSteeringCWMod.yaml#/BeamSteeringCWModSettings" BFMDemodSettings: $ref: "http://swgserver:8081/api/swagger/include/BFMDemod.yaml#/BFMDemodSettings" ChannelAnalyzerSettings: diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 7d1698367..a26c78484 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -1771,6 +1771,42 @@ margin-bottom: 20px; } }, "description" : "A bandwidth expressed in Hertz (Hz)" +}; + defs.BeamSteeringCWModSettings = { + "properties" : { + "steerDegrees" : { + "type" : "integer" + }, + "rgbColor" : { + "type" : "integer" + }, + "title" : { + "type" : "string" + }, + "log2Interp" : { + "type" : "integer" + }, + "filterChainHash" : { + "type" : "integer" + }, + "useReverseAPI" : { + "type" : "integer", + "description" : "Synchronize with reverse API (1 for yes, 0 for no)" + }, + "reverseAPIAddress" : { + "type" : "string" + }, + "reverseAPIPort" : { + "type" : "integer" + }, + "reverseAPIDeviceIndex" : { + "type" : "integer" + }, + "reverseAPIChannelIndex" : { + "type" : "integer" + } + }, + "description" : "BeamSteeringCWMod" }; defs.BladeRF1InputSettings = { "properties" : { @@ -2548,6 +2584,9 @@ margin-bottom: 20px; "ATVModSettings" : { "$ref" : "#/definitions/ATVModSettings" }, + "BeamSteeringCWModSettings" : { + "$ref" : "#/definitions/BeamSteeringCWModSettings" + }, "BFMDemodSettings" : { "$ref" : "#/definitions/BFMDemodSettings" }, @@ -41110,7 +41149,7 @@ except ApiException as e:
- Generated 2020-11-10T19:50:40.958+01:00 + Generated 2020-11-10T21:31:22.328+01:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGBeamSteeringCWModSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGBeamSteeringCWModSettings.cpp new file mode 100644 index 000000000..ea7dc0712 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGBeamSteeringCWModSettings.cpp @@ -0,0 +1,319 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1, USRP and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 4.15.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGBeamSteeringCWModSettings.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGBeamSteeringCWModSettings::SWGBeamSteeringCWModSettings(QString* json) { + init(); + this->fromJson(*json); +} + +SWGBeamSteeringCWModSettings::SWGBeamSteeringCWModSettings() { + steer_degrees = 0; + m_steer_degrees_isSet = false; + rgb_color = 0; + m_rgb_color_isSet = false; + title = nullptr; + m_title_isSet = false; + log2_interp = 0; + m_log2_interp_isSet = false; + filter_chain_hash = 0; + m_filter_chain_hash_isSet = false; + use_reverse_api = 0; + m_use_reverse_api_isSet = false; + reverse_api_address = nullptr; + m_reverse_api_address_isSet = false; + reverse_api_port = 0; + m_reverse_api_port_isSet = false; + reverse_api_device_index = 0; + m_reverse_api_device_index_isSet = false; + reverse_api_channel_index = 0; + m_reverse_api_channel_index_isSet = false; +} + +SWGBeamSteeringCWModSettings::~SWGBeamSteeringCWModSettings() { + this->cleanup(); +} + +void +SWGBeamSteeringCWModSettings::init() { + steer_degrees = 0; + m_steer_degrees_isSet = false; + rgb_color = 0; + m_rgb_color_isSet = false; + title = new QString(""); + m_title_isSet = false; + log2_interp = 0; + m_log2_interp_isSet = false; + filter_chain_hash = 0; + m_filter_chain_hash_isSet = false; + use_reverse_api = 0; + m_use_reverse_api_isSet = false; + reverse_api_address = new QString(""); + m_reverse_api_address_isSet = false; + reverse_api_port = 0; + m_reverse_api_port_isSet = false; + reverse_api_device_index = 0; + m_reverse_api_device_index_isSet = false; + reverse_api_channel_index = 0; + m_reverse_api_channel_index_isSet = false; +} + +void +SWGBeamSteeringCWModSettings::cleanup() { + + + if(title != nullptr) { + delete title; + } + + + + if(reverse_api_address != nullptr) { + delete reverse_api_address; + } + + + +} + +SWGBeamSteeringCWModSettings* +SWGBeamSteeringCWModSettings::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGBeamSteeringCWModSettings::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&steer_degrees, pJson["steerDegrees"], "qint32", ""); + + ::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", ""); + + ::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString"); + + ::SWGSDRangel::setValue(&log2_interp, pJson["log2Interp"], "qint32", ""); + + ::SWGSDRangel::setValue(&filter_chain_hash, pJson["filterChainHash"], "qint32", ""); + + ::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString"); + + ::SWGSDRangel::setValue(&reverse_api_port, pJson["reverseAPIPort"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_device_index, pJson["reverseAPIDeviceIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_channel_index, pJson["reverseAPIChannelIndex"], "qint32", ""); + +} + +QString +SWGBeamSteeringCWModSettings::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGBeamSteeringCWModSettings::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_steer_degrees_isSet){ + obj->insert("steerDegrees", QJsonValue(steer_degrees)); + } + if(m_rgb_color_isSet){ + obj->insert("rgbColor", QJsonValue(rgb_color)); + } + if(title != nullptr && *title != QString("")){ + toJsonValue(QString("title"), title, obj, QString("QString")); + } + if(m_log2_interp_isSet){ + obj->insert("log2Interp", QJsonValue(log2_interp)); + } + if(m_filter_chain_hash_isSet){ + obj->insert("filterChainHash", QJsonValue(filter_chain_hash)); + } + if(m_use_reverse_api_isSet){ + obj->insert("useReverseAPI", QJsonValue(use_reverse_api)); + } + if(reverse_api_address != nullptr && *reverse_api_address != QString("")){ + toJsonValue(QString("reverseAPIAddress"), reverse_api_address, obj, QString("QString")); + } + if(m_reverse_api_port_isSet){ + obj->insert("reverseAPIPort", QJsonValue(reverse_api_port)); + } + if(m_reverse_api_device_index_isSet){ + obj->insert("reverseAPIDeviceIndex", QJsonValue(reverse_api_device_index)); + } + if(m_reverse_api_channel_index_isSet){ + obj->insert("reverseAPIChannelIndex", QJsonValue(reverse_api_channel_index)); + } + + return obj; +} + +qint32 +SWGBeamSteeringCWModSettings::getSteerDegrees() { + return steer_degrees; +} +void +SWGBeamSteeringCWModSettings::setSteerDegrees(qint32 steer_degrees) { + this->steer_degrees = steer_degrees; + this->m_steer_degrees_isSet = true; +} + +qint32 +SWGBeamSteeringCWModSettings::getRgbColor() { + return rgb_color; +} +void +SWGBeamSteeringCWModSettings::setRgbColor(qint32 rgb_color) { + this->rgb_color = rgb_color; + this->m_rgb_color_isSet = true; +} + +QString* +SWGBeamSteeringCWModSettings::getTitle() { + return title; +} +void +SWGBeamSteeringCWModSettings::setTitle(QString* title) { + this->title = title; + this->m_title_isSet = true; +} + +qint32 +SWGBeamSteeringCWModSettings::getLog2Interp() { + return log2_interp; +} +void +SWGBeamSteeringCWModSettings::setLog2Interp(qint32 log2_interp) { + this->log2_interp = log2_interp; + this->m_log2_interp_isSet = true; +} + +qint32 +SWGBeamSteeringCWModSettings::getFilterChainHash() { + return filter_chain_hash; +} +void +SWGBeamSteeringCWModSettings::setFilterChainHash(qint32 filter_chain_hash) { + this->filter_chain_hash = filter_chain_hash; + this->m_filter_chain_hash_isSet = true; +} + +qint32 +SWGBeamSteeringCWModSettings::getUseReverseApi() { + return use_reverse_api; +} +void +SWGBeamSteeringCWModSettings::setUseReverseApi(qint32 use_reverse_api) { + this->use_reverse_api = use_reverse_api; + this->m_use_reverse_api_isSet = true; +} + +QString* +SWGBeamSteeringCWModSettings::getReverseApiAddress() { + return reverse_api_address; +} +void +SWGBeamSteeringCWModSettings::setReverseApiAddress(QString* reverse_api_address) { + this->reverse_api_address = reverse_api_address; + this->m_reverse_api_address_isSet = true; +} + +qint32 +SWGBeamSteeringCWModSettings::getReverseApiPort() { + return reverse_api_port; +} +void +SWGBeamSteeringCWModSettings::setReverseApiPort(qint32 reverse_api_port) { + this->reverse_api_port = reverse_api_port; + this->m_reverse_api_port_isSet = true; +} + +qint32 +SWGBeamSteeringCWModSettings::getReverseApiDeviceIndex() { + return reverse_api_device_index; +} +void +SWGBeamSteeringCWModSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) { + this->reverse_api_device_index = reverse_api_device_index; + this->m_reverse_api_device_index_isSet = true; +} + +qint32 +SWGBeamSteeringCWModSettings::getReverseApiChannelIndex() { + return reverse_api_channel_index; +} +void +SWGBeamSteeringCWModSettings::setReverseApiChannelIndex(qint32 reverse_api_channel_index) { + this->reverse_api_channel_index = reverse_api_channel_index; + this->m_reverse_api_channel_index_isSet = true; +} + + +bool +SWGBeamSteeringCWModSettings::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_steer_degrees_isSet){ + isObjectUpdated = true; break; + } + if(m_rgb_color_isSet){ + isObjectUpdated = true; break; + } + if(title && *title != QString("")){ + isObjectUpdated = true; break; + } + if(m_log2_interp_isSet){ + isObjectUpdated = true; break; + } + if(m_filter_chain_hash_isSet){ + isObjectUpdated = true; break; + } + if(m_use_reverse_api_isSet){ + isObjectUpdated = true; break; + } + if(reverse_api_address && *reverse_api_address != QString("")){ + isObjectUpdated = true; break; + } + if(m_reverse_api_port_isSet){ + isObjectUpdated = true; break; + } + if(m_reverse_api_device_index_isSet){ + isObjectUpdated = true; break; + } + if(m_reverse_api_channel_index_isSet){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGBeamSteeringCWModSettings.h b/swagger/sdrangel/code/qt5/client/SWGBeamSteeringCWModSettings.h new file mode 100644 index 000000000..d71aa9fde --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGBeamSteeringCWModSettings.h @@ -0,0 +1,113 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1, USRP and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 4.15.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGBeamSteeringCWModSettings.h + * + * BeamSteeringCWMod + */ + +#ifndef SWGBeamSteeringCWModSettings_H_ +#define SWGBeamSteeringCWModSettings_H_ + +#include + + +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGBeamSteeringCWModSettings: public SWGObject { +public: + SWGBeamSteeringCWModSettings(); + SWGBeamSteeringCWModSettings(QString* json); + virtual ~SWGBeamSteeringCWModSettings(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGBeamSteeringCWModSettings* fromJson(QString &jsonString) override; + + qint32 getSteerDegrees(); + void setSteerDegrees(qint32 steer_degrees); + + qint32 getRgbColor(); + void setRgbColor(qint32 rgb_color); + + QString* getTitle(); + void setTitle(QString* title); + + qint32 getLog2Interp(); + void setLog2Interp(qint32 log2_interp); + + qint32 getFilterChainHash(); + void setFilterChainHash(qint32 filter_chain_hash); + + qint32 getUseReverseApi(); + void setUseReverseApi(qint32 use_reverse_api); + + QString* getReverseApiAddress(); + void setReverseApiAddress(QString* reverse_api_address); + + qint32 getReverseApiPort(); + void setReverseApiPort(qint32 reverse_api_port); + + qint32 getReverseApiDeviceIndex(); + void setReverseApiDeviceIndex(qint32 reverse_api_device_index); + + qint32 getReverseApiChannelIndex(); + void setReverseApiChannelIndex(qint32 reverse_api_channel_index); + + + virtual bool isSet() override; + +private: + qint32 steer_degrees; + bool m_steer_degrees_isSet; + + qint32 rgb_color; + bool m_rgb_color_isSet; + + QString* title; + bool m_title_isSet; + + qint32 log2_interp; + bool m_log2_interp_isSet; + + qint32 filter_chain_hash; + bool m_filter_chain_hash_isSet; + + qint32 use_reverse_api; + bool m_use_reverse_api_isSet; + + QString* reverse_api_address; + bool m_reverse_api_address_isSet; + + qint32 reverse_api_port; + bool m_reverse_api_port_isSet; + + qint32 reverse_api_device_index; + bool m_reverse_api_device_index_isSet; + + qint32 reverse_api_channel_index; + bool m_reverse_api_channel_index_isSet; + +}; + +} + +#endif /* SWGBeamSteeringCWModSettings_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp index 2c791eed1..0c0872050 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp @@ -46,6 +46,8 @@ SWGChannelSettings::SWGChannelSettings() { m_atv_demod_settings_isSet = false; atv_mod_settings = nullptr; m_atv_mod_settings_isSet = false; + beam_steering_cw_mod_settings = nullptr; + m_beam_steering_cw_mod_settings_isSet = false; bfm_demod_settings = nullptr; m_bfm_demod_settings_isSet = false; channel_analyzer_settings = nullptr; @@ -126,6 +128,8 @@ SWGChannelSettings::init() { m_atv_demod_settings_isSet = false; atv_mod_settings = new SWGATVModSettings(); m_atv_mod_settings_isSet = false; + beam_steering_cw_mod_settings = new SWGBeamSteeringCWModSettings(); + m_beam_steering_cw_mod_settings_isSet = false; bfm_demod_settings = new SWGBFMDemodSettings(); m_bfm_demod_settings_isSet = false; channel_analyzer_settings = new SWGChannelAnalyzerSettings(); @@ -205,6 +209,9 @@ SWGChannelSettings::cleanup() { if(atv_mod_settings != nullptr) { delete atv_mod_settings; } + if(beam_steering_cw_mod_settings != nullptr) { + delete beam_steering_cw_mod_settings; + } if(bfm_demod_settings != nullptr) { delete bfm_demod_settings; } @@ -317,6 +324,8 @@ SWGChannelSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&atv_mod_settings, pJson["ATVModSettings"], "SWGATVModSettings", "SWGATVModSettings"); + ::SWGSDRangel::setValue(&beam_steering_cw_mod_settings, pJson["BeamSteeringCWModSettings"], "SWGBeamSteeringCWModSettings", "SWGBeamSteeringCWModSettings"); + ::SWGSDRangel::setValue(&bfm_demod_settings, pJson["BFMDemodSettings"], "SWGBFMDemodSettings", "SWGBFMDemodSettings"); ::SWGSDRangel::setValue(&channel_analyzer_settings, pJson["ChannelAnalyzerSettings"], "SWGChannelAnalyzerSettings", "SWGChannelAnalyzerSettings"); @@ -414,6 +423,9 @@ SWGChannelSettings::asJsonObject() { if((atv_mod_settings != nullptr) && (atv_mod_settings->isSet())){ toJsonValue(QString("ATVModSettings"), atv_mod_settings, obj, QString("SWGATVModSettings")); } + if((beam_steering_cw_mod_settings != nullptr) && (beam_steering_cw_mod_settings->isSet())){ + toJsonValue(QString("BeamSteeringCWModSettings"), beam_steering_cw_mod_settings, obj, QString("SWGBeamSteeringCWModSettings")); + } if((bfm_demod_settings != nullptr) && (bfm_demod_settings->isSet())){ toJsonValue(QString("BFMDemodSettings"), bfm_demod_settings, obj, QString("SWGBFMDemodSettings")); } @@ -589,6 +601,16 @@ SWGChannelSettings::setAtvModSettings(SWGATVModSettings* atv_mod_settings) { this->m_atv_mod_settings_isSet = true; } +SWGBeamSteeringCWModSettings* +SWGChannelSettings::getBeamSteeringCwModSettings() { + return beam_steering_cw_mod_settings; +} +void +SWGChannelSettings::setBeamSteeringCwModSettings(SWGBeamSteeringCWModSettings* beam_steering_cw_mod_settings) { + this->beam_steering_cw_mod_settings = beam_steering_cw_mod_settings; + this->m_beam_steering_cw_mod_settings_isSet = true; +} + SWGBFMDemodSettings* SWGChannelSettings::getBfmDemodSettings() { return bfm_demod_settings; @@ -891,6 +913,9 @@ SWGChannelSettings::isSet(){ if(atv_mod_settings && atv_mod_settings->isSet()){ isObjectUpdated = true; break; } + if(beam_steering_cw_mod_settings && beam_steering_cw_mod_settings->isSet()){ + isObjectUpdated = true; break; + } if(bfm_demod_settings && bfm_demod_settings->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h index 5c9e8cb4e..20ac71dd6 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h @@ -28,6 +28,7 @@ #include "SWGATVDemodSettings.h" #include "SWGATVModSettings.h" #include "SWGBFMDemodSettings.h" +#include "SWGBeamSteeringCWModSettings.h" #include "SWGChannelAnalyzerSettings.h" #include "SWGChirpChatDemodSettings.h" #include "SWGChirpChatModSettings.h" @@ -101,6 +102,9 @@ public: SWGATVModSettings* getAtvModSettings(); void setAtvModSettings(SWGATVModSettings* atv_mod_settings); + SWGBeamSteeringCWModSettings* getBeamSteeringCwModSettings(); + void setBeamSteeringCwModSettings(SWGBeamSteeringCWModSettings* beam_steering_cw_mod_settings); + SWGBFMDemodSettings* getBfmDemodSettings(); void setBfmDemodSettings(SWGBFMDemodSettings* bfm_demod_settings); @@ -213,6 +217,9 @@ private: SWGATVModSettings* atv_mod_settings; bool m_atv_mod_settings_isSet; + SWGBeamSteeringCWModSettings* beam_steering_cw_mod_settings; + bool m_beam_steering_cw_mod_settings_isSet; + SWGBFMDemodSettings* bfm_demod_settings; bool m_bfm_demod_settings_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h index d4469a4d4..c821bfdfa 100644 --- a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h +++ b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h @@ -41,6 +41,7 @@ #include "SWGBFMDemodReport.h" #include "SWGBFMDemodSettings.h" #include "SWGBandwidth.h" +#include "SWGBeamSteeringCWModSettings.h" #include "SWGBladeRF1InputSettings.h" #include "SWGBladeRF1OutputSettings.h" #include "SWGBladeRF2InputReport.h" @@ -307,6 +308,9 @@ namespace SWGSDRangel { if(QString("SWGBandwidth").compare(type) == 0) { return new SWGBandwidth(); } + if(QString("SWGBeamSteeringCWModSettings").compare(type) == 0) { + return new SWGBeamSteeringCWModSettings(); + } if(QString("SWGBladeRF1InputSettings").compare(type) == 0) { return new SWGBladeRF1InputSettings(); }