From 672c0b8a5bea7a90392452a9028522e05ceae00e Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 1 May 2021 09:50:51 +0200 Subject: [PATCH] PlutoSDR MIMO: base implementation --- devices/plutosdr/deviceplutosdrbox.cpp | 126 +- devices/plutosdr/deviceplutosdrbox.h | 13 +- plugins/samplemimo/CMakeLists.txt | 4 + .../samplemimo/plutosdrmimo/CMakeLists.txt | 66 + .../samplemimo/plutosdrmimo/plutosdrmimo.cpp | 1496 +++++++++++++++++ .../samplemimo/plutosdrmimo/plutosdrmimo.h | 200 +++ .../plutosdrmimo/plutosdrmimogui.cpp | 848 ++++++++++ .../samplemimo/plutosdrmimo/plutosdrmimogui.h | 120 ++ .../plutosdrmimo/plutosdrmimogui.ui | 1283 ++++++++++++++ .../plutosdrmimo/plutosdrmimoplugin.cpp | 142 ++ .../plutosdrmimo/plutosdrmimoplugin.h | 53 + .../plutosdrmimo/plutosdrmimosettings.cpp | 369 ++++ .../plutosdrmimo/plutosdrmimosettings.h | 136 ++ .../plutosdrmimowebapiadapter.cpp | 51 + .../plutosdrmimo/plutosdrmimowebapiadapter.h | 49 + .../plutosdrmimo/plutosdrmithread.cpp | 358 ++++ .../plutosdrmimo/plutosdrmithread.h | 69 + .../plutosdrmimo/plutosdrmothread.cpp | 253 +++ .../plutosdrmimo/plutosdrmothread.h | 64 + .../plutosdroutput/plutosdroutputthread.cpp | 2 +- sdrbase/resources/webapi/doc/html2/index.html | 328 +++- .../doc/swagger/include/ChannelSettings.yaml | 2 + .../webapi/doc/swagger/include/DABDemod.yaml | 36 + .../doc/swagger/include/DeviceReports.yaml | 4 + .../doc/swagger/include/DeviceSettings.yaml | 4 + .../webapi/doc/swagger/include/PlutoSdr.yaml | 124 ++ .../webapi/doc/swagger/include/SDRPlayV3.yaml | 61 + .../api/swagger/include/DeviceReports.yaml | 2 + .../api/swagger/include/DeviceSettings.yaml | 2 + .../api/swagger/include/PlutoSdr.yaml | 124 ++ swagger/sdrangel/code/html2/index.html | 246 ++- .../code/qt5/client/SWGDeviceReport.cpp | 25 + .../code/qt5/client/SWGDeviceReport.h | 7 + .../code/qt5/client/SWGDeviceSettings.cpp | 25 + .../code/qt5/client/SWGDeviceSettings.h | 7 + .../code/qt5/client/SWGModelFactory.h | 8 + .../code/qt5/client/SWGPlutoSdrMIMOReport.cpp | 277 +++ .../code/qt5/client/SWGPlutoSdrMIMOReport.h | 101 ++ .../qt5/client/SWGPlutoSdrMIMOSettings.cpp | 959 +++++++++++ .../code/qt5/client/SWGPlutoSdrMIMOSettings.h | 280 +++ 40 files changed, 8312 insertions(+), 12 deletions(-) create mode 100644 plugins/samplemimo/plutosdrmimo/CMakeLists.txt create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmimo.cpp create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmimo.h create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmimogui.cpp create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmimogui.h create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmimogui.ui create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmimoplugin.cpp create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmimoplugin.h create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmimosettings.cpp create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmimosettings.h create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmimowebapiadapter.cpp create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmimowebapiadapter.h create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmithread.cpp create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmithread.h create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmothread.cpp create mode 100644 plugins/samplemimo/plutosdrmimo/plutosdrmothread.h create mode 100644 sdrbase/resources/webapi/doc/swagger/include/DABDemod.yaml create mode 100644 sdrbase/resources/webapi/doc/swagger/include/SDRPlayV3.yaml create mode 100644 swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOReport.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOReport.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOSettings.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOSettings.h diff --git a/devices/plutosdr/deviceplutosdrbox.cpp b/devices/plutosdr/deviceplutosdrbox.cpp index 39da90601..871e5fa5c 100644 --- a/devices/plutosdr/deviceplutosdrbox.cpp +++ b/devices/plutosdr/deviceplutosdrbox.cpp @@ -74,9 +74,10 @@ DevicePlutoSDRBox::DevicePlutoSDRBox(const std::string& uri) : if (std::regex_match(channelId, channelIdReg)) { + int nbAttributes = iio_channel_get_attrs_count(chn); m_rxChannelIds.append(QString(channelId.c_str())); m_rxChannels.append(chn); - qDebug("DevicePlutoSDRBox::DevicePlutoSDRBox: Rx: %s", channelId.c_str()); + qDebug("DevicePlutoSDRBox::DevicePlutoSDRBox: Rx: %s #Attrs: %d", channelId.c_str(), nbAttributes); } } @@ -89,9 +90,10 @@ DevicePlutoSDRBox::DevicePlutoSDRBox(const std::string& uri) : if (std::regex_match(channelId, channelIdReg)) { + int nbAttributes = iio_channel_get_attrs_count(chn); m_txChannelIds.append(QString(channelId.c_str())); m_txChannels.append(chn); - qDebug("DevicePlutoSDRBox::DevicePlutoSDRBox: Tx: %s", channelId.c_str()); + qDebug("DevicePlutoSDRBox::DevicePlutoSDRBox: Tx: %s #Attrs: %d", channelId.c_str(), nbAttributes); } } } @@ -296,7 +298,7 @@ bool DevicePlutoSDRBox::openRx() } else { - std::cerr << "DevicePlutoSDRBox::openRx: failed" << std::endl; + qWarning("DevicePlutoSDRBox::openRx: open channel I failed"); return false; } @@ -318,7 +320,55 @@ bool DevicePlutoSDRBox::openRx() } else { - std::cerr << "DevicePlutoSDRBox::openRx: failed" << std::endl; + qWarning("DevicePlutoSDRBox::openRx: open channel Q failed"); + return false; + } +} + +bool DevicePlutoSDRBox::openSecondRx() +{ + if (!m_valid) { return false; } + + if (m_rxChannels.size() > 2) + { + iio_channel_enable(m_rxChannels.at(2)); + + const struct iio_data_format *df = iio_channel_get_data_format(m_rxChannels.at(2)); + qDebug("DevicePlutoSDRBox::openSecondRx channel I: length: %u bits: %u shift: %u signed: %s be: %s with_scale: %s scale: %lf repeat: %u", + df->length, + df->bits, + df->shift, + df->is_signed ? "true" : "false", + df->is_be ? "true" : "false", + df->with_scale? "true" : "false", + df->scale, + df->repeat); + } + else + { + qWarning("DevicePlutoSDRBox::openSecondRx: open channel I failed"); + return false; + } + + if (m_rxChannels.size() > 3) + { + iio_channel_enable(m_rxChannels.at(3)); + + const struct iio_data_format* df = iio_channel_get_data_format(m_rxChannels.at(3)); + qDebug("DevicePlutoSDRBox::openSecondRx channel Q: length: %u bits: %u shift: %u signed: %s be: %s with_scale: %s scale: %lf repeat: %u", + df->length, + df->bits, + df->shift, + df->is_signed ? "true" : "false", + df->is_be ? "true" : "false", + df->with_scale ? "true" : "false", + df->scale, + df->repeat); + return true; + } + else + { + qWarning("DevicePlutoSDRBox::openSecondRx: open channel Q failed"); return false; } } @@ -369,18 +419,76 @@ bool DevicePlutoSDRBox::openTx() } } +bool DevicePlutoSDRBox::openSecondTx() +{ + if (!m_valid) { return false; } + + if (m_txChannels.size() > 2) + { + iio_channel_enable(m_txChannels.at(2)); + const struct iio_data_format *df = iio_channel_get_data_format(m_txChannels.at(2)); + qDebug("DevicePlutoSDRBox::openSecondTx: channel I: length: %u bits: %u shift: %u signed: %s be: %s with_scale: %s scale: %lf repeat: %u", + df->length, + df->bits, + df->shift, + df->is_signed ? "true" : "false", + df->is_be ? "true" : "false", + df->with_scale? "true" : "false", + df->scale, + df->repeat); + } + else + { + qWarning("DevicePlutoSDRBox::openSecondTx: failed to open I channel"); + return false; + } + + if (m_txChannels.size() > 3) + { + iio_channel_enable(m_txChannels.at(3)); + const struct iio_data_format *df = iio_channel_get_data_format(m_txChannels.at(3)); + qDebug("DevicePlutoSDRBox::openSecondTx: channel Q: length: %u bits: %u shift: %u signed: %s be: %s with_scale: %s scale: %lf repeat: %u", + df->length, + df->bits, + df->shift, + df->is_signed ? "true" : "false", + df->is_be ? "true" : "false", + df->with_scale? "true" : "false", + df->scale, + df->repeat); + return true; + } + else + { + qWarning("DevicePlutoSDRBox::openSecondTx: failed to open Q channel"); + return false; + } +} + void DevicePlutoSDRBox::closeRx() { if (m_rxChannels.size() > 0) { iio_channel_disable(m_rxChannels.at(0)); } if (m_rxChannels.size() > 1) { iio_channel_disable(m_rxChannels.at(1)); } } +void DevicePlutoSDRBox::closeSecondRx() +{ + if (m_rxChannels.size() > 2) { iio_channel_disable(m_rxChannels.at(2)); } + if (m_rxChannels.size() > 3) { iio_channel_disable(m_rxChannels.at(3)); } +} + void DevicePlutoSDRBox::closeTx() { if (m_txChannels.size() > 0) { iio_channel_disable(m_txChannels.at(0)); } if (m_txChannels.size() > 1) { iio_channel_disable(m_txChannels.at(1)); } } +void DevicePlutoSDRBox::closeSecondTx() +{ + if (m_txChannels.size() > 2) { iio_channel_disable(m_txChannels.at(2)); } + if (m_txChannels.size() > 3) { iio_channel_disable(m_txChannels.at(3)); } +} + struct iio_buffer *DevicePlutoSDRBox::createRxBuffer(unsigned int size, bool cyclic) { if (m_devRx) { @@ -519,6 +627,16 @@ void DevicePlutoSDRBox::txChannelConvert(int16_t *dst, int16_t *src) } } +void DevicePlutoSDRBox::txChannelConvert(int chanIndex, int16_t *dst, int16_t *src) +{ + if (m_txChannels.size() > 2*chanIndex) { + iio_channel_convert_inverse(m_txChannels.at(2*chanIndex), &dst[0], &src[0]); + } + if (m_txChannels.size() > 2*chanIndex+1) { + iio_channel_convert_inverse(m_txChannels.at(2*chanIndex+1), &dst[1], &src[1]); + } +} + bool DevicePlutoSDRBox::getRxSampleRates(SampleRates& sampleRates) { std::string srStr; diff --git a/devices/plutosdr/deviceplutosdrbox.h b/devices/plutosdr/deviceplutosdrbox.h index 314abdd12..aebe22415 100644 --- a/devices/plutosdr/deviceplutosdrbox.h +++ b/devices/plutosdr/deviceplutosdrbox.h @@ -80,10 +80,14 @@ public: void set_params(DeviceType devType, const std::vector ¶ms); bool get_param(DeviceType devType, const std::string ¶m, std::string &value); - bool openRx(); //!< Open first Rx (Rx0) - bool openTx(); //!< Open first Tx (Tx0) - void closeRx(); //!< Close first Rx (Rx0) - void closeTx(); //!< Close first Tx (Tx0) + bool openRx(); //!< Open first Rx (Rx0) + bool openTx(); //!< Open first Tx (Tx0) + bool openSecondRx(); //!< Open second Rx (Rx1) + bool openSecondTx(); //!< Open second Tx (Tx1) + void closeRx(); //!< Close first Rx (Rx0) + void closeTx(); //!< Close first Tx (Tx0) + void closeSecondRx(); //!< Close second Rx (Rx1) + void closeSecondTx(); //!< Close second Tx (Tx1) int getNbRx() const { return m_rxChannels.size() / 2; } int getNbTx() const { return m_txChannels.size() / 2; } struct iio_buffer *createRxBuffer(unsigned int size, bool cyclic); @@ -101,6 +105,7 @@ public: char* txBufferEnd(); char* txBufferFirst(); void txChannelConvert(int16_t *dst, int16_t *src); + void txChannelConvert(int chanIndex, int16_t *dst, int16_t *src); bool getRxSampleRates(SampleRates& sampleRates); bool getTxSampleRates(SampleRates& sampleRates); void setSampleRate(uint32_t sampleRate); diff --git a/plugins/samplemimo/CMakeLists.txt b/plugins/samplemimo/CMakeLists.txt index 676a2b69b..9a5923418 100644 --- a/plugins/samplemimo/CMakeLists.txt +++ b/plugins/samplemimo/CMakeLists.txt @@ -12,6 +12,10 @@ if(ENABLE_XTRX AND LIBXTRX_FOUND) add_subdirectory(xtrxmimo) endif() +if(ENABLE_IIO AND LIBIIO_FOUND) + add_subdirectory(plutosdrmimo) +endif() + add_subdirectory(metismiso) add_subdirectory(testmi) add_subdirectory(testmosync) diff --git a/plugins/samplemimo/plutosdrmimo/CMakeLists.txt b/plugins/samplemimo/plutosdrmimo/CMakeLists.txt new file mode 100644 index 000000000..358c2fb7d --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/CMakeLists.txt @@ -0,0 +1,66 @@ +project(plutosdrmimo) + +set(plutosdrmimo_SOURCES + plutosdrmimo.cpp + plutosdrmimoplugin.cpp + plutosdrmithread.cpp + plutosdrmothread.cpp + plutosdrmimosettings.cpp + plutosdrmimowebapiadapter.cpp +) + +set(plutosdrmimo_HEADERS + plutosdrmimo.h + plutosdrmimoplugin.h + plutosdrmithread.h + plutosdrmothread.h + plutosdrmimosettings.h + plutosdrmimowebapiadapter.h +) + +include_directories( + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${CMAKE_SOURCE_DIR}/devices + ${LIBBLADERF_INCLUDE_DIRS} +) + +if (NOT SERVER_MODE) + set (plutosdrmimo_SOURCES + ${plutosdrmimo_SOURCES} + plutosdrmimogui.cpp + plutosdrmimogui.ui + ) + set(plutosdrmimo_HEADERS + ${plutosdrmimo_HEADERS} + plutosdrmimogui.h + ) + set(TARGET_NAME mimoplutosdr) + set(TARGET_LIB "Qt5::Widgets") + set(TARGET_LIB_GUI "sdrgui") + set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) +else() + set(TARGET_NAME mimoplutosdrsrv) + set(TARGET_LIB "") + set(TARGET_LIB_GUI "") + set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR}) +endif() + +add_library(${TARGET_NAME} SHARED + ${plutosdrmimo_SOURCES} +) + +if(LIBIIO_EXTERNAL) + add_dependencies(${TARGET_NAME} libiio) +endif() + +target_link_libraries(${TARGET_NAME} + Qt5::Core + ${TARGET_LIB} + sdrbase + ${TARGET_LIB_GUI} + swagger + ${LIBBLADERF_LIBRARIES} + plutosdrdevice +) + +install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER}) diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmimo.cpp b/plugins/samplemimo/plutosdrmimo/plutosdrmimo.cpp new file mode 100644 index 000000000..6dc77cb0a --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmimo.cpp @@ -0,0 +1,1496 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 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 "SWGDeviceSettings.h" +#include "SWGDeviceState.h" +#include "SWGDeviceReport.h" +#include "device/deviceapi.h" +#include "dsp/dspcommands.h" +#include "dsp/dspengine.h" +#include "dsp/dspdevicemimoengine.h" +#include "dsp/devicesamplesource.h" +#include "dsp/devicesamplesink.h" +#include "plutosdr/deviceplutosdrparams.h" +#include "plutosdr/deviceplutosdrshared.h" + +#include "plutosdrmithread.h" +#include "plutosdrmothread.h" +#include "plutosdrmimo.h" + +MESSAGE_CLASS_DEFINITION(PlutoSDRMIMO::MsgConfigurePlutoSDRMIMO, Message) +MESSAGE_CLASS_DEFINITION(PlutoSDRMIMO::MsgStartStop, Message) + +PlutoSDRMIMO::PlutoSDRMIMO(DeviceAPI *deviceAPI) : + m_deviceAPI(deviceAPI), + m_settings(), + m_sourceThread(nullptr), + m_sinkThread(nullptr), + m_deviceDescription("BladeRF2MIMO"), + m_runningRx(false), + m_runningTx(false), + m_plutoParams(nullptr), + m_open(false), + m_nbRx(0), + m_nbTx(0) +{ + m_mimoType = MIMOHalfSynchronous; + m_sampleMIFifo.init(2, PlutoSDRMIMOSettings::m_plutoSDRBlockSizeSamples); + m_sampleMOFifo.init(2, PlutoSDRMIMOSettings::m_plutoSDRBlockSizeSamples); + m_networkManager = new QNetworkAccessManager(); + connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); + + m_open = openDevice(); + + if (m_plutoParams) + { + m_nbRx = m_plutoParams->getBox()->getNbRx(); + m_deviceAPI->setNbSourceStreams(m_nbRx); + m_nbTx = m_plutoParams->getBox()->getNbTx(); + m_deviceAPI->setNbSinkStreams(m_nbTx); + } +} + +PlutoSDRMIMO::~PlutoSDRMIMO() +{ + disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); + delete m_networkManager; + closeDevice(); +} + +void PlutoSDRMIMO::destroy() +{ + delete this; +} + +bool PlutoSDRMIMO::openDevice() +{ + m_plutoParams = new DevicePlutoSDRParams(); + + if (m_deviceAPI->getHardwareUserArguments().size() != 0) + { + QStringList kv = m_deviceAPI->getHardwareUserArguments().split('='); // expecting "uri=xxx" + + if (kv.size() > 1) + { + if (kv.at(0) == "uri") + { + if (!m_plutoParams->openURI(kv.at(1).toStdString())) + { + qCritical("PlutoSDRMIMO::openDevice: open network device uri=%s failed", qPrintable(kv.at(1))); + return false; + } + } + else + { + qCritical("PlutoSDRMIMO::openDevice: unexpected user parameter key %s", qPrintable(kv.at(0))); + return false; + } + } + else + { + qCritical("PlutoSDRMIMO::openDevice: unexpected user arguments %s", qPrintable(m_deviceAPI->getHardwareUserArguments())); + return false; + } + } + else + { + char serial[256]; + strcpy(serial, qPrintable(m_deviceAPI->getSamplingDeviceSerial())); + + if (!m_plutoParams->open(serial)) + { + qCritical("PlutoSDRMIMO::openDevice: open serial %s failed", serial); + return false; + } + } + + return true; +} + +void PlutoSDRMIMO::closeDevice() +{ + if (m_plutoParams == nullptr) { // was never open + return; + } + + if (m_runningRx) { + stopRx(); + } + + if (m_runningTx) { + stopTx(); + } + + m_plutoParams->close(); + delete m_plutoParams; + m_plutoParams = nullptr; + m_open = false; +} + +void PlutoSDRMIMO::init() +{ + applySettings(m_settings, true); +} + +bool PlutoSDRMIMO::startRx() +{ + qDebug("PlutoSDRMIMO::startRx"); + + if (!m_open) + { + qCritical("PlutoSDRMIMO::startRx: device was not opened"); + return false; + } + + QMutexLocker mutexLocker(&m_mutex); + + if (m_runningRx) { + stopRx(); + } + + m_sourceThread = new PlutoSDRMIThread(m_plutoParams->getBox()); + m_sampleMIFifo.reset(); + m_sourceThread->setFifo(&m_sampleMIFifo); + m_sourceThread->setFcPos(m_settings.m_fcPosRx); + m_sourceThread->setLog2Decimation(m_settings.m_log2Decim); + m_sourceThread->setIQOrder(m_settings.m_iqOrder); + + if (m_nbRx > 0) { + m_plutoParams->getBox()->openRx(); + } + + if (m_nbRx > 1) { + m_plutoParams->getBox()->openSecondRx(); + } + + m_sourceThread->startWork(); + mutexLocker.unlock(); + m_runningRx = true; + + return true; +} + +bool PlutoSDRMIMO::startTx() +{ + qDebug("PlutoSDRMIMO::startTx"); + + if (!m_open) + { + qCritical("PlutoSDRMIMO::startTx: device was not opened"); + return false; + } + + QMutexLocker mutexLocker(&m_mutex); + + if (m_runningTx) { + stopTx(); + } + + m_sinkThread = new PlutoSDRMOThread(m_plutoParams->getBox()); + m_sampleMOFifo.reset(); + m_sinkThread->setFifo(&m_sampleMOFifo); + m_sinkThread->setFcPos(m_settings.m_fcPosTx); + m_sinkThread->setLog2Interpolation(m_settings.m_log2Interp); + + if (m_nbTx > 0) { + m_plutoParams->getBox()->openTx(); + } + + if (m_nbTx > 1) { + m_plutoParams->getBox()->openSecondTx(); + } + + m_sinkThread->startWork(); + mutexLocker.unlock(); + m_runningTx = true; + + return true; +} + +void PlutoSDRMIMO::stopRx() +{ + qDebug("PlutoSDRMIMO::stopRx"); + + if (!m_sourceThread) { + return; + } + + QMutexLocker mutexLocker(&m_mutex); + + m_sourceThread->stopWork(); + delete m_sourceThread; + m_sourceThread = nullptr; + m_runningRx = false; + + if (m_nbRx > 1) { + m_plutoParams->getBox()->closeSecondRx(); + } + + if (m_nbRx > 0) { + m_plutoParams->getBox()->closeRx(); + } +} + +void PlutoSDRMIMO::stopTx() +{ + qDebug("PlutoSDRMIMO::stopTx"); + + if (!m_sinkThread) { + return; + } + + QMutexLocker mutexLocker(&m_mutex); + + m_sinkThread->stopWork(); + delete m_sinkThread; + m_sinkThread = nullptr; + m_runningTx = false; + + if (m_nbTx > 1) { + m_plutoParams->getBox()->closeSecondTx(); + } + + if (m_nbTx > 0) { + m_plutoParams->getBox()->closeTx(); + } +} + +QByteArray PlutoSDRMIMO::serialize() const +{ + return m_settings.serialize(); +} + +bool PlutoSDRMIMO::deserialize(const QByteArray& data) +{ + bool success = true; + + if (!m_settings.deserialize(data)) + { + m_settings.resetToDefaults(); + success = false; + } + + MsgConfigurePlutoSDRMIMO* message = MsgConfigurePlutoSDRMIMO::create(m_settings, true); + m_inputMessageQueue.push(message); + + if (m_guiMessageQueue) + { + MsgConfigurePlutoSDRMIMO* messageToGUI = MsgConfigurePlutoSDRMIMO::create(m_settings, true); + m_guiMessageQueue->push(messageToGUI); + } + + return success; +} + +const QString& PlutoSDRMIMO::getDeviceDescription() const +{ + return m_deviceDescription; +} + +int PlutoSDRMIMO::getSourceSampleRate(int index) const +{ + (void) index; + int rate = m_settings.m_devSampleRate; + return (rate / (1<push(messageToGUI); + } +} + +quint64 PlutoSDRMIMO::getSinkCenterFrequency(int index) const +{ + (void) index; + return m_settings.m_txCenterFrequency; +} + +void PlutoSDRMIMO::setSinkCenterFrequency(qint64 centerFrequency, int index) +{ + (void) index; + PlutoSDRMIMOSettings settings = m_settings; + settings.m_txCenterFrequency = centerFrequency; + + MsgConfigurePlutoSDRMIMO* message = MsgConfigurePlutoSDRMIMO::create(settings, false); + m_inputMessageQueue.push(message); + + if (m_guiMessageQueue) + { + MsgConfigurePlutoSDRMIMO* messageToGUI = MsgConfigurePlutoSDRMIMO::create(settings, false); + m_guiMessageQueue->push(messageToGUI); + } +} + +bool PlutoSDRMIMO::handleMessage(const Message& message) +{ + if (MsgConfigurePlutoSDRMIMO::match(message)) + { + MsgConfigurePlutoSDRMIMO& conf = (MsgConfigurePlutoSDRMIMO&) message; + qDebug() << "PlutoSDRMIMO::handleMessage: MsgConfigurePlutoSDRMIMO"; + + bool success = applySettings(conf.getSettings(), conf.getForce()); + + if (!success) { + qDebug("PlutoSDRMIMO::handleMessage: config error"); + } + + return true; + } + else if (MsgStartStop::match(message)) + { + MsgStartStop& cmd = (MsgStartStop&) message; + qDebug() << "PlutoSDRMIMO::handleMessage: " + << " " << (cmd.getRxElseTx() ? "Rx" : "Tx") + << " MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop"); + + bool startStopRxElseTx = cmd.getRxElseTx(); + + if (cmd.getStartStop()) + { + if (m_deviceAPI->initDeviceEngine(startStopRxElseTx ? 0 : 1)) { + m_deviceAPI->startDeviceEngine(startStopRxElseTx ? 0 : 1); + } + } + else + { + m_deviceAPI->stopDeviceEngine(startStopRxElseTx ? 0 : 1); + } + + if (m_settings.m_useReverseAPI) { + webapiReverseSendStartStop(cmd.getStartStop()); + } + + return true; + } + else + { + return false; + } +} + +bool PlutoSDRMIMO::applySettings(const PlutoSDRMIMOSettings& settings, bool force) +{ + qDebug() << "PlutoSDRMIMO::applySettings: common: " + << " m_devSampleRate: " << settings.m_devSampleRate + << " m_LOppmTenths: " << settings.m_LOppmTenths + << " m_rxCenterFrequency: " << settings.m_rxCenterFrequency + << " m_dcBlock: " << settings.m_dcBlock + << " m_iqCorrection: " << settings.m_iqCorrection + << " m_hwBBDCBlock: " << settings.m_hwBBDCBlock + << " m_hwRFDCBlock: " << settings.m_hwRFDCBlock + << " m_hwIQCorrection: " << settings.m_hwIQCorrection + << " m_fcPosRx: " << settings.m_fcPosRx + << " m_rxTransverterMode: " << settings.m_rxTransverterMode + << " m_rxTransverterDeltaFrequency: " << settings.m_rxTransverterDeltaFrequency + << " m_iqOrder: " << settings.m_iqOrder + << " m_lpfBWRx: " << settings.m_lpfBWRx + << " m_lpfRxFIREnable: " << settings.m_lpfRxFIREnable + << " m_lpfRxFIRBW: " << settings.m_lpfRxFIRBW + << " m_lpfRxFIRlog2Decim: " << settings.m_lpfRxFIRlog2Decim + << " m_lpfRxFIRGain: " << settings.m_lpfRxFIRGain + << " m_log2Decim: " << settings.m_log2Decim + << " m_rx0Gain: " << settings.m_rx0Gain + << " m_rx0GainMode: " << settings.m_rx0GainMode + << " m_rx0AntennaPath: " << settings.m_rx0AntennaPath + << " m_rx0Gain: " << settings.m_rx1Gain + << " m_rx0GainMode: " << settings.m_rx1GainMode + << " m_rx0AntennaPath: " << settings.m_rx1AntennaPath + << " m_txCenterFrequency: " << settings.m_txCenterFrequency + << " m_fcPosTx: " << settings.m_fcPosTx + << " m_txTransverterMode: " << settings.m_txTransverterMode + << " m_txTransverterDeltaFrequency: " << settings.m_txTransverterDeltaFrequency + << " m_lpfBWTx: " << settings.m_lpfBWTx + << " m_lpfTxFIREnable: " << settings.m_lpfTxFIREnable + << " m_lpfTxFIRBW: " << settings.m_lpfTxFIRBW + << " m_lpfTxFIRlog2Interp: " << settings.m_lpfTxFIRlog2Interp + << " m_lpfTxFIRGain: " << settings.m_lpfTxFIRGain + << " m_log2Interp: " << settings.m_log2Interp + << " m_tx0Att: " << settings.m_tx0Att + << " m_tx0AntennaPath: " << settings.m_tx0AntennaPath + << " m_tx1Att: " << settings.m_tx1Att + << " m_tx1AntennaPath: " << settings.m_tx1AntennaPath + << " m_useReverseAPI: " << settings.m_useReverseAPI + << " m_reverseAPIAddress: " << settings.m_reverseAPIAddress + << " m_reverseAPIPort: " << settings.m_reverseAPIPort + << " m_reverseAPIDeviceIndex: " << settings.m_reverseAPIDeviceIndex + << " force: " << force; + + QList reverseAPIKeys; + bool forwardChangeRxDSP = false; + bool forwardChangeTxDSP = false; + DevicePlutoSDRBox *plutoBox = m_plutoParams ? m_plutoParams->getBox() : nullptr; + + // Rx + + if ((m_settings.m_rxCenterFrequency != settings.m_rxCenterFrequency) || force) { + reverseAPIKeys.append("rxCenterFrequency"); + } + if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force) { + reverseAPIKeys.append("devSampleRate"); + } + if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) { + reverseAPIKeys.append("LOppmTenths"); + } + if ((m_settings.m_dcBlock != settings.m_dcBlock) || force) { + reverseAPIKeys.append("dcBlock"); + } + if ((m_settings.m_iqCorrection != settings.m_iqCorrection) || force) { + reverseAPIKeys.append("iqCorrection"); + } + if ((m_settings.m_hwBBDCBlock != settings.m_hwBBDCBlock) || force) { + reverseAPIKeys.append("hwBBDCBlock"); + } + if ((m_settings.m_hwRFDCBlock != settings.m_hwRFDCBlock) || force) { + reverseAPIKeys.append("hwRFDCBlock"); + } + if ((m_settings.m_hwIQCorrection != settings.m_hwIQCorrection) || force) { + reverseAPIKeys.append("hwIQCorrection"); + } + if ((m_settings.m_lpfRxFIREnable != settings.m_lpfRxFIREnable) || force) { + reverseAPIKeys.append("lpfRxFIREnable"); + } + if ((m_settings.m_lpfRxFIRBW != settings.m_lpfRxFIRBW) || force) { + reverseAPIKeys.append("lpfRxFIRBW"); + } + if ((m_settings.m_lpfRxFIRlog2Decim != settings.m_lpfRxFIRlog2Decim) || force) { + reverseAPIKeys.append("lpfRxFIRlog2Decim"); + } + if ((m_settings.m_lpfRxFIRGain != settings.m_lpfRxFIRGain) || force) { + reverseAPIKeys.append("lpfRxFIRGain"); + } + if ((m_settings.m_lpfTxFIREnable != settings.m_lpfTxFIREnable) || force) { + reverseAPIKeys.append("lpfTxFIREnable"); + } + if ((m_settings.m_lpfTxFIRBW != settings.m_lpfTxFIRBW) || force) { + reverseAPIKeys.append("lpfTxFIRBW"); + } + if ((m_settings.m_lpfTxFIRlog2Interp != settings.m_lpfTxFIRlog2Interp) || force) { + reverseAPIKeys.append("lpfRxFIRlog2Decim"); + } + if ((m_settings.m_lpfTxFIRGain != settings.m_lpfTxFIRGain) || force) { + reverseAPIKeys.append("lpfTxFIRGain"); + } + if ((m_settings.m_log2Decim != settings.m_log2Decim) || force) { + reverseAPIKeys.append("log2Decim"); + } + if ((m_settings.m_fcPosRx != settings.m_fcPosRx) || force) { + reverseAPIKeys.append("fcPosRx"); + } + if ((m_settings.m_fcPosTx != settings.m_fcPosTx) || force) { + reverseAPIKeys.append("fcPosTx"); + } + if ((m_settings.m_lpfBWRx != settings.m_lpfBWRx) || force) { + reverseAPIKeys.append("lpfBWRx"); + } + if ((m_settings.m_lpfBWTx != settings.m_lpfBWTx) || force) { + reverseAPIKeys.append("lpfBWTx"); + } + if ((m_settings.m_rx0Gain != settings.m_rx0Gain) || force) { + reverseAPIKeys.append("rx0Gain"); + } + if ((m_settings.m_rx0AntennaPath != settings.m_rx0AntennaPath) || force) { + reverseAPIKeys.append("rx0AntennaPath"); + } + if ((m_settings.m_rx0GainMode != settings.m_rx0GainMode) || force) { + reverseAPIKeys.append("rx0GainMode"); + } + if ((m_settings.m_rx1Gain != settings.m_rx1Gain) || force) { + reverseAPIKeys.append("rx1Gain"); + } + if ((m_settings.m_rx1AntennaPath != settings.m_rx1AntennaPath) || force) { + reverseAPIKeys.append("rx1AntennaPath"); + } + if ((m_settings.m_rx1GainMode != settings.m_rx1GainMode) || force) { + reverseAPIKeys.append("rx1GainMode"); + } + if ((m_settings.m_rxTransverterMode != settings.m_rxTransverterMode) || force) { + reverseAPIKeys.append("rxTransverterMode"); + } + if ((m_settings.m_rxTransverterDeltaFrequency != settings.m_rxTransverterDeltaFrequency) || force) { + reverseAPIKeys.append("rxTransverterDeltaFrequency"); + } + + // Tx + + if ((m_settings.m_txCenterFrequency != settings.m_txCenterFrequency) || force) { + reverseAPIKeys.append("txCenterFrequency"); + } + if ((m_settings.m_txTransverterMode != settings.m_txTransverterMode) || force) { + reverseAPIKeys.append("txTransverterMode"); + } + if ((m_settings.m_txTransverterDeltaFrequency != settings.m_txTransverterDeltaFrequency) || force) { + reverseAPIKeys.append("txTransverterDeltaFrequency"); + } + + // Rx + + if ((m_settings.m_dcBlock != settings.m_dcBlock) || + (m_settings.m_iqCorrection != settings.m_iqCorrection) || force) + { + m_deviceAPI->configureCorrections(settings.m_dcBlock, m_settings.m_iqCorrection); + } + + // Change affecting device sample rate chain and other buddies + if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || + (m_settings.m_lpfRxFIREnable != settings.m_lpfRxFIREnable) || + (m_settings.m_lpfRxFIRlog2Decim != settings.m_lpfRxFIRlog2Decim) || + (settings.m_lpfRxFIRBW != m_settings.m_lpfRxFIRBW) || + (settings.m_lpfRxFIRGain != m_settings.m_lpfRxFIRGain) || force) + { + if (plutoBox) + { + plutoBox->setFIR( + settings.m_devSampleRate, + settings.m_lpfRxFIRlog2Decim, + DevicePlutoSDRBox::USE_RX, + settings.m_lpfRxFIRBW, + settings.m_lpfRxFIRGain + ); + plutoBox->setFIREnable(settings.m_lpfRxFIREnable); // eventually enable/disable FIR + plutoBox->setSampleRate(settings.m_devSampleRate); // and set end point sample rate + + plutoBox->getRxSampleRates(m_rxDeviceSampleRates); // pick up possible new rates + qDebug() << "PlutoSDRMIMO::applySettings: Rx: BBPLL(Hz): " << m_rxDeviceSampleRates.m_bbRateHz + << " ADC: " << m_rxDeviceSampleRates.m_addaConnvRate + << " -HB3-> " << m_rxDeviceSampleRates.m_hb3Rate + << " -HB2-> " << m_rxDeviceSampleRates.m_hb2Rate + << " -HB1-> " << m_rxDeviceSampleRates.m_hb1Rate + << " -FIR-> " << m_rxDeviceSampleRates.m_firRate; + } + + forwardChangeRxDSP = (m_settings.m_devSampleRate != settings.m_devSampleRate) || force; + } + + if ((m_settings.m_log2Decim != settings.m_log2Decim) || force) + { + if (m_sourceThread) + { + m_sourceThread->setLog2Decimation(settings.m_log2Decim); + qDebug() << "PlutoSDRMIMO::applySettings: set soft decimation to " << (1<setIQOrder(settings.m_iqOrder); + } + } + + if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) + { + if (plutoBox) { + plutoBox->setLOPPMTenths(settings.m_LOppmTenths); + } + } + + std::vector params; + bool paramsToSet = false; + + if ((m_settings.m_rxCenterFrequency != settings.m_rxCenterFrequency) + || (m_settings.m_fcPosRx != settings.m_fcPosRx) + || (m_settings.m_log2Decim != settings.m_log2Decim) + || (m_settings.m_devSampleRate != settings.m_devSampleRate) + || (m_settings.m_rxTransverterMode != settings.m_rxTransverterMode) + || (m_settings.m_rxTransverterDeltaFrequency != settings.m_rxTransverterDeltaFrequency) || force) + { + qint64 deviceCenterFrequency = DeviceSampleSource::calculateDeviceCenterFrequency( + settings.m_rxCenterFrequency, + settings.m_rxTransverterDeltaFrequency, + settings.m_log2Decim, + (DeviceSampleSource::fcPos_t) settings.m_fcPosRx, + settings.m_devSampleRate, + DeviceSampleSource::FrequencyShiftScheme::FSHIFT_STD, + settings.m_rxTransverterMode); + + params.push_back(QString(tr("out_altvoltage0_RX_LO_frequency=%1").arg(deviceCenterFrequency)).toStdString()); + paramsToSet = true; + forwardChangeRxDSP = true; + + if ((m_settings.m_fcPosRx != settings.m_fcPosRx) || force) + { + if (m_sourceThread) + { + m_sourceThread->setFcPos(settings.m_fcPosRx); + qDebug() << "PlutoSDRMIMO::applySettings: set fcPos to " << settings.m_fcPosRx; + } + } + } + + if ((m_settings.m_lpfBWRx != settings.m_lpfBWRx) || force) + { + params.push_back(QString(tr("in_voltage_rf_bandwidth=%1").arg(settings.m_lpfBWRx)).toStdString()); + paramsToSet = true; + } + + if ((m_settings.m_rx0AntennaPath != settings.m_rx0AntennaPath) || force) + { + QString rfPortStr; + PlutoSDRMIMOSettings::translateRFPathRx(settings.m_rx0AntennaPath, rfPortStr); + params.push_back(QString(tr("in_voltage0_rf_port_select=%1").arg(rfPortStr)).toStdString()); + paramsToSet = true; + } + + if ((m_settings.m_rx1AntennaPath != settings.m_rx1AntennaPath) || force) + { + QString rfPortStr; + PlutoSDRMIMOSettings::translateRFPathRx(settings.m_rx1AntennaPath, rfPortStr); + params.push_back(QString(tr("in_voltage1_rf_port_select=%1").arg(rfPortStr)).toStdString()); + paramsToSet = true; + } + + if ((m_settings.m_rx0GainMode != settings.m_rx0GainMode) || force) + { + QString gainModeStr; + PlutoSDRMIMOSettings::translateGainMode(settings.m_rx0GainMode, gainModeStr); + params.push_back(QString(tr("in_voltage0_gain_control_mode=%1").arg(gainModeStr)).toStdString()); + paramsToSet = true; + } + + if ((m_settings.m_rx1GainMode != settings.m_rx1GainMode) || force) + { + QString gainModeStr; + PlutoSDRMIMOSettings::translateGainMode(settings.m_rx1GainMode, gainModeStr); + params.push_back(QString(tr("in_voltage1_gain_control_mode=%1").arg(gainModeStr)).toStdString()); + paramsToSet = true; + } + + if ((m_settings.m_rx0Gain != settings.m_rx0Gain) || force) + { + params.push_back(QString(tr("in_voltage0_hardwaregain=%1").arg(settings.m_rx0Gain)).toStdString()); + paramsToSet = true; + } + + if ((m_settings.m_rx1Gain != settings.m_rx1Gain) || force) + { + params.push_back(QString(tr("in_voltage1_hardwaregain=%1").arg(settings.m_rx1Gain)).toStdString()); + paramsToSet = true; + } + + if ((m_settings.m_hwBBDCBlock != settings.m_hwBBDCBlock) || force) + { + params.push_back(QString(tr("in_voltage_bb_dc_offset_tracking_en=%1").arg(settings.m_hwBBDCBlock ? 1 : 0)).toStdString()); + paramsToSet = true; + } + + if ((m_settings.m_hwRFDCBlock != settings.m_hwRFDCBlock) || force) + { + params.push_back(QString(tr("in_voltage_rf_dc_offset_tracking_en=%1").arg(settings.m_hwRFDCBlock ? 1 : 0)).toStdString()); + paramsToSet = true; + } + + if ((m_settings.m_hwIQCorrection != settings.m_hwIQCorrection) || force) + { + params.push_back(QString(tr("in_voltage_quadrature_tracking_en=%1").arg(settings.m_hwIQCorrection ? 1 : 0)).toStdString()); + paramsToSet = true; + } + + // Tx + + // Change affecting device sample rate chain and other buddies + if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || + (m_settings.m_lpfTxFIREnable != settings.m_lpfTxFIREnable) || + (m_settings.m_lpfTxFIRlog2Interp != settings.m_lpfTxFIRlog2Interp) || + (settings.m_lpfTxFIRBW != m_settings.m_lpfTxFIRBW) || + (settings.m_lpfTxFIRGain != m_settings.m_lpfTxFIRGain) || force) + { + plutoBox->setFIR( + settings.m_devSampleRate, + settings.m_lpfTxFIRlog2Interp, + DevicePlutoSDRBox::USE_TX, + settings.m_lpfTxFIRBW, + settings.m_lpfTxFIRGain + ); + plutoBox->setFIREnable(settings.m_lpfTxFIREnable); // eventually enable/disable FIR + plutoBox->setSampleRate(settings.m_devSampleRate); // and set end point sample rate + + plutoBox->getTxSampleRates(m_txDeviceSampleRates); // pick up possible new rates + qDebug() << "PlutoSDRMIMO::applySettings: Tx: BBPLL(Hz): " << m_txDeviceSampleRates.m_bbRateHz + << " DAC: " << m_txDeviceSampleRates.m_addaConnvRate + << " <-HB3- " << m_txDeviceSampleRates.m_hb3Rate + << " <-HB2- " << m_txDeviceSampleRates.m_hb2Rate + << " <-HB1- " << m_txDeviceSampleRates.m_hb1Rate + << " <-FIR- " << m_txDeviceSampleRates.m_firRate; + + forwardChangeTxDSP = (m_settings.m_devSampleRate != settings.m_devSampleRate) || force; + } + + if ((m_settings.m_log2Interp != settings.m_log2Interp) || force) + { + reverseAPIKeys.append("log2Interp"); + + if (m_sinkThread != 0) + { + m_sinkThread->setLog2Interpolation(settings.m_log2Interp); + qDebug() << "PlutoSDRMIMO::applySettings: set soft interpolation in thread to " << (1<set_params(DevicePlutoSDRBox::DEVICE_PHY, params); + } + + if (settings.m_useReverseAPI) + { + bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) || + (m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) || + (m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) || + (m_settings.m_reverseAPIDeviceIndex != settings.m_reverseAPIDeviceIndex); + webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); + } + + m_settings = settings; + + if (forwardChangeRxDSP) + { + int sampleRate = settings.m_devSampleRate/(1<getDeviceEngineInputMessageQueue()->push(notif0); + DSPMIMOSignalNotification *notif1 = new DSPMIMOSignalNotification(sampleRate, settings.m_rxCenterFrequency, true, 1); + m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif1); + } + + if (forwardChangeTxDSP) + { + qDebug("PlutoSDROutput::applySettings: forward change to self"); + + int sampleRate = m_settings.m_devSampleRate/(1<getDeviceEngineInputMessageQueue()->push(notif); + } + + return true; +} + +int PlutoSDRMIMO::webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setPlutoSdrMimoSettings(new SWGSDRangel::SWGPlutoSdrMIMOSettings()); + response.getPlutoSdrMimoSettings()->init(); + webapiFormatDeviceSettings(response, m_settings); + return 200; +} + +int PlutoSDRMIMO::webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage) +{ + (void) errorMessage; + PlutoSDRMIMOSettings settings = m_settings; + webapiUpdateDeviceSettings(settings, deviceSettingsKeys, response); + + MsgConfigurePlutoSDRMIMO *msg = MsgConfigurePlutoSDRMIMO::create(settings, force); + m_inputMessageQueue.push(msg); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigurePlutoSDRMIMO *msgToGUI = MsgConfigurePlutoSDRMIMO::create(settings, force); + m_guiMessageQueue->push(msgToGUI); + } + + webapiFormatDeviceSettings(response, settings); + return 200; +} + +void PlutoSDRMIMO::webapiUpdateDeviceSettings( + PlutoSDRMIMOSettings& settings, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response) +{ + if (deviceSettingsKeys.contains("devSampleRate")) { + settings.m_devSampleRate = response.getPlutoSdrMimoSettings()->getDevSampleRate(); + } + if (deviceSettingsKeys.contains("LOppmTenths")) { + settings.m_LOppmTenths = response.getPlutoSdrMimoSettings()->getLOppmTenths(); + } + if (deviceSettingsKeys.contains("rxCenterFrequency")) { + settings.m_rxCenterFrequency = response.getPlutoSdrMimoSettings()->getRxCenterFrequency(); + } + if (deviceSettingsKeys.contains("dcBlock")) { + settings.m_dcBlock = response.getPlutoSdrMimoSettings()->getDcBlock() != 0; + } + if (deviceSettingsKeys.contains("iqCorrection")) { + settings.m_iqCorrection = response.getPlutoSdrMimoSettings()->getIqCorrection() != 0; + } + if (deviceSettingsKeys.contains("hwBBDCBlock")) { + settings.m_hwBBDCBlock = response.getPlutoSdrMimoSettings()->getHwBbdcBlock() != 0; + } + if (deviceSettingsKeys.contains("hwRFDCBlock")) { + settings.m_hwRFDCBlock = response.getPlutoSdrMimoSettings()->getHwRfdcBlock() != 0; + } + if (deviceSettingsKeys.contains("hwIQCorrection")) { + settings.m_hwIQCorrection = response.getPlutoSdrMimoSettings()->getHwIqCorrection() != 0; + } + if (deviceSettingsKeys.contains("fcPosRx")) { + settings.m_fcPosRx = static_cast(response.getPlutoSdrMimoSettings()->getFcPosRx()); + } + if (deviceSettingsKeys.contains("rxTransverterMode")) { + settings.m_rxTransverterMode = response.getPlutoSdrMimoSettings()->getRxTransverterMode() != 0; + } + if (deviceSettingsKeys.contains("rxTransverterDeltaFrequency")) { + settings.m_rxTransverterDeltaFrequency = response.getPlutoSdrMimoSettings()->getRxTransverterDeltaFrequency(); + } + if (deviceSettingsKeys.contains("iqOrder")) { + settings.m_iqOrder = response.getPlutoSdrMimoSettings()->getIqOrder() != 0; + } + if (deviceSettingsKeys.contains("lpfBWRx")) { + settings.m_lpfBWRx = response.getPlutoSdrMimoSettings()->getLpfBwRx(); + } + if (deviceSettingsKeys.contains("lpfRxFIREnable")) { + settings.m_lpfRxFIREnable = response.getPlutoSdrMimoSettings()->getLpfRxFirEnable() != 0; + } + if (deviceSettingsKeys.contains("lpfRxFIRBW")) { + settings.m_lpfRxFIRBW = response.getPlutoSdrMimoSettings()->getLpfRxFirbw(); + } + if (deviceSettingsKeys.contains("lpfRxFIRlog2Decim")) { + settings.m_lpfRxFIRlog2Decim = response.getPlutoSdrMimoSettings()->getLpfRxFiRlog2Decim(); + } + if (deviceSettingsKeys.contains("lpfRxFIRGain")) { + settings.m_lpfRxFIRGain = response.getPlutoSdrMimoSettings()->getLpfRxFirGain(); + } + if (deviceSettingsKeys.contains("log2Decim")) { + settings.m_log2Decim = response.getPlutoSdrMimoSettings()->getLog2Decim(); + } + if (deviceSettingsKeys.contains("rx0Gain")) { + settings.m_rx0Gain = response.getPlutoSdrMimoSettings()->getRx0Gain(); + } + if (deviceSettingsKeys.contains("rx0GainMode")) { + settings.m_rx0GainMode = static_cast(response.getPlutoSdrMimoSettings()->getRx0GainMode()); + } + if (deviceSettingsKeys.contains("rx0AntennaPath")) { + settings.m_rx0AntennaPath = static_cast(response.getPlutoSdrMimoSettings()->getRx0AntennaPath()); + } + if (deviceSettingsKeys.contains("rx1Gain")) { + settings.m_rx1Gain = response.getPlutoSdrMimoSettings()->getRx1Gain(); + } + if (deviceSettingsKeys.contains("rx1GainMode")) { + settings.m_rx1GainMode = static_cast(response.getPlutoSdrMimoSettings()->getRx1GainMode()); + } + if (deviceSettingsKeys.contains("rx1AntennaPath")) { + settings.m_rx1AntennaPath = static_cast(response.getPlutoSdrMimoSettings()->getRx1AntennaPath()); + } + if (deviceSettingsKeys.contains("txCenterFrequency")) { + settings.m_txCenterFrequency = response.getPlutoSdrMimoSettings()->getTxCenterFrequency(); + } + if (deviceSettingsKeys.contains("fcPosTx")) { + settings.m_fcPosTx = static_cast(response.getPlutoSdrMimoSettings()->getFcPosTx()); + } + if (deviceSettingsKeys.contains("txTransverterMode")) { + settings.m_txTransverterMode = response.getPlutoSdrMimoSettings()->getTxTransverterMode() != 0; + } + if (deviceSettingsKeys.contains("txTransverterDeltaFrequency")) { + settings.m_txTransverterDeltaFrequency = response.getPlutoSdrMimoSettings()->getTxTransverterDeltaFrequency(); + } + if (deviceSettingsKeys.contains("lpfBWTx")) { + settings.m_lpfBWTx = response.getPlutoSdrMimoSettings()->getLpfBwTx(); + } + if (deviceSettingsKeys.contains("lpfTxFIREnable")) { + settings.m_lpfTxFIREnable = response.getPlutoSdrMimoSettings()->getLpfTxFirEnable() != 0; + } + if (deviceSettingsKeys.contains("lpfTxFIRBW")) { + settings.m_lpfTxFIRBW = response.getPlutoSdrMimoSettings()->getLpfTxFirbw(); + } + if (deviceSettingsKeys.contains("lpfTxFIRlog2Interp")) { + settings.m_lpfTxFIRlog2Interp = response.getPlutoSdrMimoSettings()->getLpfTxFiRlog2Interp(); + } + if (deviceSettingsKeys.contains("lpfTxFIRGain")) { + settings.m_lpfTxFIRGain = response.getPlutoSdrMimoSettings()->getLpfTxFirGain(); + } + if (deviceSettingsKeys.contains("log2Interp")) { + settings.m_log2Interp = response.getPlutoSdrMimoSettings()->getLog2Interp(); + } + if (deviceSettingsKeys.contains("tx0Att")) { + settings.m_tx0Att = response.getPlutoSdrMimoSettings()->getTx0Att(); + } + if (deviceSettingsKeys.contains("tx0AntennaPath")) { + settings.m_tx0AntennaPath = static_cast(response.getPlutoSdrMimoSettings()->getTx0AntennaPath()); + } + if (deviceSettingsKeys.contains("tx1Att")) { + settings.m_tx1Att = response.getPlutoSdrMimoSettings()->getTx1Att(); + } + if (deviceSettingsKeys.contains("tx1AntennaPath")) { + settings.m_tx1AntennaPath = static_cast(response.getPlutoSdrMimoSettings()->getTx1AntennaPath()); + } + if (deviceSettingsKeys.contains("useReverseAPI")) { + settings.m_useReverseAPI = response.getBladeRf2MimoSettings()->getUseReverseApi() != 0; + } + if (deviceSettingsKeys.contains("reverseAPIAddress")) { + settings.m_reverseAPIAddress = *response.getBladeRf2MimoSettings()->getReverseApiAddress(); + } + if (deviceSettingsKeys.contains("reverseAPIPort")) { + settings.m_reverseAPIPort = response.getBladeRf2MimoSettings()->getReverseApiPort(); + } + if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) { + settings.m_reverseAPIDeviceIndex = response.getBladeRf2MimoSettings()->getReverseApiDeviceIndex(); + } +} + +void PlutoSDRMIMO::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const PlutoSDRMIMOSettings& settings) +{ + response.getPlutoSdrMimoSettings()->setDevSampleRate(settings.m_devSampleRate); + response.getPlutoSdrMimoSettings()->setLOppmTenths(settings.m_LOppmTenths); + response.getPlutoSdrMimoSettings()->setRxCenterFrequency(settings.m_rxCenterFrequency); + response.getPlutoSdrMimoSettings()->setDcBlock(settings.m_dcBlock ? 1 : 0); + response.getPlutoSdrMimoSettings()->setIqCorrection(settings.m_iqCorrection ? 1 : 0); + response.getPlutoSdrMimoSettings()->setHwBbdcBlock(settings.m_hwBBDCBlock ? 1 : 0); + response.getPlutoSdrMimoSettings()->setHwRfdcBlock(settings.m_hwRFDCBlock ? 1 : 0); + response.getPlutoSdrMimoSettings()->setHwIqCorrection(settings.m_hwIQCorrection ? 1 : 0); + response.getPlutoSdrMimoSettings()->setFcPosRx((int) settings.m_fcPosRx); + response.getPlutoSdrMimoSettings()->setRxTransverterMode(settings.m_rxTransverterMode ? 1 : 0); + response.getPlutoSdrMimoSettings()->setRxTransverterDeltaFrequency(settings.m_rxTransverterDeltaFrequency); + response.getPlutoSdrMimoSettings()->setIqOrder(settings.m_iqOrder ? 1 : 0); + response.getPlutoSdrMimoSettings()->setLpfBwRx(settings.m_lpfBWRx); + response.getPlutoSdrMimoSettings()->setLpfRxFirEnable(settings.m_lpfRxFIREnable ? 1 : 0); + response.getPlutoSdrMimoSettings()->setLpfRxFirbw(settings.m_lpfRxFIRBW); + response.getPlutoSdrMimoSettings()->setLpfRxFiRlog2Decim(settings.m_lpfRxFIRlog2Decim); + response.getPlutoSdrMimoSettings()->setLpfRxFirGain(settings.m_lpfRxFIRGain); + response.getPlutoSdrMimoSettings()->setRx0Gain(settings.m_rx0Gain); + response.getPlutoSdrMimoSettings()->setRx0GainMode((int) settings.m_rx0GainMode); + response.getPlutoSdrMimoSettings()->setRx0AntennaPath((int) settings.m_rx0AntennaPath); + response.getPlutoSdrMimoSettings()->setRx1Gain(settings.m_rx1Gain); + response.getPlutoSdrMimoSettings()->setRx1GainMode((int) settings.m_rx1GainMode); + response.getPlutoSdrMimoSettings()->setRx1AntennaPath((int) settings.m_rx1AntennaPath); + response.getPlutoSdrMimoSettings()->setTxCenterFrequency(settings.m_txCenterFrequency); + response.getPlutoSdrMimoSettings()->setFcPosTx((int) settings.m_fcPosTx); + response.getPlutoSdrMimoSettings()->setTxTransverterMode(settings.m_txTransverterMode ? 1 : 0); + response.getPlutoSdrMimoSettings()->setTxTransverterDeltaFrequency(settings.m_txTransverterDeltaFrequency); + response.getPlutoSdrMimoSettings()->setLpfBwTx(settings.m_lpfBWTx); + response.getPlutoSdrMimoSettings()->setLpfTxFirEnable(settings.m_lpfTxFIREnable ? 1 : 0); + response.getPlutoSdrMimoSettings()->setLpfTxFirbw(settings.m_lpfTxFIRBW); + response.getPlutoSdrMimoSettings()->setLpfTxFiRlog2Interp(settings.m_lpfTxFIRlog2Interp); + response.getPlutoSdrMimoSettings()->setLpfTxFirGain(settings.m_lpfTxFIRGain); + response.getPlutoSdrMimoSettings()->setLog2Interp(settings.m_log2Interp); + response.getPlutoSdrMimoSettings()->setTx0Att(settings.m_tx0Att); + response.getPlutoSdrMimoSettings()->setTx0AntennaPath((int) settings.m_tx0AntennaPath); + response.getPlutoSdrMimoSettings()->setTx1Att(settings.m_tx1Att); + response.getPlutoSdrMimoSettings()->setTx1AntennaPath((int) settings.m_tx1AntennaPath); + response.getBladeRf2MimoSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); + + if (response.getBladeRf2MimoSettings()->getReverseApiAddress()) { + *response.getBladeRf2MimoSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress; + } else { + response.getBladeRf2MimoSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress)); + } + + response.getBladeRf2MimoSettings()->setReverseApiPort(settings.m_reverseAPIPort); + response.getBladeRf2MimoSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex); +} + +int PlutoSDRMIMO::webapiRunGet( + int subsystemIndex, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage) +{ + if ((subsystemIndex == 0) || (subsystemIndex == 1)) + { + m_deviceAPI->getDeviceEngineStateStr(*response.getState(), subsystemIndex); + return 200; + } + else + { + errorMessage = QString("Subsystem invalid: must be 0 (Rx) or 1 (Tx)"); + return 404; + } +} + +int PlutoSDRMIMO::webapiRun( + bool run, + int subsystemIndex, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage) +{ + if ((subsystemIndex == 0) || (subsystemIndex == 1)) + { + m_deviceAPI->getDeviceEngineStateStr(*response.getState(), subsystemIndex); + MsgStartStop *message = MsgStartStop::create(run, subsystemIndex == 0); + m_inputMessageQueue.push(message); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgStartStop *msgToGUI = MsgStartStop::create(run, subsystemIndex == 0); + m_guiMessageQueue->push(msgToGUI); + } + + return 200; + } + else + { + errorMessage = QString("Subsystem invalid: must be 0 (Rx) or 1 (Tx)"); + return 404; + } +} + +void PlutoSDRMIMO::webapiReverseSendSettings(QList& deviceSettingsKeys, const PlutoSDRMIMOSettings& settings, bool force) +{ + SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings(); + swgDeviceSettings->setDirection(2); // MIMO + swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex()); + swgDeviceSettings->setDeviceHwType(new QString("PlutoSDR")); + swgDeviceSettings->setPlutoSdrMimoSettings(new SWGSDRangel::SWGPlutoSdrMIMOSettings()); + SWGSDRangel::SWGPlutoSdrMIMOSettings *swgPlutoSDRMIMOSettings = swgDeviceSettings->getPlutoSdrMimoSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (deviceSettingsKeys.contains("devSampleRate") || force) { + swgPlutoSDRMIMOSettings->setDevSampleRate(settings.m_devSampleRate); + } + if (deviceSettingsKeys.contains("LOppmTenths")) { + swgPlutoSDRMIMOSettings->setLOppmTenths(settings.m_LOppmTenths); + } + if (deviceSettingsKeys.contains("rxCenterFrequency")) { + swgPlutoSDRMIMOSettings->setRxCenterFrequency(settings.m_rxCenterFrequency); + } + if (deviceSettingsKeys.contains("dcBlock")) { + swgPlutoSDRMIMOSettings->setDcBlock(settings.m_dcBlock ? 1 : 0); + } + if (deviceSettingsKeys.contains("iqCorrection")) { + swgPlutoSDRMIMOSettings->setIqCorrection(settings.m_iqCorrection ? 1 : 0); + } + if (deviceSettingsKeys.contains("hwBBDCBlock")) { + swgPlutoSDRMIMOSettings->setHwBbdcBlock(settings.m_hwBBDCBlock ? 1 : 0); + } + if (deviceSettingsKeys.contains("hwRFDCBlock")) { + swgPlutoSDRMIMOSettings->setHwRfdcBlock(settings.m_hwRFDCBlock ? 1 : 0); + } + if (deviceSettingsKeys.contains("hwIQCorrection")) { + swgPlutoSDRMIMOSettings->setHwIqCorrection(settings.m_hwIQCorrection ? 1 : 0); + } + if (deviceSettingsKeys.contains("fcPosRx")) { + swgPlutoSDRMIMOSettings->setFcPosRx((int) settings.m_fcPosRx); + } + if (deviceSettingsKeys.contains("rxTransverterMode")) { + swgPlutoSDRMIMOSettings->setRxTransverterMode(settings.m_rxTransverterMode ? 1 : 0); + } + if (deviceSettingsKeys.contains("rxTransverterDeltaFrequency")) { + swgPlutoSDRMIMOSettings->setRxTransverterDeltaFrequency(settings.m_rxTransverterDeltaFrequency); + } + if (deviceSettingsKeys.contains("iqOrder")) { + swgPlutoSDRMIMOSettings->setIqOrder(settings.m_iqOrder ? 1 : 0); + } + if (deviceSettingsKeys.contains("lpfBWRx")) { + swgPlutoSDRMIMOSettings->setLpfBwRx(settings.m_lpfBWRx); + } + if (deviceSettingsKeys.contains("lpfRxFIREnable")) { + swgPlutoSDRMIMOSettings->setLpfRxFirEnable(settings.m_lpfRxFIREnable ? 1 : 0); + } + if (deviceSettingsKeys.contains("lpfRxFIRBW")) { + swgPlutoSDRMIMOSettings->setLpfRxFirbw(settings.m_lpfRxFIRBW); + } + if (deviceSettingsKeys.contains("lpfRxFIRlog2Decim")) { + swgPlutoSDRMIMOSettings->setLpfRxFiRlog2Decim(settings.m_lpfRxFIRlog2Decim); + } + if (deviceSettingsKeys.contains("lpfRxFIRGain")) { + swgPlutoSDRMIMOSettings->setLpfRxFirGain(settings.m_lpfRxFIRGain); + } + if (deviceSettingsKeys.contains("log2Decim")) { + swgPlutoSDRMIMOSettings->setLog2Decim(settings.m_log2Decim); + } + if (deviceSettingsKeys.contains("rx0Gain")) { + swgPlutoSDRMIMOSettings->setRx0Gain(settings.m_rx0Gain); + } + if (deviceSettingsKeys.contains("rx0GainMode")) { + swgPlutoSDRMIMOSettings->setRx0GainMode((int) settings.m_rx0GainMode); + } + if (deviceSettingsKeys.contains("rx0AntennaPath")) { + swgPlutoSDRMIMOSettings->setRx0AntennaPath((int) settings.m_rx0AntennaPath); + } + if (deviceSettingsKeys.contains("rx1Gain")) { + swgPlutoSDRMIMOSettings->setRx1Gain(settings.m_rx1Gain); + } + if (deviceSettingsKeys.contains("rx1GainMode")) { + swgPlutoSDRMIMOSettings->setRx1GainMode((int) settings.m_rx1GainMode); + } + if (deviceSettingsKeys.contains("rx1AntennaPath")) { + swgPlutoSDRMIMOSettings->setRx1AntennaPath((int) settings.m_rx1AntennaPath); + } + if (deviceSettingsKeys.contains("txCenterFrequency")) { + swgPlutoSDRMIMOSettings->setTxCenterFrequency(settings.m_txCenterFrequency); + } + if (deviceSettingsKeys.contains("fcPosTx")) { + swgPlutoSDRMIMOSettings->setFcPosTx((int) settings.m_fcPosTx); + } + if (deviceSettingsKeys.contains("txTransverterMode")) { + swgPlutoSDRMIMOSettings->setTxTransverterMode(settings.m_txTransverterMode ? 1 : 0); + } + if (deviceSettingsKeys.contains("txTransverterDeltaFrequency")) { + swgPlutoSDRMIMOSettings->setTxTransverterDeltaFrequency(settings.m_txTransverterDeltaFrequency); + } + if (deviceSettingsKeys.contains("lpfBWTx")) { + swgPlutoSDRMIMOSettings->setLpfBwTx(settings.m_lpfBWTx); + } + if (deviceSettingsKeys.contains("lpfTxFIREnable")) { + swgPlutoSDRMIMOSettings->setLpfTxFirEnable(settings.m_lpfTxFIREnable ? 1 : 0); + } + if (deviceSettingsKeys.contains("lpfTxFIRBW")) { + swgPlutoSDRMIMOSettings->setLpfTxFirbw(settings.m_lpfTxFIRBW); + } + if (deviceSettingsKeys.contains("lpfTxFIRlog2Interp")) { + swgPlutoSDRMIMOSettings->setLpfTxFiRlog2Interp(settings.m_lpfTxFIRlog2Interp); + } + if (deviceSettingsKeys.contains("lpfTxFIRGain")) { + swgPlutoSDRMIMOSettings->setLpfTxFirGain(settings.m_lpfTxFIRGain); + } + if (deviceSettingsKeys.contains("log2Interp")) { + swgPlutoSDRMIMOSettings->setLog2Interp(settings.m_log2Interp); + } + if (deviceSettingsKeys.contains("tx0Att")) { + swgPlutoSDRMIMOSettings->setTx0Att(settings.m_tx0Att); + } + if (deviceSettingsKeys.contains("tx0AntennaPath")) { + swgPlutoSDRMIMOSettings->setTx0AntennaPath((int) settings.m_tx0AntennaPath); + } + if (deviceSettingsKeys.contains("tx1Att")) { + swgPlutoSDRMIMOSettings->setTx1Att(settings.m_tx1Att); + } + if (deviceSettingsKeys.contains("tx1AntennaPath")) { + swgPlutoSDRMIMOSettings->setTx1AntennaPath((int) settings.m_tx1AntennaPath); + } + + QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex); + m_networkRequest.setUrl(QUrl(deviceSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgDeviceSettings->asJson().toUtf8()); + buffer->seek(0); + + // Always use PATCH to avoid passing reverse API settings + QNetworkReply *reply = m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + buffer->setParent(reply); + + delete swgDeviceSettings; +} + +void PlutoSDRMIMO::webapiReverseSendStartStop(bool start) +{ + SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings(); + swgDeviceSettings->setDirection(2); // MIMO + swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex()); + swgDeviceSettings->setDeviceHwType(new QString("PlutoSDR")); + + QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run") + .arg(m_settings.m_reverseAPIAddress) + .arg(m_settings.m_reverseAPIPort) + .arg(m_settings.m_reverseAPIDeviceIndex); + m_networkRequest.setUrl(QUrl(deviceSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgDeviceSettings->asJson().toUtf8()); + buffer->seek(0); + QNetworkReply *reply; + + if (start) { + reply = m_networkManager->sendCustomRequest(m_networkRequest, "POST", buffer); + } else { + reply = m_networkManager->sendCustomRequest(m_networkRequest, "DELETE", buffer); + } + + buffer->setParent(reply); + delete swgDeviceSettings; +} + +int PlutoSDRMIMO::webapiReportGet(SWGSDRangel::SWGDeviceReport& response, QString& errorMessage) +{ + (void) errorMessage; + response.setPlutoSdrMimoReport(new SWGSDRangel::SWGPlutoSdrMIMOReport()); + response.getPlutoSdrMimoReport()->init(); + webapiFormatDeviceReport(response); + return 200; +} + +void PlutoSDRMIMO::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response) +{ + response.getPlutoSdrMimoReport()->setAdcRate(getADCSampleRate()); + std::string rssiStr; + getRxRSSI(rssiStr, 0); + response.getPlutoSdrMimoReport()->setRssiRx0(new QString(rssiStr.c_str())); + getRxRSSI(rssiStr, 1); + response.getPlutoSdrMimoReport()->setRssiRx1(new QString(rssiStr.c_str())); + int gainDB; + getRxGain(gainDB, 0); + response.getPlutoSdrMimoReport()->setRx0GainDb(gainDB); + getRxGain(gainDB, 1); + response.getPlutoSdrMimoReport()->setRx1GainDb(gainDB); + response.getPlutoSdrMimoReport()->setDacRate(getDACSampleRate()); + getTxRSSI(rssiStr, 0); + response.getPlutoSdrMimoReport()->setRssiTx0(new QString(rssiStr.c_str())); + getTxRSSI(rssiStr, 1); + response.getPlutoSdrMimoReport()->setRssiTx1(new QString(rssiStr.c_str())); +} + +void PlutoSDRMIMO::networkManagerFinished(QNetworkReply *reply) +{ + QNetworkReply::NetworkError replyError = reply->error(); + + if (replyError) + { + qWarning() << "PlutoSDRMIMO::networkManagerFinished:" + << " error(" << (int) replyError + << "): " << replyError + << ": " << reply->errorString(); + } + else + { + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("PlutoSDRMIMO::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); + } + + reply->deleteLater(); +} + +void PlutoSDRMIMO::getRxRSSI(std::string& rssiStr, int chan) +{ + if (!m_open) + { + qDebug("PlutoSDRMIMO::getRxRSSI: device not open"); + return; + } + + if (m_plutoParams) + { + DevicePlutoSDRBox *plutoBox = m_plutoParams->getBox(); + + if (!plutoBox->getRxRSSI(rssiStr, chan)) { + rssiStr = "xxx dB"; + } + } +} + +void PlutoSDRMIMO::getTxRSSI(std::string& rssiStr, int chan) +{ + if (!m_open) + { + qDebug("PlutoSDRMIMO::getTxRSSI: device not open"); + return; + } + + if (m_plutoParams) + { + DevicePlutoSDRBox *plutoBox = m_plutoParams->getBox(); + + if (!plutoBox->getTxRSSI(rssiStr, chan)) { + rssiStr = "xxx dB"; + } + } + +} + +void PlutoSDRMIMO::getRxGain(int& gaindB, int chan) +{ + if (!m_open) + { + qDebug("PlutoSDRMIMO::getRxGain: device not open"); + return; + } + + if (m_plutoParams) + { + DevicePlutoSDRBox *plutoBox = m_plutoParams->getBox(); + + if (!plutoBox->getRxGain(gaindB, chan)) { + gaindB = 0; + } + } +} + +void PlutoSDRMIMO::getbbLPRange(quint32& minLimit, quint32& maxLimit) +{ + if (!m_open) + { + qDebug("PlutoSDRMIMO::getbbLPRange: device not open"); + return; + } + + if (m_plutoParams) + { + DevicePlutoSDRBox *plutoBox = m_plutoParams->getBox(); + + if (plutoBox) + { + uint32_t min, max; + plutoBox->getbbLPRxRange(min, max); + minLimit = min; + maxLimit = max; + } + } +} + +void PlutoSDRMIMO::getLORange(qint64& minLimit, qint64& maxLimit) +{ + if (!m_open) + { + qDebug("PlutoSDRMIMO::getLORange: device not open"); + return; + } + + if (m_plutoParams) + { + DevicePlutoSDRBox *plutoBox = m_plutoParams->getBox(); + + if (plutoBox) + { + uint64_t min, max; + plutoBox->getRxLORange(min, max); + minLimit = min; + maxLimit = max; + } + } +} + +bool PlutoSDRMIMO::fetchTemperature() +{ + if (!m_open) + { + qDebug("PlutoSDRMIMO::fetchTemperature: device not open"); + return false; + } + + if (m_plutoParams) + { + DevicePlutoSDRBox *plutoBox = m_plutoParams->getBox(); + + if (plutoBox) { + return plutoBox->fetchTemp(); + } + } + + return false; +} + +float PlutoSDRMIMO::getTemperature() +{ + if (!m_open) + { + qDebug("PlutoSDRMIMO::getTemperature: device not open"); + return 0.0; + } + + if (m_plutoParams) + { + DevicePlutoSDRBox *plutoBox = m_plutoParams->getBox(); + + if (plutoBox) { + return plutoBox->getTemp(); + } + } + + return 0.0; +} diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmimo.h b/plugins/samplemimo/plutosdrmimo/plutosdrmimo.h new file mode 100644 index 000000000..f646142bb --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmimo.h @@ -0,0 +1,200 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 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 _PLUTOSDR_PLUTOSDRMIMO_H_ +#define _PLUTOSDR_PLUTOSDRMIMO_H_ + +#include + +#include +#include +#include + +#include "dsp/devicesamplemimo.h" +#include "plutosdr/deviceplutosdrbox.h" + +#include "plutosdrmimosettings.h" + +class QNetworkAccessManager; +class QNetworkReply; +class DeviceAPI; +class PlutoSDRMIThread; +class PlutoSDRMOThread; +class DevicePlutoSDRParams; + +class PlutoSDRMIMO : public DeviceSampleMIMO { + Q_OBJECT + +public: + class MsgConfigurePlutoSDRMIMO : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const PlutoSDRMIMOSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigurePlutoSDRMIMO* create(const PlutoSDRMIMOSettings& settings, bool force) + { + return new MsgConfigurePlutoSDRMIMO(settings, force); + } + + private: + PlutoSDRMIMOSettings m_settings; + bool m_force; + + MsgConfigurePlutoSDRMIMO(const PlutoSDRMIMOSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + class MsgStartStop : public Message { + MESSAGE_CLASS_DECLARATION + + public: + bool getStartStop() const { return m_startStop; } + bool getRxElseTx() const { return m_rxElseTx; } + + static MsgStartStop* create(bool startStop, bool rxElseTx) { + return new MsgStartStop(startStop, rxElseTx); + } + + protected: + bool m_startStop; + bool m_rxElseTx; + + MsgStartStop(bool startStop, bool rxElseTx) : + Message(), + m_startStop(startStop), + m_rxElseTx(rxElseTx) + { } + }; + + PlutoSDRMIMO(DeviceAPI *deviceAPI); + virtual ~PlutoSDRMIMO(); + virtual void destroy(); + + virtual void init(); + virtual bool startRx(); + virtual void stopRx(); + virtual bool startTx(); + virtual void stopTx(); + + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); + + virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; } + virtual const QString& getDeviceDescription() const; + + virtual int getSourceSampleRate(int index) const; + virtual void setSourceSampleRate(int sampleRate, int index) { (void) sampleRate; (void) index; } + virtual quint64 getSourceCenterFrequency(int index) const; + virtual void setSourceCenterFrequency(qint64 centerFrequency, int index); + + virtual int getSinkSampleRate(int index) const; + virtual void setSinkSampleRate(int sampleRate, int index) { (void) sampleRate; (void) index; } + virtual quint64 getSinkCenterFrequency(int index) const; + virtual void setSinkCenterFrequency(qint64 centerFrequency, int index); + + virtual quint64 getMIMOCenterFrequency() const { return getSourceCenterFrequency(0); } + virtual unsigned int getMIMOSampleRate() const { return getSourceSampleRate(0); } + + virtual bool handleMessage(const Message& message); + + virtual int webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage); + + virtual int webapiReportGet( + SWGSDRangel::SWGDeviceReport& response, + QString& errorMessage); + + virtual int webapiRunGet( + int subsystemIndex, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage); + + virtual int webapiRun( + bool run, + int subsystemIndex, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage); + + static void webapiFormatDeviceSettings( + SWGSDRangel::SWGDeviceSettings& response, + const PlutoSDRMIMOSettings& settings); + + static void webapiUpdateDeviceSettings( + PlutoSDRMIMOSettings& settings, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response); + + int getNbRx() { return m_nbRx; } + int getNbTx() { return m_nbTx; } + bool getRxRunning() const { return m_runningRx; } + bool getTxRunning() const { return m_runningTx; } + uint32_t getADCSampleRate() const { return m_rxDeviceSampleRates.m_addaConnvRate; } + uint32_t getDACSampleRate() const { return m_txDeviceSampleRates.m_addaConnvRate; } + uint32_t getRxFIRSampleRate() const { return m_rxDeviceSampleRates.m_hb1Rate; } + uint32_t getTxFIRSampleRate() const { return m_txDeviceSampleRates.m_hb1Rate; } + void getRxRSSI(std::string& rssiStr, int chan); + void getTxRSSI(std::string& rssiStr, int chan); + void getRxGain(int& gainStr, int chan); + void getLORange(qint64& minLimit, qint64& maxLimit); + void getbbLPRange(quint32& minLimit, quint32& maxLimit); + bool fetchTemperature(); + float getTemperature(); + +private: + DeviceAPI *m_deviceAPI; + QMutex m_mutex; + PlutoSDRMIMOSettings m_settings; + PlutoSDRMIThread* m_sourceThread; + PlutoSDRMOThread* m_sinkThread; + DevicePlutoSDRBox::SampleRates m_rxDeviceSampleRates; + DevicePlutoSDRBox::SampleRates m_txDeviceSampleRates; + QString m_deviceDescription; + bool m_runningRx; + bool m_runningTx; + QNetworkAccessManager *m_networkManager; + QNetworkRequest m_networkRequest; + + DevicePlutoSDRParams *m_plutoParams; + bool m_open; + int m_nbRx; + int m_nbTx; + + bool openDevice(); + void closeDevice(); + + bool applySettings(const PlutoSDRMIMOSettings& settings, bool force); + void webapiReverseSendSettings(QList& deviceSettingsKeys, const PlutoSDRMIMOSettings& settings, bool force); + void webapiReverseSendStartStop(bool start); + void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response); + +private slots: + void networkManagerFinished(QNetworkReply *reply); +}; + +#endif // _PLUTOSDR_PLUTOSDRMIMO_H_ diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmimogui.cpp b/plugins/samplemimo/plutosdrmimo/plutosdrmimogui.cpp new file mode 100644 index 000000000..d2b8b8302 --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmimogui.cpp @@ -0,0 +1,848 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 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 "plugin/pluginapi.h" +#include "device/deviceapi.h" +#include "device/deviceuiset.h" +#include "gui/colormapper.h" +#include "gui/glspectrum.h" +#include "gui/crightclickenabler.h" +#include "gui/basicdevicesettingsdialog.h" +#include "dsp/dspengine.h" +#include "dsp/dspdevicemimoengine.h" +#include "dsp/dspcommands.h" +#include "dsp/devicesamplestatic.h" +#include "dsp/devicesamplesource.h" +#include "dsp/devicesamplesink.h" +#include "util/db.h" +#include "plutosdr/deviceplutosdr.h" + +#include "mainwindow.h" + +#include "plutosdrmimo.h" +#include "ui_plutosdrmimogui.h" +#include "plutosdrmimogui.h" + +PlutoSDRMIMOGUI::PlutoSDRMIMOGUI(DeviceUISet *deviceUISet, QWidget* parent) : + DeviceGUI(parent), + ui(new Ui::PlutoSDRMIMOGUI), + m_deviceUISet(deviceUISet), + m_settings(), + m_rxElseTx(true), + m_streamIndex(0), + m_spectrumRxElseTx(true), + m_spectrumStreamIndex(0), + m_gainLock(false), + m_doApplySettings(true), + m_forceSettings(true), + m_sampleMIMO(nullptr), + m_tickCount(0), + m_rxBasebandSampleRate(3072000), + m_txBasebandSampleRate(3072000), + m_rxDeviceCenterFrequency(435000*1000), + m_txDeviceCenterFrequency(435000*1000), + m_lastRxEngineState(DeviceAPI::StNotStarted), + m_lastTxEngineState(DeviceAPI::StNotStarted), + m_statusCounter(0), + m_sampleRateMode(true) +{ + qDebug("PlutoSDRMIMOGui::PlutoSDRMIMOGui"); + ui->setupUi(this); + m_sampleMIMO = (PlutoSDRMIMO*) m_deviceUISet->m_deviceAPI->getSampleMIMO(); + + ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); + updateFrequencyLimits(); + + ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow)); + ui->sampleRate->setValueRange(8, DevicePlutoSDR::srLowLimitFreq, DevicePlutoSDR::srHighLimitFreq); + + ui->lpf->setColorMapper(ColorMapper(ColorMapper::GrayYellow)); + + quint32 minLimit, maxLimit; + ((PlutoSDRMIMO *) m_sampleMIMO)->getbbLPRange(minLimit, maxLimit); + ui->lpf->setValueRange(5, minLimit/1000, maxLimit/1000); + + ui->lpFIR->setColorMapper(ColorMapper(ColorMapper::GrayYellow)); + ui->lpFIR->setValueRange(5, 1U, 56000U); // will be dynamically recalculated + + ui->swDecimLabel->setText(QString::fromUtf8("S\u2193")); + ui->lpFIRDecimationLabel->setText(QString::fromUtf8("\u2193")); + + CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStopRx); + connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &))); + + blockApplySettings(true); + displaySettings(); + blockApplySettings(false); + + connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); + connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); + m_statusTimer.start(500); + + connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection); + m_sampleMIMO->setMessageQueueToGUI(&m_inputMessageQueue); +} + +PlutoSDRMIMOGUI::~PlutoSDRMIMOGUI() +{ + delete ui; +} + +void PlutoSDRMIMOGUI::destroy() +{ + delete this; +} + +void PlutoSDRMIMOGUI::resetToDefaults() +{ + m_settings.resetToDefaults(); + displaySettings(); + sendSettings(); +} + +QByteArray PlutoSDRMIMOGUI::serialize() const +{ + return m_settings.serialize(); +} + +bool PlutoSDRMIMOGUI::deserialize(const QByteArray& data) +{ + if (m_settings.deserialize(data)) + { + displaySettings(); + m_forceSettings = true; + sendSettings(); + return true; + } + else + { + resetToDefaults(); + return false; + } +} + +void PlutoSDRMIMOGUI::displaySettings() +{ + if (m_rxElseTx) + { + ui->transverter->setDeltaFrequency(m_settings.m_rxTransverterDeltaFrequency); + ui->transverter->setDeltaFrequencyActive(m_settings.m_rxTransverterMode); + ui->transverter->setIQOrder(m_settings.m_iqOrder); + updateFrequencyLimits(); + ui->centerFrequency->setValue(m_settings.m_rxCenterFrequency / 1000); + displaySampleRate(); + + ui->dcOffset->setChecked(m_settings.m_dcBlock); + ui->iqImbalance->setChecked(m_settings.m_iqCorrection); + ui->bbDCOffset->setChecked(m_settings.m_hwBBDCBlock); + ui->rfDCOffset->setChecked(m_settings.m_hwRFDCBlock); + ui->hwIQImbalance->setChecked(m_settings.m_hwIQCorrection); + ui->loPPM->setValue(m_settings.m_LOppmTenths); + ui->loPPMText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1))); + + ui->swDecim->setCurrentIndex(m_settings.m_log2Decim); + ui->fcPos->setCurrentIndex((int) m_settings.m_fcPosRx); + + ui->lpf->setValue(m_settings.m_lpfBWRx / 1000); + + ui->lpFIREnable->setChecked(m_settings.m_lpfRxFIREnable); + ui->lpFIR->setValue(m_settings.m_lpfRxFIRBW / 1000); + ui->lpFIRDecimation->setCurrentIndex(m_settings.m_lpfRxFIRlog2Decim); + ui->lpFIRGain->setCurrentIndex((m_settings.m_lpfRxFIRGain + 12)/6); + ui->lpFIRDecimation->setEnabled(m_settings.m_lpfRxFIREnable); + ui->lpFIRGain->setEnabled(m_settings.m_lpfRxFIREnable); + + ui->gainMode->setEnabled(true); + ui->gain->setEnabled(true); + ui->att->setEnabled(false); + + if (m_streamIndex == 0) + { + ui->gainMode->setCurrentIndex((int) m_settings.m_rx0GainMode); + ui->gain->setValue(m_settings.m_rx0Gain); + ui->gainText->setText(tr("%1").arg(m_settings.m_rx0Gain)); + ui->antenna->setCurrentIndex((int) m_settings.m_rx0AntennaPath); + } + else + { + ui->gainMode->setCurrentIndex((int) m_settings.m_rx1GainMode); + ui->gain->setValue(m_settings.m_rx1Gain); + ui->gainText->setText(tr("%1").arg(m_settings.m_rx1Gain)); + ui->antenna->setCurrentIndex((int) m_settings.m_rx1AntennaPath); + } + + setFIRBWLimits(); + setSampleRateLimits(); + } + else + { + ui->transverter->setDeltaFrequency(m_settings.m_txTransverterDeltaFrequency); + ui->transverter->setDeltaFrequencyActive(m_settings.m_txTransverterMode); + updateFrequencyLimits(); + ui->centerFrequency->setValue(m_settings.m_txCenterFrequency / 1000); + displaySampleRate(); + + ui->swDecim->setCurrentIndex(m_settings.m_log2Interp); + ui->fcPos->setCurrentIndex((int) m_settings.m_fcPosTx); + + ui->lpf->setValue(m_settings.m_lpfBWTx / 1000); + + ui->lpFIREnable->setChecked(m_settings.m_lpfTxFIREnable); + ui->lpFIR->setValue(m_settings.m_lpfTxFIRBW / 1000); + ui->lpFIRDecimation->setCurrentIndex(m_settings.m_lpfTxFIRlog2Interp); + ui->lpFIRGain->setCurrentIndex((m_settings.m_lpfTxFIRGain + 6)/6); + ui->lpFIRDecimation->setEnabled(m_settings.m_lpfTxFIREnable); + ui->lpFIRGain->setEnabled(m_settings.m_lpfTxFIREnable); + + ui->gainMode->setEnabled(false); + ui->gain->setEnabled(false); + ui->att->setEnabled(true); + + if (m_streamIndex == 0) + { + ui->att->setValue(m_settings.m_tx0Att); + ui->attText->setText(QString("%1 dB").arg(QString::number(m_settings.m_tx0Att*0.25, 'f', 2))); + ui->antenna->setCurrentIndex((int) m_settings.m_tx0AntennaPath); + } + else + { + ui->att->setValue(m_settings.m_tx1Att); + ui->attText->setText(QString("%1 dB").arg(QString::number(m_settings.m_tx1Att*0.25, 'f', 2))); + ui->antenna->setCurrentIndex((int) m_settings.m_tx1AntennaPath); + } + + setFIRBWLimits(); + setSampleRateLimits(); + } +} + +void PlutoSDRMIMOGUI::displaySampleRate() +{ + ui->sampleRate->blockSignals(true); + displayFcTooltip(); + + if (m_sampleRateMode) + { + ui->sampleRateMode->setStyleSheet("QToolButton { background:rgb(60,60,60); }"); + ui->sampleRateMode->setText("SR"); + ui->sampleRate->setValueRange(8, DevicePlutoSDR::srLowLimitFreq, DevicePlutoSDR::srHighLimitFreq); + ui->sampleRate->setValue(m_settings.m_devSampleRate); + ui->sampleRate->setToolTip("Device to host sample rate (S/s)"); + ui->deviceRateText->setToolTip("Baseband sample rate (S/s)"); + uint32_t basebandSampleRate = m_settings.m_devSampleRate/(1<deviceRateText->setText(tr("%1k").arg(QString::number(basebandSampleRate / 1000.0f, 'g', 5))); + } + else + { + ui->sampleRateMode->setStyleSheet("QToolButton { background:rgb(50,50,50); }"); + ui->sampleRateMode->setText("BB"); + ui->sampleRate->setValueRange(8, DevicePlutoSDR::srLowLimitFreq/(1<sampleRate->setValue(m_settings.m_devSampleRate/(1<sampleRate->setToolTip("Baseband sample rate (S/s)"); + ui->deviceRateText->setToolTip("Device to host sample rate (S/s)"); + ui->deviceRateText->setText(tr("%1k").arg(QString::number(m_settings.m_devSampleRate / 1000.0f, 'g', 5))); + } + + ui->sampleRate->blockSignals(false); +} + +void PlutoSDRMIMOGUI::displayFcTooltip() +{ + if (m_rxElseTx) + { + int32_t fShift = DeviceSampleSource::calculateFrequencyShift( + m_settings.m_log2Decim, + (DeviceSampleSource::fcPos_t) m_settings.m_fcPosRx, + m_settings.m_devSampleRate, + DeviceSampleSource::FrequencyShiftScheme::FSHIFT_STD + ); + ui->fcPos->setToolTip(tr("Relative position of device center frequency: %1 kHz").arg(QString::number(fShift / 1000.0f, 'g', 5))); + } + else + { + int32_t fShift = DeviceSampleSink::calculateFrequencyShift( + m_settings.m_log2Interp, + (DeviceSampleSink::fcPos_t) m_settings.m_fcPosTx, + m_settings.m_devSampleRate + ); + ui->fcPos->setToolTip(tr("Relative position of device center frequency: %1 kHz").arg(QString::number(fShift / 1000.0f, 'g', 5))); + } +} + +void PlutoSDRMIMOGUI::sendSettings(bool forceSettings) +{ + m_forceSettings = forceSettings; + if(!m_updateTimer.isActive()) { m_updateTimer.start(100); } +} + +void PlutoSDRMIMOGUI::updateHardware() +{ + if (m_doApplySettings) + { + qDebug() << "PlutoSDRMIMOGUI::updateHardware"; + PlutoSDRMIMO::MsgConfigurePlutoSDRMIMO* message = PlutoSDRMIMO::MsgConfigurePlutoSDRMIMO::create(m_settings, m_forceSettings); + m_sampleMIMO->getInputMessageQueue()->push(message); + m_forceSettings = false; + m_updateTimer.stop(); + } +} + +void PlutoSDRMIMOGUI::blockApplySettings(bool block) +{ + m_doApplySettings = !block; +} + +void PlutoSDRMIMOGUI::updateSampleRateAndFrequency() +{ + if (m_rxElseTx) + { + m_deviceUISet->getSpectrum()->setSampleRate(m_settings.m_devSampleRate/(1<getSpectrum()->setCenterFrequency(m_rxDeviceCenterFrequency); + } + else + { + m_deviceUISet->getSpectrum()->setSampleRate(m_settings.m_devSampleRate/(1<getSpectrum()->setCenterFrequency(m_txDeviceCenterFrequency); + } + + displaySampleRate(); +} + +void PlutoSDRMIMOGUI::setFIRBWLimits() +{ + if (m_rxElseTx) + { + float high = DevicePlutoSDR::firBWHighLimitFactor * m_sampleMIMO->getRxFIRSampleRate(); + float low = DevicePlutoSDR::firBWLowLimitFactor * m_sampleMIMO->getRxFIRSampleRate(); + ui->lpFIR->setValueRange(5, (int(low)/1000)+1, (int(high)/1000)+1); + ui->lpFIR->setValue(m_settings.m_lpfRxFIRBW/1000); + } + else + { + float high = DevicePlutoSDR::firBWHighLimitFactor * m_sampleMIMO->getTxFIRSampleRate(); + float low = DevicePlutoSDR::firBWLowLimitFactor * m_sampleMIMO->getTxFIRSampleRate(); + ui->lpFIR->setValueRange(5, (int(low)/1000)+1, (int(high)/1000)+1); + ui->lpFIR->setValue(m_settings.m_lpfTxFIRBW/1000); + } +} + +void PlutoSDRMIMOGUI::setSampleRateLimits() +{ + uint32_t low = ui->lpFIREnable->isChecked() ? DevicePlutoSDR::srLowLimitFreq / (1<lpFIRDecimation->currentIndex()) : DevicePlutoSDR::srLowLimitFreq; + ui->sampleRate->setValueRange(8, low, DevicePlutoSDR::srHighLimitFreq); + ui->sampleRate->setValue(m_settings.m_devSampleRate); +} + +void PlutoSDRMIMOGUI::updateFrequencyLimits() +{ + qint64 minLimit, maxLimit; + qint64 deltaFrequency; + // values should be in kHz + if (m_rxElseTx) { + deltaFrequency = m_settings.m_rxTransverterMode ? m_settings.m_rxTransverterDeltaFrequency/1000 : 0; + } else { + deltaFrequency = m_settings.m_txTransverterMode ? m_settings.m_txTransverterDeltaFrequency/1000 : 0; + } + + m_sampleMIMO->getLORange(minLimit, maxLimit); + + minLimit = minLimit/1000 + deltaFrequency; + maxLimit = maxLimit/1000 + deltaFrequency; + + minLimit = minLimit < 0 ? 0 : minLimit > 9999999 ? 9999999 : minLimit; + maxLimit = maxLimit < 0 ? 0 : maxLimit > 9999999 ? 9999999 : maxLimit; + + qDebug("PlutoSDRMIMOGUI::updateFrequencyLimits: delta: %lld min: %lld max: %lld", deltaFrequency, minLimit, maxLimit); + + ui->centerFrequency->setValueRange(7, minLimit, maxLimit); +} + +bool PlutoSDRMIMOGUI::handleMessage(const Message& message) +{ + if (DSPMIMOSignalNotification::match(message)) + { + const DSPMIMOSignalNotification& notif = (const DSPMIMOSignalNotification&) message; + int istream = notif.getIndex(); + bool sourceOrSink = notif.getSourceOrSink(); + + if (sourceOrSink) + { + m_rxBasebandSampleRate = notif.getSampleRate(); + m_rxDeviceCenterFrequency = notif.getCenterFrequency(); + } + else + { + m_txBasebandSampleRate = notif.getSampleRate(); + m_txDeviceCenterFrequency = notif.getCenterFrequency(); + } + + qDebug("PlutoSDRMIMOGUI::handleInputMessages: DSPMIMOSignalNotification: %s stream: %d SampleRate:%d, CenterFrequency:%llu", + sourceOrSink ? "source" : "sink", + istream, + notif.getSampleRate(), + notif.getCenterFrequency()); + + updateSampleRateAndFrequency(); + + return true; + } + else if (PlutoSDRMIMO::MsgConfigurePlutoSDRMIMO::match(message)) + { + const PlutoSDRMIMO::MsgConfigurePlutoSDRMIMO& notif = (const PlutoSDRMIMO::MsgConfigurePlutoSDRMIMO&) message; + m_settings = notif.getSettings(); + displaySettings(); + + return true; + } + + return false; +} + +void PlutoSDRMIMOGUI::handleInputMessages() +{ + Message* message; + + while ((message = m_inputMessageQueue.pop()) != 0) + { + if (handleMessage(*message)) { + delete message; + } else { + qDebug("PlutoSDRMIMOGUI::handleInputMessages: unhandled message: %s", message->getIdentifier()); + } + } +} + +void PlutoSDRMIMOGUI::updateStatus() +{ + int stateRx = m_deviceUISet->m_deviceAPI->state(0); + int stateTx = m_deviceUISet->m_deviceAPI->state(1); + + if (m_lastRxEngineState != stateRx) + { + switch(stateRx) + { + case DeviceAPI::StNotStarted: + ui->startStopRx->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); + break; + case DeviceAPI::StIdle: + ui->startStopRx->setStyleSheet("QToolButton { background-color : blue; }"); + break; + case DeviceAPI::StRunning: + ui->startStopRx->setStyleSheet("QToolButton { background-color : green; }"); + break; + case DeviceAPI::StError: + ui->startStopRx->setStyleSheet("QToolButton { background-color : red; }"); + QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage()); + break; + default: + break; + } + + m_lastRxEngineState = stateRx; + } + + if (m_lastTxEngineState != stateTx) + { + switch(stateTx) + { + case DeviceAPI::StNotStarted: + ui->startStopTx->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); + break; + case DeviceAPI::StIdle: + ui->startStopTx->setStyleSheet("QToolButton { background-color : blue; }"); + break; + case DeviceAPI::StRunning: + ui->startStopTx->setStyleSheet("QToolButton { background-color : green; }"); + break; + case DeviceAPI::StError: + ui->startStopTx->setStyleSheet("QToolButton { background-color : red; }"); + QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage()); + break; + default: + break; + } + + m_lastTxEngineState = stateTx; + } + + + if (m_statusCounter % 2 == 0) // 1s + { + uint32_t samplerRate; + + if (m_rxElseTx) { + samplerRate = m_sampleMIMO->getADCSampleRate(); + } else { + samplerRate = m_sampleMIMO->getDACSampleRate(); + } + + if (samplerRate < 100000000) { + ui->adcRateText->setText(tr("%1k").arg(QString::number(samplerRate / 1000.0f, 'g', 5))); + } else { + ui->adcRateText->setText(tr("%1M").arg(QString::number(samplerRate / 1000000.0f, 'g', 5))); + } + } + + if (m_statusCounter % 4 == 0) // 2s + { + std::string rssiStr; + + if (m_rxElseTx) { + m_sampleMIMO->getRxRSSI(rssiStr, m_streamIndex); + } else { + m_sampleMIMO->getTxRSSI(rssiStr, m_streamIndex); + } + + ui->rssiText->setText(tr("-%1").arg(QString::fromStdString(rssiStr))); + int gaindB; + + if (m_rxElseTx) { + m_sampleMIMO->getRxGain(gaindB, m_streamIndex); + } else { + gaindB = 0; + } + + ui->actualGainText->setText(tr("%1").arg(gaindB)); + } + + if (m_statusCounter % 10 == 0) // 5s + { + m_sampleMIMO->fetchTemperature(); + ui->temperatureText->setText(tr("%1C").arg(QString::number(m_sampleMIMO->getTemperature(), 'f', 0))); + } + + m_statusCounter++; +} + +void PlutoSDRMIMOGUI::on_streamSide_currentIndexChanged(int index) +{ + m_rxElseTx = index == 0; + displaySettings(); +} + +void PlutoSDRMIMOGUI::on_streamIndex_currentIndexChanged(int index) +{ + m_streamIndex = index < 0 ? 0 : index > 1 ? 1 : index; + displaySettings(); +} + +void PlutoSDRMIMOGUI::on_spectrumSide_currentIndexChanged(int index) +{ + m_spectrumRxElseTx = (index == 0); + m_deviceUISet->m_spectrum->setDisplayedStream(m_spectrumRxElseTx, m_spectrumStreamIndex); + m_deviceUISet->m_deviceAPI->setSpectrumSinkInput(m_spectrumRxElseTx, m_spectrumStreamIndex); + m_deviceUISet->setSpectrumScalingFactor(m_spectrumRxElseTx ? SDR_RX_SCALEF : SDR_TX_SCALEF); + updateSampleRateAndFrequency(); +} + +void PlutoSDRMIMOGUI::on_spectrumIndex_currentIndexChanged(int index) +{ + m_spectrumStreamIndex = index < 0 ? 0 : index > 1 ? 1 : index; + m_deviceUISet->m_spectrum->setDisplayedStream(m_spectrumRxElseTx, m_spectrumStreamIndex); + m_deviceUISet->m_deviceAPI->setSpectrumSinkInput(m_spectrumRxElseTx, m_spectrumStreamIndex); + updateSampleRateAndFrequency(); +} + +void PlutoSDRMIMOGUI::on_startStopRx_toggled(bool checked) +{ + if (m_doApplySettings) + { + PlutoSDRMIMO::MsgStartStop *message = PlutoSDRMIMO::MsgStartStop::create(checked, true); + m_sampleMIMO->getInputMessageQueue()->push(message); + } +} + +void PlutoSDRMIMOGUI::on_startStopTx_toggled(bool checked) +{ + if (m_doApplySettings) + { + PlutoSDRMIMO::MsgStartStop *message = PlutoSDRMIMO::MsgStartStop::create(checked, false); + m_sampleMIMO->getInputMessageQueue()->push(message); + } +} + +void PlutoSDRMIMOGUI::on_centerFrequency_changed(quint64 value) +{ + if (m_rxElseTx) { + m_settings.m_rxCenterFrequency = value * 1000; + } else { + m_settings.m_txCenterFrequency = value * 1000; + } + + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_loPPM_valueChanged(int value) +{ + ui->loPPMText->setText(QString("%1").arg(QString::number(value/10.0, 'f', 1))); + m_settings.m_LOppmTenths = value; + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_dcOffset_toggled(bool checked) +{ + m_settings.m_dcBlock = checked; + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_iqImbalance_toggled(bool checked) +{ + m_settings.m_iqCorrection = checked; + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_rfDCOffset_toggled(bool checked) +{ + m_settings.m_hwRFDCBlock = checked; + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_bbDCOffset_toggled(bool checked) +{ + m_settings.m_hwBBDCBlock = checked; + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_hwIQImbalance_toggled(bool checked) +{ + m_settings.m_hwIQCorrection = checked; + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_swDecim_currentIndexChanged(int index) +{ + if (m_rxElseTx) { + m_settings.m_log2Decim = index > 6 ? 6 : index; + } else { + m_settings.m_log2Interp = index > 6 ? 6 : index; + } + + displaySampleRate(); + m_settings.m_devSampleRate = ui->sampleRate->getValueNew(); + + if (!m_sampleRateMode) + { + if (m_rxElseTx) { + m_settings.m_devSampleRate <<= m_settings.m_log2Decim; + } else { + m_settings.m_devSampleRate <<= m_settings.m_log2Interp; + } + } + + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_fcPos_currentIndexChanged(int index) +{ + PlutoSDRMIMOSettings::fcPos_t fcPos = (PlutoSDRMIMOSettings::fcPos_t) (index < (int) PlutoSDRMIMOSettings::FC_POS_END ? index : PlutoSDRMIMOSettings::FC_POS_CENTER); + + if (m_rxElseTx) { + m_settings.m_fcPosRx = fcPos; + } else { + m_settings.m_fcPosTx = fcPos; + } + + displayFcTooltip(); + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_sampleRate_changed(quint64 value) +{ + m_settings.m_devSampleRate = value; + + if (!m_sampleRateMode) + { + if (m_rxElseTx) { + m_settings.m_devSampleRate <<= m_settings.m_log2Decim; + } else { + m_settings.m_devSampleRate <<= m_settings.m_log2Interp; + } + } + + displayFcTooltip(); + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_lpf_changed(quint64 value) +{ + if (m_rxElseTx) { + m_settings.m_lpfBWRx = value * 1000; + } else { + m_settings.m_lpfBWTx = value * 1000; + } + + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_lpFIREnable_toggled(bool checked) +{ + if (m_rxElseTx) { + m_settings.m_lpfRxFIREnable = checked; + } else { + m_settings.m_lpfTxFIREnable = checked; + } + + ui->lpFIRDecimation->setEnabled(checked); + ui->lpFIRGain->setEnabled(checked); + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_lpFIR_changed(quint64 value) +{ + if (m_rxElseTx) { + m_settings.m_lpfRxFIRBW = value * 1000; + } else { + m_settings.m_lpfTxFIRBW = value * 1000; + } + + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_lpFIRDecimation_currentIndexChanged(int index) +{ + if (m_rxElseTx) { + m_settings.m_lpfRxFIRlog2Decim = index > 2 ? 2 : index; + } else { + m_settings.m_lpfTxFIRlog2Interp = index > 2 ? 2 : index; + } + + setSampleRateLimits(); + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_lpFIRGain_currentIndexChanged(int index) +{ + if (m_rxElseTx) { + m_settings.m_lpfRxFIRGain = 6*(index > 3 ? 3 : index) - 12; + } else { + m_settings.m_lpfTxFIRGain = 6*(index > 3 ? 3 : index) - 12; + } + + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_gainMode_currentIndexChanged(int index) +{ + if (m_streamIndex == 0) + { + m_settings.m_rx0GainMode = (PlutoSDRMIMOSettings::GainMode) (index < PlutoSDRMIMOSettings::GAIN_END ? index : 0); + ui->gain->setEnabled(m_settings.m_rx0GainMode == PlutoSDRMIMOSettings::GAIN_MANUAL); + } + else + { + m_settings.m_rx1GainMode = (PlutoSDRMIMOSettings::GainMode) (index < PlutoSDRMIMOSettings::GAIN_END ? index : 0); + ui->gain->setEnabled(m_settings.m_rx1GainMode == PlutoSDRMIMOSettings::GAIN_MANUAL); + } + + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_gain_valueChanged(int value) +{ + ui->gainText->setText(tr("%1").arg(value)); + + if (m_streamIndex == 0) { + m_settings.m_rx0Gain = value; + } else { + m_settings.m_rx1Gain = value; + } + + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_antenna_currentIndexChanged(int index) +{ + if (m_rxElseTx) + { + if (m_streamIndex == 0) { + m_settings.m_rx0AntennaPath = (PlutoSDRMIMOSettings::RFPathRx) (index < PlutoSDRMIMOSettings::RFPATHRX_END ? index : 0); + } else { + m_settings.m_rx1AntennaPath = (PlutoSDRMIMOSettings::RFPathRx) (index < PlutoSDRMIMOSettings::RFPATHRX_END ? index : 0); + } + } + else + { + if (m_streamIndex == 0) { + m_settings.m_tx0AntennaPath = (PlutoSDRMIMOSettings::RFPathTx) (index < PlutoSDRMIMOSettings::RFPATHTX_END ? index : 0); + } else { + m_settings.m_tx1AntennaPath = (PlutoSDRMIMOSettings::RFPathTx) (index < PlutoSDRMIMOSettings::RFPATHTX_END ? index : 0); + } + } + + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_transverter_clicked() +{ + if (m_rxElseTx) + { + m_settings.m_rxTransverterMode = ui->transverter->getDeltaFrequencyAcive(); + m_settings.m_rxTransverterDeltaFrequency = ui->transverter->getDeltaFrequency(); + m_settings.m_iqOrder = ui->transverter->getIQOrder(); + qDebug("PlutoSDRInputGui::on_transverter_clicked: %lld Hz %s", + m_settings.m_rxTransverterDeltaFrequency, m_settings.m_rxTransverterMode ? "on" : "off"); + } + else + { + m_settings.m_txTransverterMode = ui->transverter->getDeltaFrequencyAcive(); + m_settings.m_txTransverterDeltaFrequency = ui->transverter->getDeltaFrequency(); + qDebug("PlutoSDRInputGui::on_transverter_clicked: %lld Hz %s", + m_settings.m_rxTransverterDeltaFrequency, m_settings.m_txTransverterMode ? "on" : "off"); + } + + updateFrequencyLimits(); + + if (m_rxElseTx) { + m_settings.m_rxCenterFrequency = ui->centerFrequency->getValueNew()*1000; + } else { + m_settings.m_txCenterFrequency = ui->centerFrequency->getValueNew()*1000; + } + + sendSettings(); +} + +void PlutoSDRMIMOGUI::on_sampleRateMode_toggled(bool checked) +{ + m_sampleRateMode = checked; + displaySampleRate(); +} + +void PlutoSDRMIMOGUI::openDeviceSettingsDialog(const QPoint& p) +{ + BasicDeviceSettingsDialog dialog(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.move(p); + dialog.exec(); + + m_settings.m_useReverseAPI = dialog.useReverseAPI(); + m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); + m_settings.m_reverseAPIPort = dialog.getReverseAPIPort(); + m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex(); + + sendSettings(); +} diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmimogui.h b/plugins/samplemimo/plutosdrmimo/plutosdrmimogui.h new file mode 100644 index 000000000..d906cf6fa --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmimogui.h @@ -0,0 +1,120 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 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 _PLUTOSDRMIMO_PLUTOSDRMIMOGUI_H_ +#define _PLUTOSDRMIMO_PLUTOSDRMIMOGUI_H_ + +#include +#include + +#include "util/messagequeue.h" +#include "device/devicegui.h" + +#include "plutosdrmimosettings.h" + +class DeviceUISet; +class PlutoSDRMIMO; + +namespace Ui { + class PlutoSDRMIMOGUI; +} + +class PlutoSDRMIMOGUI : public DeviceGUI { + Q_OBJECT +public: + explicit PlutoSDRMIMOGUI(DeviceUISet *deviceUISet, QWidget* parent = nullptr); + virtual ~PlutoSDRMIMOGUI(); + virtual void destroy(); + + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + +private: + Ui::PlutoSDRMIMOGUI* ui; + + DeviceUISet* m_deviceUISet; + PlutoSDRMIMOSettings m_settings; + bool m_rxElseTx; //!< Which side is being dealt with + int m_streamIndex; //!< Current stream index being dealt with + bool m_spectrumRxElseTx; + int m_spectrumStreamIndex; //!< Index of the stream displayed on main spectrum + bool m_gainLock; //!< Lock Rx or Tx channel gains (set channel gains to gain of channel 0 when engaged) + QTimer m_updateTimer; + QTimer m_statusTimer; + bool m_doApplySettings; + bool m_forceSettings; + PlutoSDRMIMO* m_sampleMIMO; + std::size_t m_tickCount; + int m_rxBasebandSampleRate; + int m_txBasebandSampleRate; + quint64 m_rxDeviceCenterFrequency; //!< Center frequency in Rx device + quint64 m_txDeviceCenterFrequency; //!< Center frequency in Tx device + int m_lastRxEngineState; + int m_lastTxEngineState; + uint32_t m_statusCounter; + MessageQueue m_inputMessageQueue; + bool m_sampleRateMode; + + void displaySettings(); + void displaySampleRate(); + void displayFcTooltip(); + void sendSettings(bool forceSettings = false); + void blockApplySettings(bool block); + void updateSampleRateAndFrequency(); + void setFIRBWLimits(); + void setSampleRateLimits(); + void updateFrequencyLimits(); + bool handleMessage(const Message& message); + +private slots: + void handleInputMessages(); + void updateHardware(); + void updateStatus(); + void on_streamSide_currentIndexChanged(int index); + void on_streamIndex_currentIndexChanged(int index); + void on_spectrumSide_currentIndexChanged(int index); + void on_spectrumIndex_currentIndexChanged(int index); + void on_startStopRx_toggled(bool checked); + void on_startStopTx_toggled(bool checked); + void on_centerFrequency_changed(quint64 value); + void on_loPPM_valueChanged(int value); + void on_dcOffset_toggled(bool checked); + void on_iqImbalance_toggled(bool checked); + void on_sampleRate_changed(quint64 value); + void on_sampleRateMode_toggled(bool checked); + void on_fcPos_currentIndexChanged(int index); + void on_swDecim_currentIndexChanged(int index); + void on_gainLock_toggled(bool checked); + void on_gainMode_currentIndexChanged(int index); + void on_gain_valueChanged(int value); + void on_transverter_clicked(); + void on_rfDCOffset_toggled(bool checked); + void on_bbDCOffset_toggled(bool checked); + void on_hwIQImbalance_toggled(bool checked); + void on_lpf_changed(quint64 value); + void on_lpFIREnable_toggled(bool checked); + void on_lpFIR_changed(quint64 value); + void on_lpFIRDecimation_currentIndexChanged(int index); + void on_lpFIRGain_currentIndexChanged(int index); + void on_antenna_currentIndexChanged(int index); + + void openDeviceSettingsDialog(const QPoint& p); +}; + +#endif // _PLUTOSDRMIMO_PLUTOSDRMIMOGUI_H_ diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmimogui.ui b/plugins/samplemimo/plutosdrmimo/plutosdrmimogui.ui new file mode 100644 index 000000000..2000eebfa --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmimogui.ui @@ -0,0 +1,1283 @@ + + + PlutoSDRMIMOGUI + + + + 0 + 0 + 382 + 344 + + + + + 0 + 0 + + + + + 350 + 260 + + + + + Liberation Sans + 9 + + + + PlutoSDR MIMO + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + 6 + + + + + + 16777215 + 22 + + + + + + + :/antenna.png + + + + + + + + 45 + 16777215 + + + + Select Rx or Tx settings + + + + Rx + + + + + Tx + + + + + + + + + 35 + 16777215 + + + + Select stream index to which settings apply + + + + 0 + + + + + 1 + + + + + + + + + 16777215 + 22 + + + + + + + :/dsb.png + + + + + + + + 45 + 0 + + + + + 45 + 16777215 + + + + Select Rx or Tx spectrum + + + + Rx + + + + + Tx + + + + + + + + + 35 + 16777215 + + + + Select which stream index to display spectrum + + + + 0 + + + + + 1 + + + + + + + + Qt::Vertical + + + + + + + Rx + + + + + + + start/stop acquisition (Rx) + + + + + + + :/play.png + :/stop.png:/play.png + + + + + + + Tx + + + + + + + start/stop generation (Tx) + + + + + + + :/play.png + :/stop.png:/play.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 4 + + + + + + + + + + + + + 54 + 0 + + + + ADC rate before hardware downsampling (k or MS/s) + + + 00000k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 20 + + + + PointingHandCursor + + + Qt::StrongFocus + + + Main center frequency in kHz + + + + + + + 6 + + + 6 + + + + + + + kHz + + + + + + + + + + + + 54 + 0 + + + + Baseband I/Q sample rate kS/s + + + 00000k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + 2 + + + + + LO ppm + + + + + + + Local oscillator correction (ppm) + + + -200 + + + 200 + + + 1 + + + Qt::Horizontal + + + + + + + + 34 + 0 + + + + Local oscillator correction (ppm) + + + -00.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 24 + 24 + + + + Transverter frequency translation dialog + + + X + + + + + + + + + + + SW + + + + + + + Software DC offset removal + + + DC + + + + + + + Software automatic IQ imbalance correction + + + IQ + + + + + + + Qt::Vertical + + + + + + + HW + + + + + + + Hardware RF DC removal + + + RFDC + + + + + + + Hardware baseband DC removal + + + BBDC + + + + + + + Hardware IQ imbalance correction + + + IQ + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + 2 + + + + + Sw + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + 16777215 + + + + Software decimation factor + + + 0 + + + + 1 + + + + + 2 + + + + + 4 + + + + + 8 + + + + + 16 + + + + + 32 + + + + + 64 + + + + + + + + Fc + + + + + + + + 55 + 16777215 + + + + Relative position of device center frequency + + + + Inf + + + + + Sup + + + + + Cen + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + :/antenna.png + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + Input path + + + + Abal + + + + + Bbal + + + + + Cbal + + + + + An + + + + + Ap + + + + + Bn + + + + + Bp + + + + + Cn + + + + + Cp + + + + + Tx1 + + + + + Tx2 + + + + + Tx3 + + + + + + + + + + + + + 24 + 0 + + + + + 24 + 16777215 + + + + Toggle between device to host (SR) and base band (BB) sample rate input + + + SR + + + true + + + true + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 12 + 50 + false + + + + PointingHandCursor + + + Device to host sample rate + + + + + + + S/s + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + LP + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 12 + 50 + false + + + + PointingHandCursor + + + Analog lowpass filer bandwidth (kHz) + + + + + + + kHz + + + + + + + + + Qt::Horizontal + + + + + + + 2 + + + 2 + + + + + Enable or disable TSP digital FIR lowpass filter + + + FIR + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 12 + + + + PointingHandCursor + + + Digital FIR lowpass filers bandwidth (kHz) @ ~-6dB + + + + + + + kHz + + + + + + + D + + + + + + + + 50 + 16777215 + + + + FIR decimation changes lower sample rate limit (see documentation) + + + + 1 + + + + + 2 + + + + + 4 + + + + + + + + G + + + + + + + FIR gain (dB) + + + + -12 + + + + + -6 + + + + + 0 + + + + + +6 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 2 + + + 2 + + + + + + 54 + 16777215 + + + + Rx gain control mode (Manual, Slow attack AGC, Fast attack AGC, Hybrid AGC) + + + + Man + + + + + Slow + + + + + Fast + + + + + Hyb + + + + + + + + + 24 + 24 + + + + Rx gain setting (dB) in manual mode only + + + 1 + + + 77 + + + 1 + + + 20 + + + + + + + + 18 + 0 + + + + + 18 + 16777215 + + + + Rx gain value (dB) + + + 20 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 24 + 0 + + + + Rx actual gain (dB) + + + 00 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + + + + 24 + 24 + + + + Tx reverse gain (attenuation) setting (dB) + + + -359 + + + 0 + + + 1 + + + 1 + + + -50 + + + + + + + + 60 + 0 + + + + Tx gain value (dB) + + + -89.75 dB + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + + + + + 68 + 0 + + + + Channel RSSI indication (dB) + + + -100.00 dB + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + + + + 24 + 0 + + + + Board temperature (degrees C) + + + 00C + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + ValueDial + QWidget +
gui/valuedial.h
+ 1 +
+ + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
+ + TransverterButton + QPushButton +
gui/transverterbutton.h
+
+
+ + + + +
diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmimoplugin.cpp b/plugins/samplemimo/plutosdrmimo/plutosdrmimoplugin.cpp new file mode 100644 index 000000000..d23fa96d3 --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmimoplugin.cpp @@ -0,0 +1,142 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 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" +#include "util/simpleserializer.h" +#include "plutosdr/deviceplutosdr.h" + +#ifndef SERVER_MODE +#include "plutosdrmimogui.h" +#endif +#include "plutosdrmimo.h" +#include "plutosdrmimoplugin.h" +#include "plutosdrmimowebapiadapter.h" + +const PluginDescriptor PlutoSDRMIMOPlugin::m_pluginDescriptor = { + QStringLiteral("PlutoSDR"), + QStringLiteral("PlutoSDR MIMO"), + QStringLiteral("6.11.0"), + QStringLiteral("(c) Edouard Griffiths, F4EXB"), + QStringLiteral("https://github.com/f4exb/sdrangel"), + true, + QStringLiteral("https://github.com/f4exb/sdrangel") +}; + +static constexpr const char* const m_hardwareID = "PlutoSDR"; +static constexpr const char* const m_deviceTypeID = PLUTOSDRMIMO_DEVICE_TYPE_ID; + +PlutoSDRMIMOPlugin::PlutoSDRMIMOPlugin(QObject* parent) : + QObject(parent) +{ +} + +const PluginDescriptor& PlutoSDRMIMOPlugin::getPluginDescriptor() const +{ + return m_pluginDescriptor; +} + +void PlutoSDRMIMOPlugin::initPlugin(PluginAPI* pluginAPI) +{ + pluginAPI->registerSampleMIMO(m_deviceTypeID, this); +} + +void PlutoSDRMIMOPlugin::enumOriginDevices(QStringList& listedHwIds, OriginDevices& originDevices) +{ + if (listedHwIds.contains(m_hardwareID)) { // check if it was done + return; + } + + DevicePlutoSDR::instance().enumOriginDevices(m_hardwareID, originDevices); + listedHwIds.append(m_hardwareID); +} + +PluginInterface::SamplingDevices PlutoSDRMIMOPlugin::enumSampleMIMO(const OriginDevices& originDevices) +{ + SamplingDevices result; + + for (OriginDevices::const_iterator it = originDevices.begin(); it != originDevices.end(); ++it) + { + if (it->hardwareId == m_hardwareID) + { + QString displayedName = it->displayableName; + displayedName.replace(QString(":$1]"), QString("]")); + result.append(SamplingDevice( + displayedName, + m_hardwareID, + m_deviceTypeID, + it->serial, + it->sequence, + PluginInterface::SamplingDevice::PhysicalDevice, + PluginInterface::SamplingDevice::StreamMIMO, + 1, + 0 + )); + } + } + + return result; +} + +#ifdef SERVER_MODE +DeviceGUI* PlutoSDRMIMOPlugin::createSampleMIMOPluginInstanceGUI( + const QString& sourceId, + QWidget **widget, + DeviceUISet *deviceUISet) +{ + (void) sourceId; + (void) widget; + (void) deviceUISet; + return nullptr; +} +#else +DeviceGUI* PlutoSDRMIMOPlugin::createSampleMIMOPluginInstanceGUI( + const QString& sourceId, + QWidget **widget, + DeviceUISet *deviceUISet) +{ + if (sourceId == m_deviceTypeID) + { + PlutoSDRMIMOGUI* gui = new PlutoSDRMIMOGUI(deviceUISet); + *widget = gui; + return gui; + } + else + { + return nullptr; + } +} +#endif + +DeviceSampleMIMO *PlutoSDRMIMOPlugin::createSampleMIMOPluginInstance(const QString& mimoId, DeviceAPI *deviceAPI) +{ + if (mimoId == m_deviceTypeID) + { + PlutoSDRMIMO* input = new PlutoSDRMIMO(deviceAPI); + return input; + } + else + { + return nullptr; + } +} + +DeviceWebAPIAdapter *PlutoSDRMIMOPlugin::createDeviceWebAPIAdapter() const +{ + return new PlutoSDRMIMOWebAPIAdapter(); +} diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmimoplugin.h b/plugins/samplemimo/plutosdrmimo/plutosdrmimoplugin.h new file mode 100644 index 000000000..d6e74b2af --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmimoplugin.h @@ -0,0 +1,53 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 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 _PLUTOSDRMIMO_PLUTOSDRMIMOPLUGIN_H +#define _PLUTOSDRMIMO_PLUTOSDRMIMOPLUGIN_H + +#include +#include "plugin/plugininterface.h" + +class PluginAPI; + +#define PLUTOSDRMIMO_DEVICE_TYPE_ID "sdrangel.samplemimo.bladerf2mimo" + +class PlutoSDRMIMOPlugin : public QObject, public PluginInterface { + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID PLUTOSDRMIMO_DEVICE_TYPE_ID) + +public: + explicit PlutoSDRMIMOPlugin(QObject* parent = nullptr); + + const PluginDescriptor& getPluginDescriptor() const; + void initPlugin(PluginAPI* pluginAPI); + + virtual void enumOriginDevices(QStringList& listedHwIds, OriginDevices& originDevices); + virtual SamplingDevices enumSampleMIMO(const OriginDevices& originDevices); + + virtual DeviceGUI* createSampleMIMOPluginInstanceGUI( + const QString& sourceId, + QWidget **widget, + DeviceUISet *deviceUISet); + virtual DeviceSampleMIMO* createSampleMIMOPluginInstance(const QString& sourceId, DeviceAPI *deviceAPI); + virtual DeviceWebAPIAdapter* createDeviceWebAPIAdapter() const; + +private: + static const PluginDescriptor m_pluginDescriptor; +}; + +#endif // _PLUTOSDRMIMO_PLUTOSDRMIMOPLUGIN_H diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmimosettings.cpp b/plugins/samplemimo/plutosdrmimo/plutosdrmimosettings.cpp new file mode 100644 index 000000000..ceb4441d3 --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmimosettings.cpp @@ -0,0 +1,369 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 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 "plutosdrmimosettings.h" + +#include +#include "util/simpleserializer.h" + + +PlutoSDRMIMOSettings::PlutoSDRMIMOSettings() +{ + resetToDefaults(); +} + +void PlutoSDRMIMOSettings::resetToDefaults() +{ + m_devSampleRate = 2500 * 1000; + m_LOppmTenths = 0; + + m_rxCenterFrequency = 435000 * 1000; + m_fcPosRx = FC_POS_CENTER; + m_log2Decim = 0; + m_dcBlock = false; + m_iqCorrection = false; + m_hwBBDCBlock = true; + m_hwRFDCBlock = true; + m_hwIQCorrection = true; + m_lpfBWRx = 1500000; + m_lpfRxFIREnable = false; + m_lpfRxFIRBW = 500000U; + m_lpfRxFIRlog2Decim = 0; + m_lpfRxFIRGain = 0; + m_rxTransverterMode = false; + m_rxTransverterDeltaFrequency = 0; + m_iqOrder = true; + + m_rx0Gain = 40; + m_rx0AntennaPath = RFPATHRX_A_BAL; + m_rx0GainMode = GAIN_MANUAL; + + m_rx1Gain = 40; + m_rx1AntennaPath = RFPATHRX_A_BAL; + m_rx1GainMode = GAIN_MANUAL; + + m_txCenterFrequency = 435000 * 1000; + m_fcPosTx = FC_POS_CENTER; + m_log2Interp = 0; + m_lpfBWTx = 1500000; + m_lpfTxFIREnable = false; + m_lpfTxFIRBW = 500000U; + m_lpfTxFIRlog2Interp = 0; + m_lpfTxFIRGain = 0; + m_txTransverterMode = false; + m_txTransverterDeltaFrequency = 0; + + m_tx0Att = -50; + m_tx0AntennaPath = RFPATHTX_A; + + m_tx1Att = -50; + m_tx1AntennaPath = RFPATHTX_A; + + m_useReverseAPI = false; + m_reverseAPIAddress = "127.0.0.1"; + m_reverseAPIPort = 8888; + m_reverseAPIDeviceIndex = 0; +} + +QByteArray PlutoSDRMIMOSettings::serialize() const +{ + SimpleSerializer s(1); + + // Common + s.writeU64(1, m_devSampleRate); + s.writeS32(2, m_LOppmTenths); + + // Rx + s.writeU64(10, m_rxCenterFrequency); + s.writeS32(11, m_fcPosRx); + s.writeU32(12, m_log2Decim); + s.writeBool(13, m_dcBlock); + s.writeBool(14, m_iqCorrection); + s.writeBool(15, m_hwBBDCBlock); + s.writeBool(16, m_hwRFDCBlock); + s.writeBool(17, m_hwIQCorrection); + s.writeU32(18, m_lpfBWRx); + s.writeBool(19, m_lpfRxFIREnable); + s.writeS32(20, m_lpfRxFIRGain); + s.writeU32(21, m_lpfRxFIRlog2Decim); + s.writeU32(22, m_lpfRxFIRBW); + s.writeBool(23, m_rxTransverterMode); + s.writeS64(24, m_rxTransverterDeltaFrequency); + s.writeBool(25, m_iqOrder); + + // Rx0 + s.writeU32(40, m_rx0Gain); + s.writeS32(41, (int) m_rx0AntennaPath); + s.writeS32(42, (int) m_rx0GainMode); + + // Rx1 + s.writeU32(50, m_rx1Gain); + s.writeS32(51, (int) m_rx1AntennaPath); + s.writeS32(52, (int) m_rx1GainMode); + + // Tx + s.writeU64(60, m_txCenterFrequency); + s.writeS32(61, m_fcPosTx); + s.writeU32(62, m_log2Interp); + s.writeU32(63, m_lpfBWTx); + s.writeBool(64, m_lpfTxFIREnable); + s.writeU32(65, m_lpfTxFIRBW); + s.writeU32(66, m_lpfTxFIRlog2Interp); + s.writeS32(67, m_lpfTxFIRGain); + s.writeBool(68, m_txTransverterMode); + s.writeS64(69, m_txTransverterDeltaFrequency); + + // Tx0 + s.writeS32(80, m_tx0Att); + s.writeS32(81, (int) m_tx0AntennaPath); + + // Tx1 + s.writeS32(90, m_tx1Att); + s.writeS32(91, (int) m_tx1AntennaPath); + + // Reverse API + s.writeBool(100, m_useReverseAPI); + s.writeString(101, m_reverseAPIAddress); + s.writeU32(102, m_reverseAPIPort); + s.writeU32(103, m_reverseAPIDeviceIndex); + + return s.final(); +} + +bool PlutoSDRMIMOSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if (!d.isValid()) + { + resetToDefaults(); + return false; + } + + if (d.getVersion() == 1) + { + int intval; + uint32_t uintval; + + // Common + d.readU64(1, &m_devSampleRate, 2500 * 1000); + d.readS32(2, &m_LOppmTenths, 0); + + // Rx + d.readU64(10, &m_rxCenterFrequency, 435000*1000); + d.readS32(11, &intval, 0); + if ((intval < 0) || (intval > 2)) { + m_fcPosRx = FC_POS_CENTER; + } else { + m_fcPosRx = (fcPos_t) intval; + } + d.readU32(12, &m_log2Decim, 0); + d.readBool(13, &m_dcBlock, false); + d.readBool(14, &m_iqCorrection, false); + d.readBool(15, &m_hwBBDCBlock, true); + d.readBool(16, &m_hwRFDCBlock, true); + d.readBool(17, &m_hwIQCorrection, true); + d.readU32(18, &m_lpfBWRx, 1500000); + d.readBool(19, &m_lpfRxFIREnable, false); + d.readS32(20, &m_lpfRxFIRGain, 0); + d.readU32(21, &uintval, 0); + if (uintval > 2) { + m_lpfRxFIRlog2Decim = 2; + } else { + m_lpfRxFIRlog2Decim = uintval; + } + d.readU32(22, &m_lpfRxFIRBW, 500000U); + d.readBool(23, &m_rxTransverterMode, false); + d.readS64(24, &m_rxTransverterDeltaFrequency, 0); + d.readBool(25, &m_iqOrder, true); + + // Rx0 + d.readU32(40, &m_rx0Gain, 40); + d.readS32(41, &intval, 0); + if ((intval >= 0) && (intval < (int) RFPATHRX_END)) { + m_rx0AntennaPath = (RFPathRx) intval; + } else { + m_rx0AntennaPath = RFPATHRX_A_BAL; + } + d.readS32(42, &intval, 0); + if ((intval >= 0) && (intval < (int) GAIN_END)) { + m_rx0GainMode = (GainMode) intval; + } else { + m_rx0GainMode = GAIN_MANUAL; + } + + // Rx1 + d.readU32(50, &m_rx0Gain, 40); + d.readS32(51, &intval, 0); + if ((intval >= 0) && (intval < (int) RFPATHRX_END)) { + m_rx0AntennaPath = (RFPathRx) intval; + } else { + m_rx0AntennaPath = RFPATHRX_A_BAL; + } + d.readS32(52, &intval, 0); + if ((intval >= 0) && (intval < (int) GAIN_END)) { + m_rx0GainMode = (GainMode) intval; + } else { + m_rx0GainMode = GAIN_MANUAL; + } + + // Tx + d.readU64(60, &m_txCenterFrequency, 435000*1000); + d.readS32(61, &intval, 0); + if ((intval < 0) || (intval > 2)) { + m_fcPosTx = FC_POS_CENTER; + } else { + m_fcPosTx = (fcPos_t) intval; + } + d.readU32(62, &m_log2Interp, 0); + d.readU32(63, &m_lpfBWTx, 1500000); + d.readBool(64, &m_lpfTxFIREnable, false); + d.readU32(65, &m_lpfTxFIRBW, 500000U); + d.readU32(66, &uintval, 0); + if (uintval > 2) { + m_lpfTxFIRlog2Interp = 2; + } else { + m_lpfTxFIRlog2Interp = uintval; + } + d.readS32(67, &m_lpfTxFIRGain, 0); + d.readBool(68, &m_txTransverterMode, false); + d.readS64(69, &m_txTransverterDeltaFrequency, 0); + + // Tx0 + d.readS32(80, &m_tx0Att, -50); + d.readS32(81, &intval, 0); + if ((intval >= 0) && (intval < (int) RFPATHTX_END)) { + m_tx0AntennaPath = (RFPathTx) intval; + } else { + m_tx0AntennaPath = RFPATHTX_A; + } + + // Tx1 + d.readS32(80, &m_tx1Att, -50); + d.readS32(81, &intval, 0); + if ((intval >= 0) && (intval < (int) RFPATHTX_END)) { + m_tx1AntennaPath = (RFPathTx) intval; + } else { + m_tx1AntennaPath = RFPATHTX_A; + } + + // Reverse API + d.readBool(100, &m_useReverseAPI, false); + d.readString(101, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(102, &uintval, 0); + + if ((uintval > 1023) && (uintval < 65535)) { + m_reverseAPIPort = uintval; + } else { + m_reverseAPIPort = 8888; + } + + d.readU32(103, &uintval, 0); + m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval; + + return true; + } + else + { + resetToDefaults(); + return false; + } +} + +void PlutoSDRMIMOSettings::translateRFPathTx(RFPathTx path, QString& s) +{ + switch(path) + { + case RFPATHTX_A: + s = "A"; + break; + case RFPATHTX_B: + s = "B"; + break; + default: + s = "A"; + break; + } +} + +void PlutoSDRMIMOSettings::translateRFPathRx(RFPathRx path, QString& s) +{ + switch(path) + { + case RFPATHRX_A_BAL: + s = "A_BALANCED"; + break; + case RFPATHRX_B_BAL: + s = "B_BALANCED"; + break; + case RFPATHRX_C_BAL: + s = "C_BALANCED"; + break; + case RFPATHRX_A_NEG: + s = "A_N"; + break; + case RFPATHRX_A_POS: + s = "A_P"; + break; + case RFPATHRX_B_NEG: + s = "B_N"; + break; + case RFPATHRX_B_POS: + s = "B_P"; + break; + case RFPATHRX_C_NEG: + s = "C_N"; + break; + case RFPATHRX_C_POS: + s = "C_P"; + break; + case RFPATHRX_TX1MON: + s = "TX_MONITOR1"; + break; + case RFPATHRX_TX2MON: + s = "TX_MONITOR2"; + break; + case RFPATHRX_TX3MON: + s = "TX_MONITOR3"; + break; + default: + s = "A_BALANCED"; + break; + } +} + +void PlutoSDRMIMOSettings::translateGainMode(GainMode mode, QString& s) +{ + switch(mode) + { + case GAIN_MANUAL: + s = "manual"; + break; + case GAIN_AGC_SLOW: + s = "slow_attack"; + break; + case GAIN_AGC_FAST: + s = "fast_attack"; + break; + case GAIN_HYBRID: + s = "hybrid"; + break; + default: + s = "manual"; + break; + } +} diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmimosettings.h b/plugins/samplemimo/plutosdrmimo/plutosdrmimosettings.h new file mode 100644 index 000000000..d99efd8f2 --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmimosettings.h @@ -0,0 +1,136 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 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 _PLUTOSDR_PLUTOSDRMIMOSETTINGS_H_ +#define _PLUTOSDR_PLUTOSDRMIMOSETTINGS_H_ + +#include +#include +#include + +struct PlutoSDRMIMOSettings { + typedef enum { + FC_POS_INFRA = 0, + FC_POS_SUPRA, + FC_POS_CENTER, + FC_POS_END + } fcPos_t; + + enum RFPathRx + { + RFPATHRX_A_BAL = 0, + RFPATHRX_B_BAL, + RFPATHRX_C_BAL, + RFPATHRX_A_NEG, + RFPATHRX_A_POS, + RFPATHRX_B_NEG, + RFPATHRX_B_POS, + RFPATHRX_C_NEG, + RFPATHRX_C_POS, + RFPATHRX_TX1MON, + RFPATHRX_TX2MON, + RFPATHRX_TX3MON, + RFPATHRX_END + }; + + enum RFPathTx + { + RFPATHTX_A = 0, + RFPATHTX_B, + RFPATHTX_END + }; + + typedef enum { + GAIN_MANUAL, + GAIN_AGC_SLOW, + GAIN_AGC_FAST, + GAIN_HYBRID, + GAIN_END + } GainMode; + + // Common + quint64 m_devSampleRate; //!< Host interface sample rate + qint32 m_LOppmTenths; //!< XO correction + + // Common Rx + quint64 m_rxCenterFrequency; + bool m_dcBlock; + bool m_iqCorrection; + bool m_hwBBDCBlock; //!< Hardware baseband DC blocking + bool m_hwRFDCBlock; //!< Hardware RF DC blocking + bool m_hwIQCorrection; //!< Hardware IQ correction + fcPos_t m_fcPosRx; + bool m_rxTransverterMode; + qint64 m_rxTransverterDeltaFrequency; + bool m_iqOrder; + quint32 m_lpfBWRx; //!< analog lowpass filter bandwidth (Hz) + bool m_lpfRxFIREnable; //!< enable digital lowpass FIR filter + quint32 m_lpfRxFIRBW; //!< digital lowpass FIR filter bandwidth (Hz) + quint32 m_lpfRxFIRlog2Decim; //!< digital lowpass FIR filter log2 of decimation factor (0..2) + int m_lpfRxFIRGain; //!< digital lowpass FIR filter gain (dB) + quint32 m_log2Decim; + + // Rx0 + quint32 m_rx0Gain; //!< "hardware" gain + GainMode m_rx0GainMode; + RFPathRx m_rx0AntennaPath; + + // Rx1 + quint32 m_rx1Gain; //!< "hardware" gain + GainMode m_rx1GainMode; + RFPathRx m_rx1AntennaPath; + + // Common Tx + quint64 m_txCenterFrequency; + fcPos_t m_fcPosTx; + bool m_txTransverterMode; + qint64 m_txTransverterDeltaFrequency; + quint32 m_lpfBWTx; //!< analog lowpass filter bandwidth (Hz) + bool m_lpfTxFIREnable; //!< enable digital lowpass FIR filter + quint32 m_lpfTxFIRBW; //!< digital lowpass FIR filter bandwidth (Hz) + quint32 m_lpfTxFIRlog2Interp; //!< digital lowpass FIR filter log2 of interpolation factor (0..2) + int m_lpfTxFIRGain; //!< digital lowpass FIR filter gain (dB) + quint32 m_log2Interp; + + // Tx0 + qint32 m_tx0Att; //!< "hardware" attenuation in dB fourths + RFPathTx m_tx0AntennaPath; + + // Tx1 + qint32 m_tx1Att; //!< "hardware" attenuation in dB fourths + RFPathTx m_tx1AntennaPath; + + // global settings to be saved + // common device settings + // individual channel settings + bool m_useReverseAPI; + QString m_reverseAPIAddress; + uint16_t m_reverseAPIPort; + uint16_t m_reverseAPIDeviceIndex; + + static const int m_plutoSDRBlockSizeSamples = 64*256; //complex samples per buffer (must be multiple of 64) + + PlutoSDRMIMOSettings(); + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + static void translateRFPathRx(RFPathRx path, QString& s); + static void translateGainMode(GainMode mod, QString& s); + static void translateRFPathTx(RFPathTx path, QString& s); +}; + +#endif /* _PLUTOSDR_PLUTOSDRMIMOSETTINGS_H_ */ diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmimowebapiadapter.cpp b/plugins/samplemimo/plutosdrmimo/plutosdrmimowebapiadapter.cpp new file mode 100644 index 000000000..3e6a392cd --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmimowebapiadapter.cpp @@ -0,0 +1,51 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// // +// Implementation of static web API adapters used for preset serialization and // +// deserialization // +// // +// 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 "SWGDeviceSettings.h" +//#include "limesdrmimo.h" +#include "plutosdrmimowebapiadapter.h" + +PlutoSDRMIMOWebAPIAdapter::PlutoSDRMIMOWebAPIAdapter() +{} + +PlutoSDRMIMOWebAPIAdapter::~PlutoSDRMIMOWebAPIAdapter() +{} + +int PlutoSDRMIMOWebAPIAdapter::webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + (void) response; + return 501; +} + +int PlutoSDRMIMOWebAPIAdapter::webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage) +{ + (void) force; + (void) deviceSettingsKeys; + (void) response; + (void) errorMessage; + return 501; +} diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmimowebapiadapter.h b/plugins/samplemimo/plutosdrmimo/plutosdrmimowebapiadapter.h new file mode 100644 index 000000000..3cd89374a --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmimowebapiadapter.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// // +// Implementation of static web API adapters used for preset serialization and // +// deserialization // +// // +// 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 _PLUTOSDR_PLUTOSDRMIMOWEBAPIADAPTER_H_ +#define _PLUTOSDR_PLUTOSDRMIMOWEBAPIADAPTER_H_ + +#include "device/devicewebapiadapter.h" +#include "plutosdrmimosettings.h" + +class PlutoSDRMIMOWebAPIAdapter : public DeviceWebAPIAdapter +{ +public: + PlutoSDRMIMOWebAPIAdapter(); + virtual ~PlutoSDRMIMOWebAPIAdapter(); + virtual QByteArray serialize() { return m_settings.serialize(); } + virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); } + + virtual int webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage); + +private: + PlutoSDRMIMOSettings m_settings; +}; + +#endif // _PLUTOSDR_PLUTOSDRMIMOWEBAPIADAPTER_H_ diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmithread.cpp b/plugins/samplemimo/plutosdrmimo/plutosdrmithread.cpp new file mode 100644 index 000000000..069538cfb --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmithread.cpp @@ -0,0 +1,358 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 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 "plutosdr/deviceplutosdrbox.h" +#include "dsp/samplemififo.h" + +#include "plutosdrmimosettings.h" +#include "plutosdrmithread.h" + +PlutoSDRMIThread::PlutoSDRMIThread(DevicePlutoSDRBox* plutoBox, QObject* parent) : + QThread(parent), + m_running(false), + m_plutoBox(plutoBox), + m_sampleFifo(nullptr), + m_iqOrder(true) +{ + qDebug("PlutoSDRMIThread::PlutoSDRMIThread"); + m_buf[0] = new qint16[2*m_plutoSDRBlockSizeSamples]; + m_buf[1] = new qint16[2*m_plutoSDRBlockSizeSamples]; + + for (unsigned int i = 0; i < 2; i++) { + m_convertBuffer[i].resize(m_plutoSDRBlockSizeSamples, Sample{0,0}); + } +} + +PlutoSDRMIThread::~PlutoSDRMIThread() +{ + qDebug("PlutoSDRMIThread::~PlutoSDRMIThread"); + + if (m_running) { + stopWork(); + } + + delete[] m_buf[0]; + delete[] m_buf[1]; +} + +void PlutoSDRMIThread::startWork() +{ + m_startWaitMutex.lock(); + start(); + + while(!m_running) { + m_startWaiter.wait(&m_startWaitMutex, 100); + } + + m_startWaitMutex.unlock(); +} + +void PlutoSDRMIThread::stopWork() +{ + m_running = false; + wait(); +} + +void PlutoSDRMIThread::setLog2Decimation(unsigned int log2Decim) +{ + m_log2Decim = log2Decim; +} + +unsigned int PlutoSDRMIThread::getLog2Decimation() const +{ + return m_log2Decim; +} + +void PlutoSDRMIThread::setFcPos(int fcPos) +{ + m_fcPos = fcPos; +} + +int PlutoSDRMIThread::getFcPos() const +{ + return m_fcPos; +} + +void PlutoSDRMIThread::run() +{ + std::ptrdiff_t p_inc = m_plutoBox->rxBufferStep(); + int sampleSize = m_plutoBox->getRxSampleSize(); // I/Q sample size in bytes + int nbChan = p_inc / sampleSize; // number of I/Q channels + + qDebug("PlutoSDRMIThread::run: rxBufferStep: %ld bytes", p_inc); + qDebug("PlutoSDRMIThread::run: Rx sample size is %ld bytes", m_plutoBox->getRxSampleSize()); + qDebug("PlutoSDRMIThread::run: Tx sample size is %ld bytes", m_plutoBox->getTxSampleSize()); + qDebug("PlutoSDRMIThread::run: nominal nbytes_rx is %ld bytes with 1 refill", m_plutoSDRBlockSizeSamples*p_inc); + + m_running = true; + m_startWaiter.wakeAll(); + + while (m_running) + { + ssize_t nbytes_rx; + char *p_dat, *p_end; + int ihs; // half sample index (I then Q to make a sample) + + // Refill RX buffer + nbytes_rx = m_plutoBox->rxBufferRefill(); + + if (nbytes_rx != m_plutoSDRBlockSizeSamples*p_inc) + { + qWarning("PlutoSDRMIThread::run: error refilling buf %d / %ld", (int) nbytes_rx, (int) m_plutoSDRBlockSizeSamples*p_inc); + usleep(200000); + continue; + } + + // READ: Get pointers to RX buf and read IQ from RX buf port 0 + p_dat = m_plutoBox->rxBufferFirst(); + p_end = m_plutoBox->rxBufferEnd(); + ihs = 0; + + // p_inc is 8 on a char* buffer therefore each iteration processes a couple of IQ samples, + // I and Q each being two bytes + // conversion is not needed as samples are little endian + + for (; p_dat < p_end; p_dat += p_inc, ihs += 2) + { + m_buf[0][ihs] = *(((int16_t *) p_dat) + 0); + m_buf[0][ihs+1] = *(((int16_t *) p_dat) + 1); + + if (nbChan == 1) + { + m_buf[1][ihs] = 0; + m_buf[1][ihs+1] = 0; + } + else if (nbChan == 2) + { + m_buf[1][ihs] = *(((int16_t *) p_dat) + 2); + m_buf[1][ihs+1] = *(((int16_t *) p_dat) + 3); + } + } + + std::vector vbegin; + int lengths[2]; + + for (unsigned int channel = 0; channel < 2; channel++) + { + if (m_iqOrder) { + lengths[channel] = channelCallbackIQ(m_buf[channel], 2*m_plutoSDRBlockSizeSamples, channel); + } else { + lengths[channel] = channelCallbackQI(m_buf[channel], 2*m_plutoSDRBlockSizeSamples, channel); + } + + vbegin.push_back(m_convertBuffer[channel].begin()); + } + + if (lengths[0] == lengths[1]) + { + m_sampleFifo->writeSync(vbegin, lengths[0]); + } + else + { + qWarning("PlutoSDRMIThread::run: unequal channel lengths: [0]=%d [1]=%d", lengths[0], lengths[1]); + m_sampleFifo->writeSync(vbegin, (std::min)(lengths[0], lengths[1])); + } + } + + m_running = false; +} + +int PlutoSDRMIThread::channelCallbackIQ(const qint16* buf, qint32 len, int channel) +{ + SampleVector::iterator it = m_convertBuffer[channel].begin(); + + if (m_log2Decim == 0) + { + m_decimatorsIQ[channel].decimate1(&it, buf, len); + } + else + { + if (m_fcPos == 0) // Infra + { + switch (m_log2Decim) + { + case 1: + m_decimatorsIQ[channel].decimate2_inf(&it, buf, len); + break; + case 2: + m_decimatorsIQ[channel].decimate4_inf(&it, buf, len); + break; + case 3: + m_decimatorsIQ[channel].decimate8_inf(&it, buf, len); + break; + case 4: + m_decimatorsIQ[channel].decimate16_inf(&it, buf, len); + break; + case 5: + m_decimatorsIQ[channel].decimate32_inf(&it, buf, len); + break; + case 6: + m_decimatorsIQ[channel].decimate64_inf(&it, buf, len); + break; + default: + break; + } + } + else if (m_fcPos == 1) // Supra + { + switch (m_log2Decim) + { + case 1: + m_decimatorsIQ[channel].decimate2_sup(&it, buf, len); + break; + case 2: + m_decimatorsIQ[channel].decimate4_sup(&it, buf, len); + break; + case 3: + m_decimatorsIQ[channel].decimate8_sup(&it, buf, len); + break; + case 4: + m_decimatorsIQ[channel].decimate16_sup(&it, buf, len); + break; + case 5: + m_decimatorsIQ[channel].decimate32_sup(&it, buf, len); + break; + case 6: + m_decimatorsIQ[channel].decimate64_sup(&it, buf, len); + break; + default: + break; + } + } + else if (m_fcPos == 2) // Center + { + switch (m_log2Decim) + { + case 1: + m_decimatorsIQ[channel].decimate2_cen(&it, buf, len); + break; + case 2: + m_decimatorsIQ[channel].decimate4_cen(&it, buf, len); + break; + case 3: + m_decimatorsIQ[channel].decimate8_cen(&it, buf, len); + break; + case 4: + m_decimatorsIQ[channel].decimate16_cen(&it, buf, len); + break; + case 5: + m_decimatorsIQ[channel].decimate32_cen(&it, buf, len); + break; + case 6: + m_decimatorsIQ[channel].decimate64_cen(&it, buf, len); + break; + default: + break; + } + } + } + + return it - m_convertBuffer[channel].begin(); +} + +int PlutoSDRMIThread::channelCallbackQI(const qint16* buf, qint32 len, int channel) +{ + SampleVector::iterator it = m_convertBuffer[channel].begin(); + + if (m_log2Decim == 0) + { + m_decimatorsQI[channel].decimate1(&it, buf, len); + } + else + { + if (m_fcPos == 0) // Infra + { + switch (m_log2Decim) + { + case 1: + m_decimatorsQI[channel].decimate2_inf(&it, buf, len); + break; + case 2: + m_decimatorsQI[channel].decimate4_inf(&it, buf, len); + break; + case 3: + m_decimatorsQI[channel].decimate8_inf(&it, buf, len); + break; + case 4: + m_decimatorsQI[channel].decimate16_inf(&it, buf, len); + break; + case 5: + m_decimatorsQI[channel].decimate32_inf(&it, buf, len); + break; + case 6: + m_decimatorsQI[channel].decimate64_inf(&it, buf, len); + break; + default: + break; + } + } + else if (m_fcPos == 1) // Supra + { + switch (m_log2Decim) + { + case 1: + m_decimatorsQI[channel].decimate2_sup(&it, buf, len); + break; + case 2: + m_decimatorsQI[channel].decimate4_sup(&it, buf, len); + break; + case 3: + m_decimatorsQI[channel].decimate8_sup(&it, buf, len); + break; + case 4: + m_decimatorsQI[channel].decimate16_sup(&it, buf, len); + break; + case 5: + m_decimatorsQI[channel].decimate32_sup(&it, buf, len); + break; + case 6: + m_decimatorsQI[channel].decimate64_sup(&it, buf, len); + break; + default: + break; + } + } + else if (m_fcPos == 2) // Center + { + switch (m_log2Decim) + { + case 1: + m_decimatorsQI[channel].decimate2_cen(&it, buf, len); + break; + case 2: + m_decimatorsQI[channel].decimate4_cen(&it, buf, len); + break; + case 3: + m_decimatorsQI[channel].decimate8_cen(&it, buf, len); + break; + case 4: + m_decimatorsQI[channel].decimate16_cen(&it, buf, len); + break; + case 5: + m_decimatorsQI[channel].decimate32_cen(&it, buf, len); + break; + case 6: + m_decimatorsQI[channel].decimate64_cen(&it, buf, len); + break; + default: + break; + } + } + } + + return it - m_convertBuffer[channel].begin(); +} diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmithread.h b/plugins/samplemimo/plutosdrmimo/plutosdrmithread.h new file mode 100644 index 000000000..e0df79d4e --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmithread.h @@ -0,0 +1,69 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 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 _PLUTOSDR_PLUTOSDRMITHREAD_H_ +#define _PLUTOSDR_PLUTOSDRMITHREAD_H_ + +#include +#include +#include + +#include "dsp/decimators.h" + +class SampleMIFifo; +class DevicePlutoSDRBox; + +class PlutoSDRMIThread : public QThread { + Q_OBJECT +public: + PlutoSDRMIThread(DevicePlutoSDRBox* plutoBox, QObject* parent = nullptr); + ~PlutoSDRMIThread(); + + void startWork(); + void stopWork(); + bool isRunning() const { return m_running; } + void setLog2Decimation(unsigned int log2Decim); + unsigned int getLog2Decimation() const; + void setFcPos(int fcPos); + int getFcPos() const; + void setFifo(SampleMIFifo *sampleFifo) { m_sampleFifo = sampleFifo; } + SampleMIFifo *getFifo() { return m_sampleFifo; } + void setIQOrder(bool iqOrder) { m_iqOrder = iqOrder; } + +private: + QMutex m_startWaitMutex; + QWaitCondition m_startWaiter; + bool m_running; + + DevicePlutoSDRBox *m_plutoBox; + qint16 *m_buf[2]; //!< one buffer per I/Q channel + SampleVector m_convertBuffer[2]; + SampleMIFifo *m_sampleFifo; + Decimators m_decimatorsIQ[2]; + Decimators m_decimatorsQI[2]; + unsigned int m_log2Decim; + int m_fcPos; + bool m_iqOrder; + + static const int m_plutoSDRBlockSizeSamples = 64*256; //complex samples per buffer (must be multiple of 64) + + void run(); + int channelCallbackIQ(const qint16* buf, qint32 len, int channel); + int channelCallbackQI(const qint16* buf, qint32 len, int channel); +}; + +#endif // _PLUTOSDR_PLUTOSDRMITHREAD_H_ diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmothread.cpp b/plugins/samplemimo/plutosdrmimo/plutosdrmothread.cpp new file mode 100644 index 000000000..27aa70616 --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmothread.cpp @@ -0,0 +1,253 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 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 "plutosdr/deviceplutosdrbox.h" +#include "dsp/samplemofifo.h" + +#include "plutosdrmimosettings.h" +#include "plutosdrmothread.h" + +PlutoSDRMOThread::PlutoSDRMOThread(DevicePlutoSDRBox* plutoBox, QObject* parent) : + QThread(parent), + m_running(false), + m_plutoBox(plutoBox), + m_log2Interp(0) +{ + qDebug("PlutoSDRMOThread::PlutoSDRMOThread"); + m_buf[0] = new qint16[2*PlutoSDRMIMOSettings::m_plutoSDRBlockSizeSamples]; + m_buf[1] = new qint16[2*PlutoSDRMIMOSettings::m_plutoSDRBlockSizeSamples]; +} + +PlutoSDRMOThread::~PlutoSDRMOThread() +{ + qDebug("PlutoSDRMOThread::~PlutoSDRMOThread"); + + if (m_running) { + stopWork(); + } + + delete[] m_buf[0]; + delete[] m_buf[1]; +} + +void PlutoSDRMOThread::startWork() +{ + m_startWaitMutex.lock(); + start(); + + while(!m_running) { + m_startWaiter.wait(&m_startWaitMutex, 100); + } + + m_startWaitMutex.unlock(); +} + +void PlutoSDRMOThread::stopWork() +{ + m_running = false; + wait(); +} + +void PlutoSDRMOThread::setLog2Interpolation(unsigned int log2Interp) +{ + qDebug("PlutoSDRMOThread::setLog2Interpolation: %u", log2Interp); + m_log2Interp = log2Interp; +} + +unsigned int PlutoSDRMOThread::getLog2Interpolation() const +{ + return m_log2Interp; +} + +void PlutoSDRMOThread::setFcPos(int fcPos) +{ + m_fcPos = fcPos; +} + +int PlutoSDRMOThread::getFcPos() const +{ + return m_fcPos; +} + +void PlutoSDRMOThread::run() +{ + std::ptrdiff_t p_inc = m_plutoBox->txBufferStep(); + int sampleSize = m_plutoBox->getTxSampleSize(); // I/Q sample size in bytes + int nbChan = p_inc / sampleSize; // number of I/Q channels + + qDebug("PlutoSDRMOThread::run: txBufferStep: %ld bytes", p_inc); + qDebug("PlutoSDRMOThread::run: Rx sample size is %ld bytes", m_plutoBox->getRxSampleSize()); + qDebug("PlutoSDRMOThread::run: Tx sample size is %ld bytes", m_plutoBox->getTxSampleSize()); + qDebug("PlutoSDRMOThread::run: nominal nbytes_tx is %ld bytes", PlutoSDRMIMOSettings::m_plutoSDRBlockSizeSamples*p_inc); + + m_running = true; + m_startWaiter.wakeAll(); + + while (m_running) + { + ssize_t nbytes_tx; + char *p_dat, *p_end; + int ihs = 0; // half sample index (I then Q to make a sample) + // WRITE: Get pointers to TX buf and number of bytes to read from FIFO + p_dat = m_plutoBox->txBufferFirst(); + p_end = m_plutoBox->txBufferEnd(); + int nbOutSamples = (p_end - p_dat) / (4*nbChan); + + callback(m_buf, nbOutSamples); + + // p_inc is 2 on a char* buffer therefore each iteration processes only the I or Q sample + // I and Q samples are processed one after the other + // conversion is not needed as samples are little endian + + for (p_dat = m_plutoBox->txBufferFirst(), ihs = 0; p_dat < p_end; p_dat += p_inc, ihs += 2) + { + m_plutoBox->txChannelConvert((int16_t*) p_dat, &m_buf[0][ihs]); + + if (nbChan > 1) { // interleave with second chanel + m_plutoBox->txChannelConvert(1, (int16_t*) (p_dat+sampleSize), &m_buf[1][ihs]); + } + } + + // Schedule TX buffer for sending + nbytes_tx = m_plutoBox->txBufferPush(); + + if (nbytes_tx != sampleSize*PlutoSDRMIMOSettings::m_plutoSDRBlockSizeSamples) + { + qDebug("PlutoSDRMOThread::run: error pushing buf %d / %d", + (int) nbytes_tx, (int) sampleSize*PlutoSDRMIMOSettings::m_plutoSDRBlockSizeSamples); + usleep(200000); + continue; + } + } + + m_running = false; +} + +void PlutoSDRMOThread::callback(qint16* buf[2], qint32 samplesPerChannel) +{ + unsigned int iPart1Begin, iPart1End, iPart2Begin, iPart2End; + m_sampleFifo->readSync(samplesPerChannel/(1< decim=16). len is a number of samples (not a number of I or Q) +void PlutoSDRMOThread::callbackPart(qint16* buf[2], qint32 nSamples, int iBegin) +{ + for (unsigned int channel = 0; channel < 2; channel++) + { + SampleVector::iterator begin = m_sampleFifo->getData(channel).begin() + iBegin; + + if (m_log2Interp == 0) + { + m_interpolators[channel].interpolate1(&begin, buf[channel], 2*nSamples); + } + else + { + if (m_fcPos == 0) // Infra + { + switch (m_log2Interp) + { + case 1: + m_interpolators[channel].interpolate2_inf(&begin, buf[channel], 2*nSamples); + break; + case 2: + m_interpolators[channel].interpolate4_inf(&begin, buf[channel], 2*nSamples); + break; + case 3: + m_interpolators[channel].interpolate8_inf(&begin, buf[channel], 2*nSamples); + break; + case 4: + m_interpolators[channel].interpolate16_inf(&begin, buf[channel], 2*nSamples); + break; + case 5: + m_interpolators[channel].interpolate32_inf(&begin, buf[channel], 2*nSamples); + break; + case 6: + m_interpolators[channel].interpolate64_inf(&begin, buf[channel], 2*nSamples); + break; + default: + break; + } + } + else if (m_fcPos == 1) // Supra + { + switch (m_log2Interp) + { + case 1: + m_interpolators[channel].interpolate2_sup(&begin, buf[channel], 2*nSamples); + break; + case 2: + m_interpolators[channel].interpolate4_sup(&begin, buf[channel], 2*nSamples); + break; + case 3: + m_interpolators[channel].interpolate8_sup(&begin, buf[channel], 2*nSamples); + break; + case 4: + m_interpolators[channel].interpolate16_sup(&begin, buf[channel], 2*nSamples); + break; + case 5: + m_interpolators[channel].interpolate32_sup(&begin, buf[channel], 2*nSamples); + break; + case 6: + m_interpolators[channel].interpolate64_sup(&begin, buf[channel], 2*nSamples); + break; + default: + break; + } + } + else if (m_fcPos == 2) // Center + { + switch (m_log2Interp) + { + case 1: + m_interpolators[channel].interpolate2_cen(&begin, buf[channel], 2*nSamples); + break; + case 2: + m_interpolators[channel].interpolate4_cen(&begin, buf[channel], 2*nSamples); + break; + case 3: + m_interpolators[channel].interpolate8_cen(&begin, buf[channel], 2*nSamples); + break; + case 4: + m_interpolators[channel].interpolate16_cen(&begin, buf[channel], 2*nSamples); + break; + case 5: + m_interpolators[channel].interpolate32_cen(&begin, buf[channel], 2*nSamples); + break; + case 6: + m_interpolators[channel].interpolate64_cen(&begin, buf[channel], 2*nSamples); + break; + default: + break; + } + } + + } + } +} diff --git a/plugins/samplemimo/plutosdrmimo/plutosdrmothread.h b/plugins/samplemimo/plutosdrmimo/plutosdrmothread.h new file mode 100644 index 000000000..51a098bc7 --- /dev/null +++ b/plugins/samplemimo/plutosdrmimo/plutosdrmothread.h @@ -0,0 +1,64 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 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 _PLUTOSDR_PLUTOSDRMOTHREAD_H_ +#define _PLUTOSDR_PLUTOSDRMOTHREAD_H_ + +#include +#include +#include + +#include "dsp/interpolators.h" + +class SampleMOFifo; +class DevicePlutoSDRBox; + +class PlutoSDRMOThread : public QThread { + Q_OBJECT +public: + PlutoSDRMOThread(DevicePlutoSDRBox* plutoBox, QObject* parent = nullptr); + ~PlutoSDRMOThread(); + + void startWork(); + void stopWork(); + bool isRunning() const { return m_running; } + void setLog2Interpolation(unsigned int log2Interp); + unsigned int getLog2Interpolation() const; + void setFcPos(int fcPos); + int getFcPos() const; + void setFifo(SampleMOFifo *sampleFifo) { m_sampleFifo = sampleFifo; } + SampleMOFifo *getFifo() { return m_sampleFifo; } + +private: + QMutex m_startWaitMutex; + QWaitCondition m_startWaiter; + bool m_running; + + DevicePlutoSDRBox *m_plutoBox; + qint16 *m_buf[2]; //!< one buffer per I/Q channel + SampleMOFifo *m_sampleFifo; + Interpolators m_interpolators[2]; + unsigned int m_log2Interp; + int m_fcPos; + + void run(); + unsigned int getNbFifos(); + void callbackPart(qint16* buf[2], qint32 nSamples, int iBegin); + void callback(qint16* buf[2], qint32 samplesPerChannel); +}; + +#endif // _PLUTOSDR_PLUTOSDRMOTHREAD_H_ diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputthread.cpp b/plugins/samplesink/plutosdroutput/plutosdroutputthread.cpp index 3a4b32699..5cb1331f6 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutputthread.cpp +++ b/plugins/samplesink/plutosdroutput/plutosdroutputthread.cpp @@ -169,4 +169,4 @@ void PlutoSDROutputThread::convertPart(qint16* buf, SampleVector& data, unsigned break; } } -} \ No newline at end of file +} diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 637b4426e..f210e96d8 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -2832,6 +2832,9 @@ margin-bottom: 20px; "DATVDemodSettings" : { "$ref" : "#/definitions/DATVDemodSettings" }, + "DABDemodSettings" : { + "$ref" : "#/definitions/DABDemodSettings" + }, "DSDDemodSettings" : { "$ref" : "#/definitions/DSDDemodSettings" }, @@ -3341,6 +3344,58 @@ margin-bottom: 20px; } }, "description" : "A complex number" +}; + defs.DABDemodSettings = { + "properties" : { + "inputFrequencyOffset" : { + "type" : "integer", + "format" : "int64" + }, + "rfBandwidth" : { + "type" : "number", + "format" : "float" + }, + "program" : { + "type" : "string" + }, + "volume" : { + "type" : "number", + "format" : "float" + }, + "audioMute" : { + "type" : "integer" + }, + "audioDeviceName" : { + "type" : "string" + }, + "rgbColor" : { + "type" : "integer" + }, + "title" : { + "type" : "string" + }, + "streamIndex" : { + "type" : "integer", + "description" : "MIMO channel. Not relevant when connected to SI (single Rx)." + }, + "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" : "DABDemod" }; defs.DATVDemodSettings = { "properties" : { @@ -3918,6 +3973,9 @@ margin-bottom: 20px; "plutoSdrOutputReport" : { "$ref" : "#/definitions/PlutoSdrOutputReport" }, + "plutoSdrMIMOReport" : { + "$ref" : "#/definitions/PlutoSdrMIMOReport" + }, "rtlSdrReport" : { "$ref" : "#/definitions/RtlSdrReport" }, @@ -3930,6 +3988,9 @@ margin-bottom: 20px; "sdrPlayReport" : { "$ref" : "#/definitions/SDRPlayReport" }, + "sdrPlayV3Report" : { + "$ref" : "#/definitions/SDRPlayV3Report" + }, "sigMFFileInputReport" : { "$ref" : "#/definitions/SigMFFileInputReport" }, @@ -4085,6 +4146,9 @@ margin-bottom: 20px; "plutoSdrOutputSettings" : { "$ref" : "#/definitions/PlutoSdrOutputSettings" }, + "plutoSdrMIMOSettings" : { + "$ref" : "#/definitions/PlutoSdrMIMOSettings" + }, "rtlSdrSettings" : { "$ref" : "#/definitions/RtlSdrSettings" }, @@ -4097,6 +4161,9 @@ margin-bottom: 20px; "sdrPlaySettings" : { "$ref" : "#/definitions/SDRPlaySettings" }, + "sdrPlayV3Settings" : { + "$ref" : "#/definitions/SDRPlayV3Settings" + }, "sigMFFileInputSettings" : { "$ref" : "#/definitions/SigMFFileInputSettings" }, @@ -7689,6 +7756,175 @@ margin-bottom: 20px; } }, "description" : "PlutoSDR" +}; + defs.PlutoSdrMIMOReport = { + "properties" : { + "adcRate" : { + "type" : "integer" + }, + "dacRate" : { + "type" : "integer" + }, + "rx0GainDB" : { + "type" : "integer" + }, + "rx1GainDB" : { + "type" : "integer" + }, + "rssiRx0" : { + "type" : "string" + }, + "rssiRx1" : { + "type" : "string" + }, + "rssiTx0" : { + "type" : "string" + }, + "rssiTx1" : { + "type" : "string" + } + }, + "description" : "PlutoSDR" +}; + defs.PlutoSdrMIMOSettings = { + "properties" : { + "devSampleRate" : { + "type" : "integer" + }, + "LOppmTenths" : { + "type" : "integer" + }, + "rxCenterFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "dcBlock" : { + "type" : "integer" + }, + "iqCorrection" : { + "type" : "integer" + }, + "hwBBDCBlock" : { + "type" : "integer" + }, + "hwRFDCBlock" : { + "type" : "integer" + }, + "hwIQCorrection" : { + "type" : "integer" + }, + "fcPosRx" : { + "type" : "integer", + "description" : "0=Infra 1=Supra 2=Center" + }, + "rxTransverterMode" : { + "type" : "integer" + }, + "rxTransverterDeltaFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "iqOrder" : { + "type" : "integer", + "description" : "IQ samples order\n * 0 - Q then I (swapped)\n * 1 - I then Q (straight)\n" + }, + "lpfBWRx" : { + "type" : "integer", + "description" : "Analog lowpass filter bandwidth (Hz)" + }, + "lpfRxFIREnable" : { + "type" : "integer", + "description" : "Low pass FIR filter enable (1 if enabled else 0)" + }, + "lpfRxFIRBW" : { + "type" : "integer", + "description" : "digital lowpass FIR filter bandwidth (Hz)" + }, + "lpfRxFIRlog2Decim" : { + "type" : "integer", + "description" : "digital lowpass FIR filter log2 of decimation factor (0..2)" + }, + "lpfRxFIRGain" : { + "type" : "integer", + "description" : "digital lowpass FIR filter gain (dB)" + }, + "log2Decim" : { + "type" : "integer" + }, + "rx0Gain" : { + "type" : "integer", + "description" : "Hardware gain" + }, + "rx0GainMode" : { + "type" : "integer" + }, + "rx0AntennaPath" : { + "type" : "integer" + }, + "rx1Gain" : { + "type" : "integer", + "description" : "Hardware gain" + }, + "rx1GainMode" : { + "type" : "integer" + }, + "rx1AntennaPath" : { + "type" : "integer" + }, + "txCenterFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "fcPosTx" : { + "type" : "integer", + "description" : "0=Infra 1=Supra 2=Center" + }, + "txTransverterMode" : { + "type" : "integer" + }, + "txTransverterDeltaFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "lpfBWTx" : { + "type" : "integer", + "description" : "Analog lowpass filter bandwidth (Hz)" + }, + "lpfTxFIREnable" : { + "type" : "integer", + "description" : "Low pass FIR filter enable (1 if enabled else 0)" + }, + "lpfTxFIRBW" : { + "type" : "integer", + "description" : "digital lowpass FIR filter bandwidth (Hz)" + }, + "lpfTxFIRlog2Interp" : { + "type" : "integer", + "description" : "digital lowpass FIR filter log2 of interpolation factor (0..2)" + }, + "lpfTxFIRGain" : { + "type" : "integer", + "description" : "digital lowpass FIR filter gain (dB)" + }, + "log2Interp" : { + "type" : "integer" + }, + "tx0Att" : { + "type" : "integer", + "description" : "Hardware attenuator gain in decibel fourths (negative)" + }, + "tx0AntennaPath" : { + "type" : "integer" + }, + "tx1Att" : { + "type" : "integer", + "description" : "Hardware attenuator gain in decibel fourths (negative)" + }, + "tx1AntennaPath" : { + "type" : "integer" + } + }, + "description" : "PlutoSDR" }; defs.PlutoSdrOutputReport = { "properties" : { @@ -8592,6 +8828,96 @@ margin-bottom: 20px; } }, "description" : "SDRplay1" +}; + defs.SDRPlayV3Report = { + "properties" : { + "bandwidths" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/Bandwidth" + } + }, + "intermediateFrequencies" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/Frequency" + } + } + }, + "description" : "SDRplayV3" +}; + defs.SDRPlayV3Settings = { + "properties" : { + "centerFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "LOppmTenths" : { + "type" : "integer" + }, + "ifFrequencyIndex" : { + "type" : "integer" + }, + "bandwidthIndex" : { + "type" : "integer" + }, + "devSampleRate" : { + "type" : "integer" + }, + "log2Decim" : { + "type" : "integer" + }, + "fcPos" : { + "type" : "integer" + }, + "dcBlock" : { + "type" : "integer" + }, + "iqCorrection" : { + "type" : "integer" + }, + "lnaIndex" : { + "type" : "integer" + }, + "ifAGC" : { + "type" : "integer" + }, + "ifGain" : { + "type" : "integer" + }, + "amNotch" : { + "type" : "integer" + }, + "fmNotch" : { + "type" : "integer" + }, + "dabNotch" : { + "type" : "integer" + }, + "extRef" : { + "type" : "integer" + }, + "tuner" : { + "type" : "integer" + }, + "antenna" : { + "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" + } + }, + "description" : "SDRplayV3" }; defs.SSBDemodReport = { "properties" : { @@ -45942,7 +46268,7 @@ except ApiException as e:
- Generated 2021-04-12T14:54:42.978+02:00 + Generated 2021-04-29T21:19:02.297+02:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/ChannelSettings.yaml b/sdrbase/resources/webapi/doc/swagger/include/ChannelSettings.yaml index f85688aa4..b0088786e 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/ChannelSettings.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/ChannelSettings.yaml @@ -43,6 +43,8 @@ ChannelSettings: $ref: "/doc/swagger/include/DATVMod.yaml#/DATVModSettings" DATVDemodSettings: $ref: "/doc/swagger/include/DATVDemod.yaml#/DATVDemodSettings" + DABDemodSettings: + $ref: "/doc/swagger/include/DABDemod.yaml#/DABDemodSettings" DSDDemodSettings: $ref: "/doc/swagger/include/DSDDemod.yaml#/DSDDemodSettings" FileSinkSettings: diff --git a/sdrbase/resources/webapi/doc/swagger/include/DABDemod.yaml b/sdrbase/resources/webapi/doc/swagger/include/DABDemod.yaml new file mode 100644 index 000000000..90e1ed840 --- /dev/null +++ b/sdrbase/resources/webapi/doc/swagger/include/DABDemod.yaml @@ -0,0 +1,36 @@ +DABDemodSettings: + description: DABDemod + properties: + inputFrequencyOffset: + type: integer + format: int64 + rfBandwidth: + type: number + format: float + program: + type: string + volume: + type: number + format: float + audioMute: + type: integer + audioDeviceName: + type: string + rgbColor: + type: integer + title: + type: string + streamIndex: + description: MIMO channel. Not relevant when connected to SI (single Rx). + 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/DeviceReports.yaml b/sdrbase/resources/webapi/doc/swagger/include/DeviceReports.yaml index c6b6890ad..20e51c4a6 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/DeviceReports.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/DeviceReports.yaml @@ -41,6 +41,8 @@ DeviceReport: $ref: "/doc/swagger/include/PlutoSdr.yaml#/PlutoSdrInputReport" plutoSdrOutputReport: $ref: "/doc/swagger/include/PlutoSdr.yaml#/PlutoSdrOutputReport" + plutoSdrMIMOReport: + $ref: "/doc/swagger/include/PlutoSdr.yaml#/PlutoSdrMIMOReport" rtlSdrReport: $ref: "/doc/swagger/include/RtlSdr.yaml#/RtlSdrReport" remoteOutputReport: @@ -49,6 +51,8 @@ DeviceReport: $ref: "/doc/swagger/include/RemoteInput.yaml#/RemoteInputReport" sdrPlayReport: $ref: "/doc/swagger/include/SDRPlay.yaml#/SDRPlayReport" + sdrPlayV3Report: + $ref: "/doc/swagger/include/SDRPlayV3.yaml#/SDRPlayV3Report" sigMFFileInputReport: $ref: "/doc/swagger/include/SigMFFileInput.yaml#/SigMFFileInputReport" soapySDRInputReport: diff --git a/sdrbase/resources/webapi/doc/swagger/include/DeviceSettings.yaml b/sdrbase/resources/webapi/doc/swagger/include/DeviceSettings.yaml index 35f0af122..1d8bb7198 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/DeviceSettings.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/DeviceSettings.yaml @@ -62,6 +62,8 @@ DeviceSettings: $ref: "/doc/swagger/include/PlutoSdr.yaml#/PlutoSdrInputSettings" plutoSdrOutputSettings: $ref: "/doc/swagger/include/PlutoSdr.yaml#/PlutoSdrOutputSettings" + plutoSdrMIMOSettings: + $ref: "/doc/swagger/include/PlutoSdr.yaml#/PlutoSdrMIMOSettings" rtlSdrSettings: $ref: "/doc/swagger/include/RtlSdr.yaml#/RtlSdrSettings" remoteOutputSettings: @@ -70,6 +72,8 @@ DeviceSettings: $ref: "/doc/swagger/include/RemoteInput.yaml#/RemoteInputSettings" sdrPlaySettings: $ref: "/doc/swagger/include/SDRPlay.yaml#/SDRPlaySettings" + sdrPlayV3Settings: + $ref: "/doc/swagger/include/SDRPlayV3.yaml#/SDRPlayV3Settings" sigMFFileInputSettings: $ref: "/doc/swagger/include/SigMFFileInput.yaml#/SigMFFileInputSettings" soapySDRInputSettings: diff --git a/sdrbase/resources/webapi/doc/swagger/include/PlutoSdr.yaml b/sdrbase/resources/webapi/doc/swagger/include/PlutoSdr.yaml index 0d59b1270..fb5b5d0ef 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/PlutoSdr.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/PlutoSdr.yaml @@ -113,6 +113,110 @@ PlutoSdrOutputSettings: reverseAPIDeviceIndex: type: integer +PlutoSdrMIMOSettings: + description: PlutoSDR + properties: + devSampleRate: + type: integer + LOppmTenths: + type: integer + rxCenterFrequency: + type: integer + format: int64 + dcBlock: + type: integer + iqCorrection: + type: integer + hwBBDCBlock: + type: integer + hwRFDCBlock: + type: integer + hwIQCorrection: + type: integer + fcPosRx: + description: 0=Infra 1=Supra 2=Center + type: integer + rxTransverterMode: + type: integer + rxTransverterDeltaFrequency: + type: integer + format: int64 + iqOrder: + type: integer + description: > + IQ samples order + * 0 - Q then I (swapped) + * 1 - I then Q (straight) + lpfBWRx: + description: Analog lowpass filter bandwidth (Hz) + type: integer + lpfRxFIREnable: + description: Low pass FIR filter enable (1 if enabled else 0) + type: integer + lpfRxFIRBW: + description: digital lowpass FIR filter bandwidth (Hz) + type: integer + lpfRxFIRlog2Decim: + description: digital lowpass FIR filter log2 of decimation factor (0..2) + type: integer + lpfRxFIRGain: + description: digital lowpass FIR filter gain (dB) + type: integer + log2Decim: + type: integer + rx0Gain: + description: Hardware gain + type: integer + rx0GainMode: + type: integer + rx0AntennaPath: + type: integer + rx1Gain: + description: Hardware gain + type: integer + rx1GainMode: + type: integer + rx1AntennaPath: + type: integer + txCenterFrequency: + type: integer + format: int64 + fcPosTx: + description: 0=Infra 1=Supra 2=Center + type: integer + txTransverterMode: + type: integer + txTransverterDeltaFrequency: + type: integer + format: int64 + lpfBWTx: + description: Analog lowpass filter bandwidth (Hz) + type: integer + lpfTxFIREnable: + description: Low pass FIR filter enable (1 if enabled else 0) + type: integer + lpfTxFIRBW: + description: digital lowpass FIR filter bandwidth (Hz) + type: integer + lpfTxFIRlog2Interp: + description: digital lowpass FIR filter log2 of interpolation factor (0..2) + type: integer + lpfTxFIRGain: + description: digital lowpass FIR filter gain (dB) + type: integer + log2Interp: + type: integer + tx0Att: + description: Hardware attenuator gain in decibel fourths (negative) + type: integer + tx0AntennaPath: + type: integer + tx1Att: + description: Hardware attenuator gain in decibel fourths (negative) + type: integer + tx1AntennaPath: + type: integer + PlutoSdrInputReport: description: PlutoSDR properties: @@ -136,3 +240,23 @@ PlutoSdrOutputReport: temperature: type: number format: float + +PlutoSdrMIMOReport: + description: PlutoSDR + properties: + adcRate: + type: integer + dacRate: + type: integer + rx0GainDB: + type: integer + rx1GainDB: + type: integer + rssiRx0: + type: string + rssiRx1: + type: string + rssiTx0: + type: string + rssiTx1: + type: string diff --git a/sdrbase/resources/webapi/doc/swagger/include/SDRPlayV3.yaml b/sdrbase/resources/webapi/doc/swagger/include/SDRPlayV3.yaml new file mode 100644 index 000000000..3aa7005af --- /dev/null +++ b/sdrbase/resources/webapi/doc/swagger/include/SDRPlayV3.yaml @@ -0,0 +1,61 @@ +SDRPlayV3Settings: + description: SDRplayV3 + properties: + centerFrequency: + type: integer + format: int64 + LOppmTenths: + type: integer + ifFrequencyIndex: + type: integer + bandwidthIndex: + type: integer + devSampleRate: + type: integer + log2Decim: + type: integer + fcPos: + type: integer + dcBlock: + type: integer + iqCorrection: + type: integer + lnaIndex: + type: integer + ifAGC: + type: integer + ifGain: + type: integer + amNotch: + type: integer + fmNotch: + type: integer + dabNotch: + type: integer + extRef: + type: integer + tuner: + type: integer + antenna: + 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 + +SDRPlayV3Report: + description: SDRplayV3 + properties: + bandwidths: + type: array + items: + $ref: "/doc/swagger/include/Structs.yaml#/Bandwidth" + intermediateFrequencies: + type: array + items: + $ref: "/doc/swagger/include/Structs.yaml#/Frequency" diff --git a/swagger/sdrangel/api/swagger/include/DeviceReports.yaml b/swagger/sdrangel/api/swagger/include/DeviceReports.yaml index 9ca55ea3c..19bef3007 100644 --- a/swagger/sdrangel/api/swagger/include/DeviceReports.yaml +++ b/swagger/sdrangel/api/swagger/include/DeviceReports.yaml @@ -41,6 +41,8 @@ DeviceReport: $ref: "http://swgserver:8081/api/swagger/include/PlutoSdr.yaml#/PlutoSdrInputReport" plutoSdrOutputReport: $ref: "http://swgserver:8081/api/swagger/include/PlutoSdr.yaml#/PlutoSdrOutputReport" + plutoSdrMIMOReport: + $ref: "http://swgserver:8081/api/swagger/include/PlutoSdr.yaml#/PlutoSdrMIMOReport" rtlSdrReport: $ref: "http://swgserver:8081/api/swagger/include/RtlSdr.yaml#/RtlSdrReport" remoteOutputReport: diff --git a/swagger/sdrangel/api/swagger/include/DeviceSettings.yaml b/swagger/sdrangel/api/swagger/include/DeviceSettings.yaml index c7babbde8..1370ebc54 100644 --- a/swagger/sdrangel/api/swagger/include/DeviceSettings.yaml +++ b/swagger/sdrangel/api/swagger/include/DeviceSettings.yaml @@ -62,6 +62,8 @@ DeviceSettings: $ref: "http://swgserver:8081/api/swagger/include/PlutoSdr.yaml#/PlutoSdrInputSettings" plutoSdrOutputSettings: $ref: "http://swgserver:8081/api/swagger/include/PlutoSdr.yaml#/PlutoSdrOutputSettings" + plutoSdrMIMOSettings: + $ref: "http://swgserver:8081/api/swagger/include/PlutoSdr.yaml#/PlutoSdrMIMOSettings" rtlSdrSettings: $ref: "http://swgserver:8081/api/swagger/include/RtlSdr.yaml#/RtlSdrSettings" remoteOutputSettings: diff --git a/swagger/sdrangel/api/swagger/include/PlutoSdr.yaml b/swagger/sdrangel/api/swagger/include/PlutoSdr.yaml index 0d59b1270..fb5b5d0ef 100644 --- a/swagger/sdrangel/api/swagger/include/PlutoSdr.yaml +++ b/swagger/sdrangel/api/swagger/include/PlutoSdr.yaml @@ -113,6 +113,110 @@ PlutoSdrOutputSettings: reverseAPIDeviceIndex: type: integer +PlutoSdrMIMOSettings: + description: PlutoSDR + properties: + devSampleRate: + type: integer + LOppmTenths: + type: integer + rxCenterFrequency: + type: integer + format: int64 + dcBlock: + type: integer + iqCorrection: + type: integer + hwBBDCBlock: + type: integer + hwRFDCBlock: + type: integer + hwIQCorrection: + type: integer + fcPosRx: + description: 0=Infra 1=Supra 2=Center + type: integer + rxTransverterMode: + type: integer + rxTransverterDeltaFrequency: + type: integer + format: int64 + iqOrder: + type: integer + description: > + IQ samples order + * 0 - Q then I (swapped) + * 1 - I then Q (straight) + lpfBWRx: + description: Analog lowpass filter bandwidth (Hz) + type: integer + lpfRxFIREnable: + description: Low pass FIR filter enable (1 if enabled else 0) + type: integer + lpfRxFIRBW: + description: digital lowpass FIR filter bandwidth (Hz) + type: integer + lpfRxFIRlog2Decim: + description: digital lowpass FIR filter log2 of decimation factor (0..2) + type: integer + lpfRxFIRGain: + description: digital lowpass FIR filter gain (dB) + type: integer + log2Decim: + type: integer + rx0Gain: + description: Hardware gain + type: integer + rx0GainMode: + type: integer + rx0AntennaPath: + type: integer + rx1Gain: + description: Hardware gain + type: integer + rx1GainMode: + type: integer + rx1AntennaPath: + type: integer + txCenterFrequency: + type: integer + format: int64 + fcPosTx: + description: 0=Infra 1=Supra 2=Center + type: integer + txTransverterMode: + type: integer + txTransverterDeltaFrequency: + type: integer + format: int64 + lpfBWTx: + description: Analog lowpass filter bandwidth (Hz) + type: integer + lpfTxFIREnable: + description: Low pass FIR filter enable (1 if enabled else 0) + type: integer + lpfTxFIRBW: + description: digital lowpass FIR filter bandwidth (Hz) + type: integer + lpfTxFIRlog2Interp: + description: digital lowpass FIR filter log2 of interpolation factor (0..2) + type: integer + lpfTxFIRGain: + description: digital lowpass FIR filter gain (dB) + type: integer + log2Interp: + type: integer + tx0Att: + description: Hardware attenuator gain in decibel fourths (negative) + type: integer + tx0AntennaPath: + type: integer + tx1Att: + description: Hardware attenuator gain in decibel fourths (negative) + type: integer + tx1AntennaPath: + type: integer + PlutoSdrInputReport: description: PlutoSDR properties: @@ -136,3 +240,23 @@ PlutoSdrOutputReport: temperature: type: number format: float + +PlutoSdrMIMOReport: + description: PlutoSDR + properties: + adcRate: + type: integer + dacRate: + type: integer + rx0GainDB: + type: integer + rx1GainDB: + type: integer + rssiRx0: + type: string + rssiRx1: + type: string + rssiTx0: + type: string + rssiTx1: + type: string diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 264d20a8e..f210e96d8 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -2832,6 +2832,9 @@ margin-bottom: 20px; "DATVDemodSettings" : { "$ref" : "#/definitions/DATVDemodSettings" }, + "DABDemodSettings" : { + "$ref" : "#/definitions/DABDemodSettings" + }, "DSDDemodSettings" : { "$ref" : "#/definitions/DSDDemodSettings" }, @@ -3341,6 +3344,58 @@ margin-bottom: 20px; } }, "description" : "A complex number" +}; + defs.DABDemodSettings = { + "properties" : { + "inputFrequencyOffset" : { + "type" : "integer", + "format" : "int64" + }, + "rfBandwidth" : { + "type" : "number", + "format" : "float" + }, + "program" : { + "type" : "string" + }, + "volume" : { + "type" : "number", + "format" : "float" + }, + "audioMute" : { + "type" : "integer" + }, + "audioDeviceName" : { + "type" : "string" + }, + "rgbColor" : { + "type" : "integer" + }, + "title" : { + "type" : "string" + }, + "streamIndex" : { + "type" : "integer", + "description" : "MIMO channel. Not relevant when connected to SI (single Rx)." + }, + "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" : "DABDemod" }; defs.DATVDemodSettings = { "properties" : { @@ -3918,6 +3973,9 @@ margin-bottom: 20px; "plutoSdrOutputReport" : { "$ref" : "#/definitions/PlutoSdrOutputReport" }, + "plutoSdrMIMOReport" : { + "$ref" : "#/definitions/PlutoSdrMIMOReport" + }, "rtlSdrReport" : { "$ref" : "#/definitions/RtlSdrReport" }, @@ -4088,6 +4146,9 @@ margin-bottom: 20px; "plutoSdrOutputSettings" : { "$ref" : "#/definitions/PlutoSdrOutputSettings" }, + "plutoSdrMIMOSettings" : { + "$ref" : "#/definitions/PlutoSdrMIMOSettings" + }, "rtlSdrSettings" : { "$ref" : "#/definitions/RtlSdrSettings" }, @@ -7076,11 +7137,23 @@ margin-bottom: 20px; "type" : "integer" }, "ctcssOn" : { - "type" : "integer" + "type" : "integer", + "description" : "Enable CTCSS squelch (takes precedence on DCS) * 0 - disabled * 1 - enabled\n" }, "ctcssIndex" : { "type" : "integer" }, + "dcsOn" : { + "type" : "integer", + "description" : "Enable DCS squelch (only if CTCSS is off) * 0 - disabled * 1 - enabled\n" + }, + "dcsCode" : { + "type" : "integer" + }, + "dcsPositive" : { + "type" : "integer", + "description" : "Modulation direction: * 0 - reverse or negative - 1 for 0 and -1 for 1 * 1 - direct or positive - -1 for 0 and 1 for 1\n" + }, "rgbColor" : { "type" : "integer" }, @@ -7683,6 +7756,175 @@ margin-bottom: 20px; } }, "description" : "PlutoSDR" +}; + defs.PlutoSdrMIMOReport = { + "properties" : { + "adcRate" : { + "type" : "integer" + }, + "dacRate" : { + "type" : "integer" + }, + "rx0GainDB" : { + "type" : "integer" + }, + "rx1GainDB" : { + "type" : "integer" + }, + "rssiRx0" : { + "type" : "string" + }, + "rssiRx1" : { + "type" : "string" + }, + "rssiTx0" : { + "type" : "string" + }, + "rssiTx1" : { + "type" : "string" + } + }, + "description" : "PlutoSDR" +}; + defs.PlutoSdrMIMOSettings = { + "properties" : { + "devSampleRate" : { + "type" : "integer" + }, + "LOppmTenths" : { + "type" : "integer" + }, + "rxCenterFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "dcBlock" : { + "type" : "integer" + }, + "iqCorrection" : { + "type" : "integer" + }, + "hwBBDCBlock" : { + "type" : "integer" + }, + "hwRFDCBlock" : { + "type" : "integer" + }, + "hwIQCorrection" : { + "type" : "integer" + }, + "fcPosRx" : { + "type" : "integer", + "description" : "0=Infra 1=Supra 2=Center" + }, + "rxTransverterMode" : { + "type" : "integer" + }, + "rxTransverterDeltaFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "iqOrder" : { + "type" : "integer", + "description" : "IQ samples order\n * 0 - Q then I (swapped)\n * 1 - I then Q (straight)\n" + }, + "lpfBWRx" : { + "type" : "integer", + "description" : "Analog lowpass filter bandwidth (Hz)" + }, + "lpfRxFIREnable" : { + "type" : "integer", + "description" : "Low pass FIR filter enable (1 if enabled else 0)" + }, + "lpfRxFIRBW" : { + "type" : "integer", + "description" : "digital lowpass FIR filter bandwidth (Hz)" + }, + "lpfRxFIRlog2Decim" : { + "type" : "integer", + "description" : "digital lowpass FIR filter log2 of decimation factor (0..2)" + }, + "lpfRxFIRGain" : { + "type" : "integer", + "description" : "digital lowpass FIR filter gain (dB)" + }, + "log2Decim" : { + "type" : "integer" + }, + "rx0Gain" : { + "type" : "integer", + "description" : "Hardware gain" + }, + "rx0GainMode" : { + "type" : "integer" + }, + "rx0AntennaPath" : { + "type" : "integer" + }, + "rx1Gain" : { + "type" : "integer", + "description" : "Hardware gain" + }, + "rx1GainMode" : { + "type" : "integer" + }, + "rx1AntennaPath" : { + "type" : "integer" + }, + "txCenterFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "fcPosTx" : { + "type" : "integer", + "description" : "0=Infra 1=Supra 2=Center" + }, + "txTransverterMode" : { + "type" : "integer" + }, + "txTransverterDeltaFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "lpfBWTx" : { + "type" : "integer", + "description" : "Analog lowpass filter bandwidth (Hz)" + }, + "lpfTxFIREnable" : { + "type" : "integer", + "description" : "Low pass FIR filter enable (1 if enabled else 0)" + }, + "lpfTxFIRBW" : { + "type" : "integer", + "description" : "digital lowpass FIR filter bandwidth (Hz)" + }, + "lpfTxFIRlog2Interp" : { + "type" : "integer", + "description" : "digital lowpass FIR filter log2 of interpolation factor (0..2)" + }, + "lpfTxFIRGain" : { + "type" : "integer", + "description" : "digital lowpass FIR filter gain (dB)" + }, + "log2Interp" : { + "type" : "integer" + }, + "tx0Att" : { + "type" : "integer", + "description" : "Hardware attenuator gain in decibel fourths (negative)" + }, + "tx0AntennaPath" : { + "type" : "integer" + }, + "tx1Att" : { + "type" : "integer", + "description" : "Hardware attenuator gain in decibel fourths (negative)" + }, + "tx1AntennaPath" : { + "type" : "integer" + } + }, + "description" : "PlutoSDR" }; defs.PlutoSdrOutputReport = { "properties" : { @@ -46026,7 +46268,7 @@ except ApiException as e:
- Generated 2021-04-11T22:11:18.598+02:00 + Generated 2021-04-29T21:19:02.297+02:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp index 56b2a23b0..4fd4bff09 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp @@ -62,6 +62,8 @@ SWGDeviceReport::SWGDeviceReport() { m_pluto_sdr_input_report_isSet = false; pluto_sdr_output_report = nullptr; m_pluto_sdr_output_report_isSet = false; + pluto_sdr_mimo_report = nullptr; + m_pluto_sdr_mimo_report_isSet = false; rtl_sdr_report = nullptr; m_rtl_sdr_report_isSet = false; remote_output_report = nullptr; @@ -130,6 +132,8 @@ SWGDeviceReport::init() { m_pluto_sdr_input_report_isSet = false; pluto_sdr_output_report = new SWGPlutoSdrOutputReport(); m_pluto_sdr_output_report_isSet = false; + pluto_sdr_mimo_report = new SWGPlutoSdrMIMOReport(); + m_pluto_sdr_mimo_report_isSet = false; rtl_sdr_report = new SWGRtlSdrReport(); m_rtl_sdr_report_isSet = false; remote_output_report = new SWGRemoteOutputReport(); @@ -209,6 +213,9 @@ SWGDeviceReport::cleanup() { if(pluto_sdr_output_report != nullptr) { delete pluto_sdr_output_report; } + if(pluto_sdr_mimo_report != nullptr) { + delete pluto_sdr_mimo_report; + } if(rtl_sdr_report != nullptr) { delete rtl_sdr_report; } @@ -295,6 +302,8 @@ SWGDeviceReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&pluto_sdr_output_report, pJson["plutoSdrOutputReport"], "SWGPlutoSdrOutputReport", "SWGPlutoSdrOutputReport"); + ::SWGSDRangel::setValue(&pluto_sdr_mimo_report, pJson["plutoSdrMIMOReport"], "SWGPlutoSdrMIMOReport", "SWGPlutoSdrMIMOReport"); + ::SWGSDRangel::setValue(&rtl_sdr_report, pJson["rtlSdrReport"], "SWGRtlSdrReport", "SWGRtlSdrReport"); ::SWGSDRangel::setValue(&remote_output_report, pJson["remoteOutputReport"], "SWGRemoteOutputReport", "SWGRemoteOutputReport"); @@ -388,6 +397,9 @@ SWGDeviceReport::asJsonObject() { if((pluto_sdr_output_report != nullptr) && (pluto_sdr_output_report->isSet())){ toJsonValue(QString("plutoSdrOutputReport"), pluto_sdr_output_report, obj, QString("SWGPlutoSdrOutputReport")); } + if((pluto_sdr_mimo_report != nullptr) && (pluto_sdr_mimo_report->isSet())){ + toJsonValue(QString("plutoSdrMIMOReport"), pluto_sdr_mimo_report, obj, QString("SWGPlutoSdrMIMOReport")); + } if((rtl_sdr_report != nullptr) && (rtl_sdr_report->isSet())){ toJsonValue(QString("rtlSdrReport"), rtl_sdr_report, obj, QString("SWGRtlSdrReport")); } @@ -601,6 +613,16 @@ SWGDeviceReport::setPlutoSdrOutputReport(SWGPlutoSdrOutputReport* pluto_sdr_outp this->m_pluto_sdr_output_report_isSet = true; } +SWGPlutoSdrMIMOReport* +SWGDeviceReport::getPlutoSdrMimoReport() { + return pluto_sdr_mimo_report; +} +void +SWGDeviceReport::setPlutoSdrMimoReport(SWGPlutoSdrMIMOReport* pluto_sdr_mimo_report) { + this->pluto_sdr_mimo_report = pluto_sdr_mimo_report; + this->m_pluto_sdr_mimo_report_isSet = true; +} + SWGRtlSdrReport* SWGDeviceReport::getRtlSdrReport() { return rtl_sdr_report; @@ -787,6 +809,9 @@ SWGDeviceReport::isSet(){ if(pluto_sdr_output_report && pluto_sdr_output_report->isSet()){ isObjectUpdated = true; break; } + if(pluto_sdr_mimo_report && pluto_sdr_mimo_report->isSet()){ + isObjectUpdated = true; break; + } if(rtl_sdr_report && rtl_sdr_report->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h index 363210779..1026d7e3c 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h @@ -36,6 +36,7 @@ #include "SWGLocalOutputReport.h" #include "SWGPerseusReport.h" #include "SWGPlutoSdrInputReport.h" +#include "SWGPlutoSdrMIMOReport.h" #include "SWGPlutoSdrOutputReport.h" #include "SWGRemoteInputReport.h" #include "SWGRemoteOutputReport.h" @@ -120,6 +121,9 @@ public: SWGPlutoSdrOutputReport* getPlutoSdrOutputReport(); void setPlutoSdrOutputReport(SWGPlutoSdrOutputReport* pluto_sdr_output_report); + SWGPlutoSdrMIMOReport* getPlutoSdrMimoReport(); + void setPlutoSdrMimoReport(SWGPlutoSdrMIMOReport* pluto_sdr_mimo_report); + SWGRtlSdrReport* getRtlSdrReport(); void setRtlSdrReport(SWGRtlSdrReport* rtl_sdr_report); @@ -214,6 +218,9 @@ private: SWGPlutoSdrOutputReport* pluto_sdr_output_report; bool m_pluto_sdr_output_report_isSet; + SWGPlutoSdrMIMOReport* pluto_sdr_mimo_report; + bool m_pluto_sdr_mimo_report_isSet; + SWGRtlSdrReport* rtl_sdr_report; bool m_rtl_sdr_report_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp index 283cf9b4d..e188eda77 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp @@ -82,6 +82,8 @@ SWGDeviceSettings::SWGDeviceSettings() { m_pluto_sdr_input_settings_isSet = false; pluto_sdr_output_settings = nullptr; m_pluto_sdr_output_settings_isSet = false; + pluto_sdr_mimo_settings = nullptr; + m_pluto_sdr_mimo_settings_isSet = false; rtl_sdr_settings = nullptr; m_rtl_sdr_settings_isSet = false; remote_output_settings = nullptr; @@ -176,6 +178,8 @@ SWGDeviceSettings::init() { m_pluto_sdr_input_settings_isSet = false; pluto_sdr_output_settings = new SWGPlutoSdrOutputSettings(); m_pluto_sdr_output_settings_isSet = false; + pluto_sdr_mimo_settings = new SWGPlutoSdrMIMOSettings(); + m_pluto_sdr_mimo_settings_isSet = false; rtl_sdr_settings = new SWGRtlSdrSettings(); m_rtl_sdr_settings_isSet = false; remote_output_settings = new SWGRemoteOutputSettings(); @@ -289,6 +293,9 @@ SWGDeviceSettings::cleanup() { if(pluto_sdr_output_settings != nullptr) { delete pluto_sdr_output_settings; } + if(pluto_sdr_mimo_settings != nullptr) { + delete pluto_sdr_mimo_settings; + } if(rtl_sdr_settings != nullptr) { delete rtl_sdr_settings; } @@ -404,6 +411,8 @@ SWGDeviceSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&pluto_sdr_output_settings, pJson["plutoSdrOutputSettings"], "SWGPlutoSdrOutputSettings", "SWGPlutoSdrOutputSettings"); + ::SWGSDRangel::setValue(&pluto_sdr_mimo_settings, pJson["plutoSdrMIMOSettings"], "SWGPlutoSdrMIMOSettings", "SWGPlutoSdrMIMOSettings"); + ::SWGSDRangel::setValue(&rtl_sdr_settings, pJson["rtlSdrSettings"], "SWGRtlSdrSettings", "SWGRtlSdrSettings"); ::SWGSDRangel::setValue(&remote_output_settings, pJson["remoteOutputSettings"], "SWGRemoteOutputSettings", "SWGRemoteOutputSettings"); @@ -533,6 +542,9 @@ SWGDeviceSettings::asJsonObject() { if((pluto_sdr_output_settings != nullptr) && (pluto_sdr_output_settings->isSet())){ toJsonValue(QString("plutoSdrOutputSettings"), pluto_sdr_output_settings, obj, QString("SWGPlutoSdrOutputSettings")); } + if((pluto_sdr_mimo_settings != nullptr) && (pluto_sdr_mimo_settings->isSet())){ + toJsonValue(QString("plutoSdrMIMOSettings"), pluto_sdr_mimo_settings, obj, QString("SWGPlutoSdrMIMOSettings")); + } if((rtl_sdr_settings != nullptr) && (rtl_sdr_settings->isSet())){ toJsonValue(QString("rtlSdrSettings"), rtl_sdr_settings, obj, QString("SWGRtlSdrSettings")); } @@ -855,6 +867,16 @@ SWGDeviceSettings::setPlutoSdrOutputSettings(SWGPlutoSdrOutputSettings* pluto_sd this->m_pluto_sdr_output_settings_isSet = true; } +SWGPlutoSdrMIMOSettings* +SWGDeviceSettings::getPlutoSdrMimoSettings() { + return pluto_sdr_mimo_settings; +} +void +SWGDeviceSettings::setPlutoSdrMimoSettings(SWGPlutoSdrMIMOSettings* pluto_sdr_mimo_settings) { + this->pluto_sdr_mimo_settings = pluto_sdr_mimo_settings; + this->m_pluto_sdr_mimo_settings_isSet = true; +} + SWGRtlSdrSettings* SWGDeviceSettings::getRtlSdrSettings() { return rtl_sdr_settings; @@ -1101,6 +1123,9 @@ SWGDeviceSettings::isSet(){ if(pluto_sdr_output_settings && pluto_sdr_output_settings->isSet()){ isObjectUpdated = true; break; } + if(pluto_sdr_mimo_settings && pluto_sdr_mimo_settings->isSet()){ + isObjectUpdated = true; break; + } if(rtl_sdr_settings && rtl_sdr_settings->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h index e7f01b239..26a1cd207 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h @@ -45,6 +45,7 @@ #include "SWGMetisMISOSettings.h" #include "SWGPerseusSettings.h" #include "SWGPlutoSdrInputSettings.h" +#include "SWGPlutoSdrMIMOSettings.h" #include "SWGPlutoSdrOutputSettings.h" #include "SWGRemoteInputSettings.h" #include "SWGRemoteOutputSettings.h" @@ -163,6 +164,9 @@ public: SWGPlutoSdrOutputSettings* getPlutoSdrOutputSettings(); void setPlutoSdrOutputSettings(SWGPlutoSdrOutputSettings* pluto_sdr_output_settings); + SWGPlutoSdrMIMOSettings* getPlutoSdrMimoSettings(); + void setPlutoSdrMimoSettings(SWGPlutoSdrMIMOSettings* pluto_sdr_mimo_settings); + SWGRtlSdrSettings* getRtlSdrSettings(); void setRtlSdrSettings(SWGRtlSdrSettings* rtl_sdr_settings); @@ -296,6 +300,9 @@ private: SWGPlutoSdrOutputSettings* pluto_sdr_output_settings; bool m_pluto_sdr_output_settings_isSet; + SWGPlutoSdrMIMOSettings* pluto_sdr_mimo_settings; + bool m_pluto_sdr_mimo_settings_isSet; + SWGRtlSdrSettings* rtl_sdr_settings; bool m_rtl_sdr_settings_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h index 2d1dbd50b..73489fc32 100644 --- a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h +++ b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h @@ -175,6 +175,8 @@ #include "SWGPerseusSettings.h" #include "SWGPlutoSdrInputReport.h" #include "SWGPlutoSdrInputSettings.h" +#include "SWGPlutoSdrMIMOReport.h" +#include "SWGPlutoSdrMIMOSettings.h" #include "SWGPlutoSdrOutputReport.h" #include "SWGPlutoSdrOutputSettings.h" #include "SWGPreferences.h" @@ -746,6 +748,12 @@ namespace SWGSDRangel { if(QString("SWGPlutoSdrInputSettings").compare(type) == 0) { return new SWGPlutoSdrInputSettings(); } + if(QString("SWGPlutoSdrMIMOReport").compare(type) == 0) { + return new SWGPlutoSdrMIMOReport(); + } + if(QString("SWGPlutoSdrMIMOSettings").compare(type) == 0) { + return new SWGPlutoSdrMIMOSettings(); + } if(QString("SWGPlutoSdrOutputReport").compare(type) == 0) { return new SWGPlutoSdrOutputReport(); } diff --git a/swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOReport.cpp b/swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOReport.cpp new file mode 100644 index 000000000..cffafc9b8 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOReport.cpp @@ -0,0 +1,277 @@ +/** + * 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 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: 6.0.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 "SWGPlutoSdrMIMOReport.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGPlutoSdrMIMOReport::SWGPlutoSdrMIMOReport(QString* json) { + init(); + this->fromJson(*json); +} + +SWGPlutoSdrMIMOReport::SWGPlutoSdrMIMOReport() { + adc_rate = 0; + m_adc_rate_isSet = false; + dac_rate = 0; + m_dac_rate_isSet = false; + rx0_gain_db = 0; + m_rx0_gain_db_isSet = false; + rx1_gain_db = 0; + m_rx1_gain_db_isSet = false; + rssi_rx0 = nullptr; + m_rssi_rx0_isSet = false; + rssi_rx1 = nullptr; + m_rssi_rx1_isSet = false; + rssi_tx0 = nullptr; + m_rssi_tx0_isSet = false; + rssi_tx1 = nullptr; + m_rssi_tx1_isSet = false; +} + +SWGPlutoSdrMIMOReport::~SWGPlutoSdrMIMOReport() { + this->cleanup(); +} + +void +SWGPlutoSdrMIMOReport::init() { + adc_rate = 0; + m_adc_rate_isSet = false; + dac_rate = 0; + m_dac_rate_isSet = false; + rx0_gain_db = 0; + m_rx0_gain_db_isSet = false; + rx1_gain_db = 0; + m_rx1_gain_db_isSet = false; + rssi_rx0 = new QString(""); + m_rssi_rx0_isSet = false; + rssi_rx1 = new QString(""); + m_rssi_rx1_isSet = false; + rssi_tx0 = new QString(""); + m_rssi_tx0_isSet = false; + rssi_tx1 = new QString(""); + m_rssi_tx1_isSet = false; +} + +void +SWGPlutoSdrMIMOReport::cleanup() { + + + + + if(rssi_rx0 != nullptr) { + delete rssi_rx0; + } + if(rssi_rx1 != nullptr) { + delete rssi_rx1; + } + if(rssi_tx0 != nullptr) { + delete rssi_tx0; + } + if(rssi_tx1 != nullptr) { + delete rssi_tx1; + } +} + +SWGPlutoSdrMIMOReport* +SWGPlutoSdrMIMOReport::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGPlutoSdrMIMOReport::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&adc_rate, pJson["adcRate"], "qint32", ""); + + ::SWGSDRangel::setValue(&dac_rate, pJson["dacRate"], "qint32", ""); + + ::SWGSDRangel::setValue(&rx0_gain_db, pJson["rx0GainDB"], "qint32", ""); + + ::SWGSDRangel::setValue(&rx1_gain_db, pJson["rx1GainDB"], "qint32", ""); + + ::SWGSDRangel::setValue(&rssi_rx0, pJson["rssiRx0"], "QString", "QString"); + + ::SWGSDRangel::setValue(&rssi_rx1, pJson["rssiRx1"], "QString", "QString"); + + ::SWGSDRangel::setValue(&rssi_tx0, pJson["rssiTx0"], "QString", "QString"); + + ::SWGSDRangel::setValue(&rssi_tx1, pJson["rssiTx1"], "QString", "QString"); + +} + +QString +SWGPlutoSdrMIMOReport::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGPlutoSdrMIMOReport::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_adc_rate_isSet){ + obj->insert("adcRate", QJsonValue(adc_rate)); + } + if(m_dac_rate_isSet){ + obj->insert("dacRate", QJsonValue(dac_rate)); + } + if(m_rx0_gain_db_isSet){ + obj->insert("rx0GainDB", QJsonValue(rx0_gain_db)); + } + if(m_rx1_gain_db_isSet){ + obj->insert("rx1GainDB", QJsonValue(rx1_gain_db)); + } + if(rssi_rx0 != nullptr && *rssi_rx0 != QString("")){ + toJsonValue(QString("rssiRx0"), rssi_rx0, obj, QString("QString")); + } + if(rssi_rx1 != nullptr && *rssi_rx1 != QString("")){ + toJsonValue(QString("rssiRx1"), rssi_rx1, obj, QString("QString")); + } + if(rssi_tx0 != nullptr && *rssi_tx0 != QString("")){ + toJsonValue(QString("rssiTx0"), rssi_tx0, obj, QString("QString")); + } + if(rssi_tx1 != nullptr && *rssi_tx1 != QString("")){ + toJsonValue(QString("rssiTx1"), rssi_tx1, obj, QString("QString")); + } + + return obj; +} + +qint32 +SWGPlutoSdrMIMOReport::getAdcRate() { + return adc_rate; +} +void +SWGPlutoSdrMIMOReport::setAdcRate(qint32 adc_rate) { + this->adc_rate = adc_rate; + this->m_adc_rate_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOReport::getDacRate() { + return dac_rate; +} +void +SWGPlutoSdrMIMOReport::setDacRate(qint32 dac_rate) { + this->dac_rate = dac_rate; + this->m_dac_rate_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOReport::getRx0GainDb() { + return rx0_gain_db; +} +void +SWGPlutoSdrMIMOReport::setRx0GainDb(qint32 rx0_gain_db) { + this->rx0_gain_db = rx0_gain_db; + this->m_rx0_gain_db_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOReport::getRx1GainDb() { + return rx1_gain_db; +} +void +SWGPlutoSdrMIMOReport::setRx1GainDb(qint32 rx1_gain_db) { + this->rx1_gain_db = rx1_gain_db; + this->m_rx1_gain_db_isSet = true; +} + +QString* +SWGPlutoSdrMIMOReport::getRssiRx0() { + return rssi_rx0; +} +void +SWGPlutoSdrMIMOReport::setRssiRx0(QString* rssi_rx0) { + this->rssi_rx0 = rssi_rx0; + this->m_rssi_rx0_isSet = true; +} + +QString* +SWGPlutoSdrMIMOReport::getRssiRx1() { + return rssi_rx1; +} +void +SWGPlutoSdrMIMOReport::setRssiRx1(QString* rssi_rx1) { + this->rssi_rx1 = rssi_rx1; + this->m_rssi_rx1_isSet = true; +} + +QString* +SWGPlutoSdrMIMOReport::getRssiTx0() { + return rssi_tx0; +} +void +SWGPlutoSdrMIMOReport::setRssiTx0(QString* rssi_tx0) { + this->rssi_tx0 = rssi_tx0; + this->m_rssi_tx0_isSet = true; +} + +QString* +SWGPlutoSdrMIMOReport::getRssiTx1() { + return rssi_tx1; +} +void +SWGPlutoSdrMIMOReport::setRssiTx1(QString* rssi_tx1) { + this->rssi_tx1 = rssi_tx1; + this->m_rssi_tx1_isSet = true; +} + + +bool +SWGPlutoSdrMIMOReport::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_adc_rate_isSet){ + isObjectUpdated = true; break; + } + if(m_dac_rate_isSet){ + isObjectUpdated = true; break; + } + if(m_rx0_gain_db_isSet){ + isObjectUpdated = true; break; + } + if(m_rx1_gain_db_isSet){ + isObjectUpdated = true; break; + } + if(rssi_rx0 && *rssi_rx0 != QString("")){ + isObjectUpdated = true; break; + } + if(rssi_rx1 && *rssi_rx1 != QString("")){ + isObjectUpdated = true; break; + } + if(rssi_tx0 && *rssi_tx0 != QString("")){ + isObjectUpdated = true; break; + } + if(rssi_tx1 && *rssi_tx1 != QString("")){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOReport.h b/swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOReport.h new file mode 100644 index 000000000..8ceeb0531 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOReport.h @@ -0,0 +1,101 @@ +/** + * 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 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: 6.0.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. + */ + +/* + * SWGPlutoSdrMIMOReport.h + * + * PlutoSDR + */ + +#ifndef SWGPlutoSdrMIMOReport_H_ +#define SWGPlutoSdrMIMOReport_H_ + +#include + + +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGPlutoSdrMIMOReport: public SWGObject { +public: + SWGPlutoSdrMIMOReport(); + SWGPlutoSdrMIMOReport(QString* json); + virtual ~SWGPlutoSdrMIMOReport(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGPlutoSdrMIMOReport* fromJson(QString &jsonString) override; + + qint32 getAdcRate(); + void setAdcRate(qint32 adc_rate); + + qint32 getDacRate(); + void setDacRate(qint32 dac_rate); + + qint32 getRx0GainDb(); + void setRx0GainDb(qint32 rx0_gain_db); + + qint32 getRx1GainDb(); + void setRx1GainDb(qint32 rx1_gain_db); + + QString* getRssiRx0(); + void setRssiRx0(QString* rssi_rx0); + + QString* getRssiRx1(); + void setRssiRx1(QString* rssi_rx1); + + QString* getRssiTx0(); + void setRssiTx0(QString* rssi_tx0); + + QString* getRssiTx1(); + void setRssiTx1(QString* rssi_tx1); + + + virtual bool isSet() override; + +private: + qint32 adc_rate; + bool m_adc_rate_isSet; + + qint32 dac_rate; + bool m_dac_rate_isSet; + + qint32 rx0_gain_db; + bool m_rx0_gain_db_isSet; + + qint32 rx1_gain_db; + bool m_rx1_gain_db_isSet; + + QString* rssi_rx0; + bool m_rssi_rx0_isSet; + + QString* rssi_rx1; + bool m_rssi_rx1_isSet; + + QString* rssi_tx0; + bool m_rssi_tx0_isSet; + + QString* rssi_tx1; + bool m_rssi_tx1_isSet; + +}; + +} + +#endif /* SWGPlutoSdrMIMOReport_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOSettings.cpp new file mode 100644 index 000000000..9bf49fe2f --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOSettings.cpp @@ -0,0 +1,959 @@ +/** + * 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 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: 6.0.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 "SWGPlutoSdrMIMOSettings.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGPlutoSdrMIMOSettings::SWGPlutoSdrMIMOSettings(QString* json) { + init(); + this->fromJson(*json); +} + +SWGPlutoSdrMIMOSettings::SWGPlutoSdrMIMOSettings() { + dev_sample_rate = 0; + m_dev_sample_rate_isSet = false; + l_oppm_tenths = 0; + m_l_oppm_tenths_isSet = false; + rx_center_frequency = 0L; + m_rx_center_frequency_isSet = false; + dc_block = 0; + m_dc_block_isSet = false; + iq_correction = 0; + m_iq_correction_isSet = false; + hw_bbdc_block = 0; + m_hw_bbdc_block_isSet = false; + hw_rfdc_block = 0; + m_hw_rfdc_block_isSet = false; + hw_iq_correction = 0; + m_hw_iq_correction_isSet = false; + fc_pos_rx = 0; + m_fc_pos_rx_isSet = false; + rx_transverter_mode = 0; + m_rx_transverter_mode_isSet = false; + rx_transverter_delta_frequency = 0L; + m_rx_transverter_delta_frequency_isSet = false; + iq_order = 0; + m_iq_order_isSet = false; + lpf_bw_rx = 0; + m_lpf_bw_rx_isSet = false; + lpf_rx_fir_enable = 0; + m_lpf_rx_fir_enable_isSet = false; + lpf_rx_firbw = 0; + m_lpf_rx_firbw_isSet = false; + lpf_rx_fi_rlog2_decim = 0; + m_lpf_rx_fi_rlog2_decim_isSet = false; + lpf_rx_fir_gain = 0; + m_lpf_rx_fir_gain_isSet = false; + log2_decim = 0; + m_log2_decim_isSet = false; + rx0_gain = 0; + m_rx0_gain_isSet = false; + rx0_gain_mode = 0; + m_rx0_gain_mode_isSet = false; + rx0_antenna_path = 0; + m_rx0_antenna_path_isSet = false; + rx1_gain = 0; + m_rx1_gain_isSet = false; + rx1_gain_mode = 0; + m_rx1_gain_mode_isSet = false; + rx1_antenna_path = 0; + m_rx1_antenna_path_isSet = false; + tx_center_frequency = 0L; + m_tx_center_frequency_isSet = false; + fc_pos_tx = 0; + m_fc_pos_tx_isSet = false; + tx_transverter_mode = 0; + m_tx_transverter_mode_isSet = false; + tx_transverter_delta_frequency = 0L; + m_tx_transverter_delta_frequency_isSet = false; + lpf_bw_tx = 0; + m_lpf_bw_tx_isSet = false; + lpf_tx_fir_enable = 0; + m_lpf_tx_fir_enable_isSet = false; + lpf_tx_firbw = 0; + m_lpf_tx_firbw_isSet = false; + lpf_tx_fi_rlog2_interp = 0; + m_lpf_tx_fi_rlog2_interp_isSet = false; + lpf_tx_fir_gain = 0; + m_lpf_tx_fir_gain_isSet = false; + log2_interp = 0; + m_log2_interp_isSet = false; + tx0_att = 0; + m_tx0_att_isSet = false; + tx0_antenna_path = 0; + m_tx0_antenna_path_isSet = false; + tx1_att = 0; + m_tx1_att_isSet = false; + tx1_antenna_path = 0; + m_tx1_antenna_path_isSet = false; +} + +SWGPlutoSdrMIMOSettings::~SWGPlutoSdrMIMOSettings() { + this->cleanup(); +} + +void +SWGPlutoSdrMIMOSettings::init() { + dev_sample_rate = 0; + m_dev_sample_rate_isSet = false; + l_oppm_tenths = 0; + m_l_oppm_tenths_isSet = false; + rx_center_frequency = 0L; + m_rx_center_frequency_isSet = false; + dc_block = 0; + m_dc_block_isSet = false; + iq_correction = 0; + m_iq_correction_isSet = false; + hw_bbdc_block = 0; + m_hw_bbdc_block_isSet = false; + hw_rfdc_block = 0; + m_hw_rfdc_block_isSet = false; + hw_iq_correction = 0; + m_hw_iq_correction_isSet = false; + fc_pos_rx = 0; + m_fc_pos_rx_isSet = false; + rx_transverter_mode = 0; + m_rx_transverter_mode_isSet = false; + rx_transverter_delta_frequency = 0L; + m_rx_transverter_delta_frequency_isSet = false; + iq_order = 0; + m_iq_order_isSet = false; + lpf_bw_rx = 0; + m_lpf_bw_rx_isSet = false; + lpf_rx_fir_enable = 0; + m_lpf_rx_fir_enable_isSet = false; + lpf_rx_firbw = 0; + m_lpf_rx_firbw_isSet = false; + lpf_rx_fi_rlog2_decim = 0; + m_lpf_rx_fi_rlog2_decim_isSet = false; + lpf_rx_fir_gain = 0; + m_lpf_rx_fir_gain_isSet = false; + log2_decim = 0; + m_log2_decim_isSet = false; + rx0_gain = 0; + m_rx0_gain_isSet = false; + rx0_gain_mode = 0; + m_rx0_gain_mode_isSet = false; + rx0_antenna_path = 0; + m_rx0_antenna_path_isSet = false; + rx1_gain = 0; + m_rx1_gain_isSet = false; + rx1_gain_mode = 0; + m_rx1_gain_mode_isSet = false; + rx1_antenna_path = 0; + m_rx1_antenna_path_isSet = false; + tx_center_frequency = 0L; + m_tx_center_frequency_isSet = false; + fc_pos_tx = 0; + m_fc_pos_tx_isSet = false; + tx_transverter_mode = 0; + m_tx_transverter_mode_isSet = false; + tx_transverter_delta_frequency = 0L; + m_tx_transverter_delta_frequency_isSet = false; + lpf_bw_tx = 0; + m_lpf_bw_tx_isSet = false; + lpf_tx_fir_enable = 0; + m_lpf_tx_fir_enable_isSet = false; + lpf_tx_firbw = 0; + m_lpf_tx_firbw_isSet = false; + lpf_tx_fi_rlog2_interp = 0; + m_lpf_tx_fi_rlog2_interp_isSet = false; + lpf_tx_fir_gain = 0; + m_lpf_tx_fir_gain_isSet = false; + log2_interp = 0; + m_log2_interp_isSet = false; + tx0_att = 0; + m_tx0_att_isSet = false; + tx0_antenna_path = 0; + m_tx0_antenna_path_isSet = false; + tx1_att = 0; + m_tx1_att_isSet = false; + tx1_antenna_path = 0; + m_tx1_antenna_path_isSet = false; +} + +void +SWGPlutoSdrMIMOSettings::cleanup() { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +SWGPlutoSdrMIMOSettings* +SWGPlutoSdrMIMOSettings::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGPlutoSdrMIMOSettings::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&dev_sample_rate, pJson["devSampleRate"], "qint32", ""); + + ::SWGSDRangel::setValue(&l_oppm_tenths, pJson["LOppmTenths"], "qint32", ""); + + ::SWGSDRangel::setValue(&rx_center_frequency, pJson["rxCenterFrequency"], "qint64", ""); + + ::SWGSDRangel::setValue(&dc_block, pJson["dcBlock"], "qint32", ""); + + ::SWGSDRangel::setValue(&iq_correction, pJson["iqCorrection"], "qint32", ""); + + ::SWGSDRangel::setValue(&hw_bbdc_block, pJson["hwBBDCBlock"], "qint32", ""); + + ::SWGSDRangel::setValue(&hw_rfdc_block, pJson["hwRFDCBlock"], "qint32", ""); + + ::SWGSDRangel::setValue(&hw_iq_correction, pJson["hwIQCorrection"], "qint32", ""); + + ::SWGSDRangel::setValue(&fc_pos_rx, pJson["fcPosRx"], "qint32", ""); + + ::SWGSDRangel::setValue(&rx_transverter_mode, pJson["rxTransverterMode"], "qint32", ""); + + ::SWGSDRangel::setValue(&rx_transverter_delta_frequency, pJson["rxTransverterDeltaFrequency"], "qint64", ""); + + ::SWGSDRangel::setValue(&iq_order, pJson["iqOrder"], "qint32", ""); + + ::SWGSDRangel::setValue(&lpf_bw_rx, pJson["lpfBWRx"], "qint32", ""); + + ::SWGSDRangel::setValue(&lpf_rx_fir_enable, pJson["lpfRxFIREnable"], "qint32", ""); + + ::SWGSDRangel::setValue(&lpf_rx_firbw, pJson["lpfRxFIRBW"], "qint32", ""); + + ::SWGSDRangel::setValue(&lpf_rx_fi_rlog2_decim, pJson["lpfRxFIRlog2Decim"], "qint32", ""); + + ::SWGSDRangel::setValue(&lpf_rx_fir_gain, pJson["lpfRxFIRGain"], "qint32", ""); + + ::SWGSDRangel::setValue(&log2_decim, pJson["log2Decim"], "qint32", ""); + + ::SWGSDRangel::setValue(&rx0_gain, pJson["rx0Gain"], "qint32", ""); + + ::SWGSDRangel::setValue(&rx0_gain_mode, pJson["rx0GainMode"], "qint32", ""); + + ::SWGSDRangel::setValue(&rx0_antenna_path, pJson["rx0AntennaPath"], "qint32", ""); + + ::SWGSDRangel::setValue(&rx1_gain, pJson["rx1Gain"], "qint32", ""); + + ::SWGSDRangel::setValue(&rx1_gain_mode, pJson["rx1GainMode"], "qint32", ""); + + ::SWGSDRangel::setValue(&rx1_antenna_path, pJson["rx1AntennaPath"], "qint32", ""); + + ::SWGSDRangel::setValue(&tx_center_frequency, pJson["txCenterFrequency"], "qint64", ""); + + ::SWGSDRangel::setValue(&fc_pos_tx, pJson["fcPosTx"], "qint32", ""); + + ::SWGSDRangel::setValue(&tx_transverter_mode, pJson["txTransverterMode"], "qint32", ""); + + ::SWGSDRangel::setValue(&tx_transverter_delta_frequency, pJson["txTransverterDeltaFrequency"], "qint64", ""); + + ::SWGSDRangel::setValue(&lpf_bw_tx, pJson["lpfBWTx"], "qint32", ""); + + ::SWGSDRangel::setValue(&lpf_tx_fir_enable, pJson["lpfTxFIREnable"], "qint32", ""); + + ::SWGSDRangel::setValue(&lpf_tx_firbw, pJson["lpfTxFIRBW"], "qint32", ""); + + ::SWGSDRangel::setValue(&lpf_tx_fi_rlog2_interp, pJson["lpfTxFIRlog2Interp"], "qint32", ""); + + ::SWGSDRangel::setValue(&lpf_tx_fir_gain, pJson["lpfTxFIRGain"], "qint32", ""); + + ::SWGSDRangel::setValue(&log2_interp, pJson["log2Interp"], "qint32", ""); + + ::SWGSDRangel::setValue(&tx0_att, pJson["tx0Att"], "qint32", ""); + + ::SWGSDRangel::setValue(&tx0_antenna_path, pJson["tx0AntennaPath"], "qint32", ""); + + ::SWGSDRangel::setValue(&tx1_att, pJson["tx1Att"], "qint32", ""); + + ::SWGSDRangel::setValue(&tx1_antenna_path, pJson["tx1AntennaPath"], "qint32", ""); + +} + +QString +SWGPlutoSdrMIMOSettings::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGPlutoSdrMIMOSettings::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_dev_sample_rate_isSet){ + obj->insert("devSampleRate", QJsonValue(dev_sample_rate)); + } + if(m_l_oppm_tenths_isSet){ + obj->insert("LOppmTenths", QJsonValue(l_oppm_tenths)); + } + if(m_rx_center_frequency_isSet){ + obj->insert("rxCenterFrequency", QJsonValue(rx_center_frequency)); + } + if(m_dc_block_isSet){ + obj->insert("dcBlock", QJsonValue(dc_block)); + } + if(m_iq_correction_isSet){ + obj->insert("iqCorrection", QJsonValue(iq_correction)); + } + if(m_hw_bbdc_block_isSet){ + obj->insert("hwBBDCBlock", QJsonValue(hw_bbdc_block)); + } + if(m_hw_rfdc_block_isSet){ + obj->insert("hwRFDCBlock", QJsonValue(hw_rfdc_block)); + } + if(m_hw_iq_correction_isSet){ + obj->insert("hwIQCorrection", QJsonValue(hw_iq_correction)); + } + if(m_fc_pos_rx_isSet){ + obj->insert("fcPosRx", QJsonValue(fc_pos_rx)); + } + if(m_rx_transverter_mode_isSet){ + obj->insert("rxTransverterMode", QJsonValue(rx_transverter_mode)); + } + if(m_rx_transverter_delta_frequency_isSet){ + obj->insert("rxTransverterDeltaFrequency", QJsonValue(rx_transverter_delta_frequency)); + } + if(m_iq_order_isSet){ + obj->insert("iqOrder", QJsonValue(iq_order)); + } + if(m_lpf_bw_rx_isSet){ + obj->insert("lpfBWRx", QJsonValue(lpf_bw_rx)); + } + if(m_lpf_rx_fir_enable_isSet){ + obj->insert("lpfRxFIREnable", QJsonValue(lpf_rx_fir_enable)); + } + if(m_lpf_rx_firbw_isSet){ + obj->insert("lpfRxFIRBW", QJsonValue(lpf_rx_firbw)); + } + if(m_lpf_rx_fi_rlog2_decim_isSet){ + obj->insert("lpfRxFIRlog2Decim", QJsonValue(lpf_rx_fi_rlog2_decim)); + } + if(m_lpf_rx_fir_gain_isSet){ + obj->insert("lpfRxFIRGain", QJsonValue(lpf_rx_fir_gain)); + } + if(m_log2_decim_isSet){ + obj->insert("log2Decim", QJsonValue(log2_decim)); + } + if(m_rx0_gain_isSet){ + obj->insert("rx0Gain", QJsonValue(rx0_gain)); + } + if(m_rx0_gain_mode_isSet){ + obj->insert("rx0GainMode", QJsonValue(rx0_gain_mode)); + } + if(m_rx0_antenna_path_isSet){ + obj->insert("rx0AntennaPath", QJsonValue(rx0_antenna_path)); + } + if(m_rx1_gain_isSet){ + obj->insert("rx1Gain", QJsonValue(rx1_gain)); + } + if(m_rx1_gain_mode_isSet){ + obj->insert("rx1GainMode", QJsonValue(rx1_gain_mode)); + } + if(m_rx1_antenna_path_isSet){ + obj->insert("rx1AntennaPath", QJsonValue(rx1_antenna_path)); + } + if(m_tx_center_frequency_isSet){ + obj->insert("txCenterFrequency", QJsonValue(tx_center_frequency)); + } + if(m_fc_pos_tx_isSet){ + obj->insert("fcPosTx", QJsonValue(fc_pos_tx)); + } + if(m_tx_transverter_mode_isSet){ + obj->insert("txTransverterMode", QJsonValue(tx_transverter_mode)); + } + if(m_tx_transverter_delta_frequency_isSet){ + obj->insert("txTransverterDeltaFrequency", QJsonValue(tx_transverter_delta_frequency)); + } + if(m_lpf_bw_tx_isSet){ + obj->insert("lpfBWTx", QJsonValue(lpf_bw_tx)); + } + if(m_lpf_tx_fir_enable_isSet){ + obj->insert("lpfTxFIREnable", QJsonValue(lpf_tx_fir_enable)); + } + if(m_lpf_tx_firbw_isSet){ + obj->insert("lpfTxFIRBW", QJsonValue(lpf_tx_firbw)); + } + if(m_lpf_tx_fi_rlog2_interp_isSet){ + obj->insert("lpfTxFIRlog2Interp", QJsonValue(lpf_tx_fi_rlog2_interp)); + } + if(m_lpf_tx_fir_gain_isSet){ + obj->insert("lpfTxFIRGain", QJsonValue(lpf_tx_fir_gain)); + } + if(m_log2_interp_isSet){ + obj->insert("log2Interp", QJsonValue(log2_interp)); + } + if(m_tx0_att_isSet){ + obj->insert("tx0Att", QJsonValue(tx0_att)); + } + if(m_tx0_antenna_path_isSet){ + obj->insert("tx0AntennaPath", QJsonValue(tx0_antenna_path)); + } + if(m_tx1_att_isSet){ + obj->insert("tx1Att", QJsonValue(tx1_att)); + } + if(m_tx1_antenna_path_isSet){ + obj->insert("tx1AntennaPath", QJsonValue(tx1_antenna_path)); + } + + return obj; +} + +qint32 +SWGPlutoSdrMIMOSettings::getDevSampleRate() { + return dev_sample_rate; +} +void +SWGPlutoSdrMIMOSettings::setDevSampleRate(qint32 dev_sample_rate) { + this->dev_sample_rate = dev_sample_rate; + this->m_dev_sample_rate_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getLOppmTenths() { + return l_oppm_tenths; +} +void +SWGPlutoSdrMIMOSettings::setLOppmTenths(qint32 l_oppm_tenths) { + this->l_oppm_tenths = l_oppm_tenths; + this->m_l_oppm_tenths_isSet = true; +} + +qint64 +SWGPlutoSdrMIMOSettings::getRxCenterFrequency() { + return rx_center_frequency; +} +void +SWGPlutoSdrMIMOSettings::setRxCenterFrequency(qint64 rx_center_frequency) { + this->rx_center_frequency = rx_center_frequency; + this->m_rx_center_frequency_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getDcBlock() { + return dc_block; +} +void +SWGPlutoSdrMIMOSettings::setDcBlock(qint32 dc_block) { + this->dc_block = dc_block; + this->m_dc_block_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getIqCorrection() { + return iq_correction; +} +void +SWGPlutoSdrMIMOSettings::setIqCorrection(qint32 iq_correction) { + this->iq_correction = iq_correction; + this->m_iq_correction_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getHwBbdcBlock() { + return hw_bbdc_block; +} +void +SWGPlutoSdrMIMOSettings::setHwBbdcBlock(qint32 hw_bbdc_block) { + this->hw_bbdc_block = hw_bbdc_block; + this->m_hw_bbdc_block_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getHwRfdcBlock() { + return hw_rfdc_block; +} +void +SWGPlutoSdrMIMOSettings::setHwRfdcBlock(qint32 hw_rfdc_block) { + this->hw_rfdc_block = hw_rfdc_block; + this->m_hw_rfdc_block_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getHwIqCorrection() { + return hw_iq_correction; +} +void +SWGPlutoSdrMIMOSettings::setHwIqCorrection(qint32 hw_iq_correction) { + this->hw_iq_correction = hw_iq_correction; + this->m_hw_iq_correction_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getFcPosRx() { + return fc_pos_rx; +} +void +SWGPlutoSdrMIMOSettings::setFcPosRx(qint32 fc_pos_rx) { + this->fc_pos_rx = fc_pos_rx; + this->m_fc_pos_rx_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getRxTransverterMode() { + return rx_transverter_mode; +} +void +SWGPlutoSdrMIMOSettings::setRxTransverterMode(qint32 rx_transverter_mode) { + this->rx_transverter_mode = rx_transverter_mode; + this->m_rx_transverter_mode_isSet = true; +} + +qint64 +SWGPlutoSdrMIMOSettings::getRxTransverterDeltaFrequency() { + return rx_transverter_delta_frequency; +} +void +SWGPlutoSdrMIMOSettings::setRxTransverterDeltaFrequency(qint64 rx_transverter_delta_frequency) { + this->rx_transverter_delta_frequency = rx_transverter_delta_frequency; + this->m_rx_transverter_delta_frequency_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getIqOrder() { + return iq_order; +} +void +SWGPlutoSdrMIMOSettings::setIqOrder(qint32 iq_order) { + this->iq_order = iq_order; + this->m_iq_order_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getLpfBwRx() { + return lpf_bw_rx; +} +void +SWGPlutoSdrMIMOSettings::setLpfBwRx(qint32 lpf_bw_rx) { + this->lpf_bw_rx = lpf_bw_rx; + this->m_lpf_bw_rx_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getLpfRxFirEnable() { + return lpf_rx_fir_enable; +} +void +SWGPlutoSdrMIMOSettings::setLpfRxFirEnable(qint32 lpf_rx_fir_enable) { + this->lpf_rx_fir_enable = lpf_rx_fir_enable; + this->m_lpf_rx_fir_enable_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getLpfRxFirbw() { + return lpf_rx_firbw; +} +void +SWGPlutoSdrMIMOSettings::setLpfRxFirbw(qint32 lpf_rx_firbw) { + this->lpf_rx_firbw = lpf_rx_firbw; + this->m_lpf_rx_firbw_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getLpfRxFiRlog2Decim() { + return lpf_rx_fi_rlog2_decim; +} +void +SWGPlutoSdrMIMOSettings::setLpfRxFiRlog2Decim(qint32 lpf_rx_fi_rlog2_decim) { + this->lpf_rx_fi_rlog2_decim = lpf_rx_fi_rlog2_decim; + this->m_lpf_rx_fi_rlog2_decim_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getLpfRxFirGain() { + return lpf_rx_fir_gain; +} +void +SWGPlutoSdrMIMOSettings::setLpfRxFirGain(qint32 lpf_rx_fir_gain) { + this->lpf_rx_fir_gain = lpf_rx_fir_gain; + this->m_lpf_rx_fir_gain_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getLog2Decim() { + return log2_decim; +} +void +SWGPlutoSdrMIMOSettings::setLog2Decim(qint32 log2_decim) { + this->log2_decim = log2_decim; + this->m_log2_decim_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getRx0Gain() { + return rx0_gain; +} +void +SWGPlutoSdrMIMOSettings::setRx0Gain(qint32 rx0_gain) { + this->rx0_gain = rx0_gain; + this->m_rx0_gain_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getRx0GainMode() { + return rx0_gain_mode; +} +void +SWGPlutoSdrMIMOSettings::setRx0GainMode(qint32 rx0_gain_mode) { + this->rx0_gain_mode = rx0_gain_mode; + this->m_rx0_gain_mode_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getRx0AntennaPath() { + return rx0_antenna_path; +} +void +SWGPlutoSdrMIMOSettings::setRx0AntennaPath(qint32 rx0_antenna_path) { + this->rx0_antenna_path = rx0_antenna_path; + this->m_rx0_antenna_path_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getRx1Gain() { + return rx1_gain; +} +void +SWGPlutoSdrMIMOSettings::setRx1Gain(qint32 rx1_gain) { + this->rx1_gain = rx1_gain; + this->m_rx1_gain_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getRx1GainMode() { + return rx1_gain_mode; +} +void +SWGPlutoSdrMIMOSettings::setRx1GainMode(qint32 rx1_gain_mode) { + this->rx1_gain_mode = rx1_gain_mode; + this->m_rx1_gain_mode_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getRx1AntennaPath() { + return rx1_antenna_path; +} +void +SWGPlutoSdrMIMOSettings::setRx1AntennaPath(qint32 rx1_antenna_path) { + this->rx1_antenna_path = rx1_antenna_path; + this->m_rx1_antenna_path_isSet = true; +} + +qint64 +SWGPlutoSdrMIMOSettings::getTxCenterFrequency() { + return tx_center_frequency; +} +void +SWGPlutoSdrMIMOSettings::setTxCenterFrequency(qint64 tx_center_frequency) { + this->tx_center_frequency = tx_center_frequency; + this->m_tx_center_frequency_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getFcPosTx() { + return fc_pos_tx; +} +void +SWGPlutoSdrMIMOSettings::setFcPosTx(qint32 fc_pos_tx) { + this->fc_pos_tx = fc_pos_tx; + this->m_fc_pos_tx_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getTxTransverterMode() { + return tx_transverter_mode; +} +void +SWGPlutoSdrMIMOSettings::setTxTransverterMode(qint32 tx_transverter_mode) { + this->tx_transverter_mode = tx_transverter_mode; + this->m_tx_transverter_mode_isSet = true; +} + +qint64 +SWGPlutoSdrMIMOSettings::getTxTransverterDeltaFrequency() { + return tx_transverter_delta_frequency; +} +void +SWGPlutoSdrMIMOSettings::setTxTransverterDeltaFrequency(qint64 tx_transverter_delta_frequency) { + this->tx_transverter_delta_frequency = tx_transverter_delta_frequency; + this->m_tx_transverter_delta_frequency_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getLpfBwTx() { + return lpf_bw_tx; +} +void +SWGPlutoSdrMIMOSettings::setLpfBwTx(qint32 lpf_bw_tx) { + this->lpf_bw_tx = lpf_bw_tx; + this->m_lpf_bw_tx_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getLpfTxFirEnable() { + return lpf_tx_fir_enable; +} +void +SWGPlutoSdrMIMOSettings::setLpfTxFirEnable(qint32 lpf_tx_fir_enable) { + this->lpf_tx_fir_enable = lpf_tx_fir_enable; + this->m_lpf_tx_fir_enable_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getLpfTxFirbw() { + return lpf_tx_firbw; +} +void +SWGPlutoSdrMIMOSettings::setLpfTxFirbw(qint32 lpf_tx_firbw) { + this->lpf_tx_firbw = lpf_tx_firbw; + this->m_lpf_tx_firbw_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getLpfTxFiRlog2Interp() { + return lpf_tx_fi_rlog2_interp; +} +void +SWGPlutoSdrMIMOSettings::setLpfTxFiRlog2Interp(qint32 lpf_tx_fi_rlog2_interp) { + this->lpf_tx_fi_rlog2_interp = lpf_tx_fi_rlog2_interp; + this->m_lpf_tx_fi_rlog2_interp_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getLpfTxFirGain() { + return lpf_tx_fir_gain; +} +void +SWGPlutoSdrMIMOSettings::setLpfTxFirGain(qint32 lpf_tx_fir_gain) { + this->lpf_tx_fir_gain = lpf_tx_fir_gain; + this->m_lpf_tx_fir_gain_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getLog2Interp() { + return log2_interp; +} +void +SWGPlutoSdrMIMOSettings::setLog2Interp(qint32 log2_interp) { + this->log2_interp = log2_interp; + this->m_log2_interp_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getTx0Att() { + return tx0_att; +} +void +SWGPlutoSdrMIMOSettings::setTx0Att(qint32 tx0_att) { + this->tx0_att = tx0_att; + this->m_tx0_att_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getTx0AntennaPath() { + return tx0_antenna_path; +} +void +SWGPlutoSdrMIMOSettings::setTx0AntennaPath(qint32 tx0_antenna_path) { + this->tx0_antenna_path = tx0_antenna_path; + this->m_tx0_antenna_path_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getTx1Att() { + return tx1_att; +} +void +SWGPlutoSdrMIMOSettings::setTx1Att(qint32 tx1_att) { + this->tx1_att = tx1_att; + this->m_tx1_att_isSet = true; +} + +qint32 +SWGPlutoSdrMIMOSettings::getTx1AntennaPath() { + return tx1_antenna_path; +} +void +SWGPlutoSdrMIMOSettings::setTx1AntennaPath(qint32 tx1_antenna_path) { + this->tx1_antenna_path = tx1_antenna_path; + this->m_tx1_antenna_path_isSet = true; +} + + +bool +SWGPlutoSdrMIMOSettings::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_dev_sample_rate_isSet){ + isObjectUpdated = true; break; + } + if(m_l_oppm_tenths_isSet){ + isObjectUpdated = true; break; + } + if(m_rx_center_frequency_isSet){ + isObjectUpdated = true; break; + } + if(m_dc_block_isSet){ + isObjectUpdated = true; break; + } + if(m_iq_correction_isSet){ + isObjectUpdated = true; break; + } + if(m_hw_bbdc_block_isSet){ + isObjectUpdated = true; break; + } + if(m_hw_rfdc_block_isSet){ + isObjectUpdated = true; break; + } + if(m_hw_iq_correction_isSet){ + isObjectUpdated = true; break; + } + if(m_fc_pos_rx_isSet){ + isObjectUpdated = true; break; + } + if(m_rx_transverter_mode_isSet){ + isObjectUpdated = true; break; + } + if(m_rx_transverter_delta_frequency_isSet){ + isObjectUpdated = true; break; + } + if(m_iq_order_isSet){ + isObjectUpdated = true; break; + } + if(m_lpf_bw_rx_isSet){ + isObjectUpdated = true; break; + } + if(m_lpf_rx_fir_enable_isSet){ + isObjectUpdated = true; break; + } + if(m_lpf_rx_firbw_isSet){ + isObjectUpdated = true; break; + } + if(m_lpf_rx_fi_rlog2_decim_isSet){ + isObjectUpdated = true; break; + } + if(m_lpf_rx_fir_gain_isSet){ + isObjectUpdated = true; break; + } + if(m_log2_decim_isSet){ + isObjectUpdated = true; break; + } + if(m_rx0_gain_isSet){ + isObjectUpdated = true; break; + } + if(m_rx0_gain_mode_isSet){ + isObjectUpdated = true; break; + } + if(m_rx0_antenna_path_isSet){ + isObjectUpdated = true; break; + } + if(m_rx1_gain_isSet){ + isObjectUpdated = true; break; + } + if(m_rx1_gain_mode_isSet){ + isObjectUpdated = true; break; + } + if(m_rx1_antenna_path_isSet){ + isObjectUpdated = true; break; + } + if(m_tx_center_frequency_isSet){ + isObjectUpdated = true; break; + } + if(m_fc_pos_tx_isSet){ + isObjectUpdated = true; break; + } + if(m_tx_transverter_mode_isSet){ + isObjectUpdated = true; break; + } + if(m_tx_transverter_delta_frequency_isSet){ + isObjectUpdated = true; break; + } + if(m_lpf_bw_tx_isSet){ + isObjectUpdated = true; break; + } + if(m_lpf_tx_fir_enable_isSet){ + isObjectUpdated = true; break; + } + if(m_lpf_tx_firbw_isSet){ + isObjectUpdated = true; break; + } + if(m_lpf_tx_fi_rlog2_interp_isSet){ + isObjectUpdated = true; break; + } + if(m_lpf_tx_fir_gain_isSet){ + isObjectUpdated = true; break; + } + if(m_log2_interp_isSet){ + isObjectUpdated = true; break; + } + if(m_tx0_att_isSet){ + isObjectUpdated = true; break; + } + if(m_tx0_antenna_path_isSet){ + isObjectUpdated = true; break; + } + if(m_tx1_att_isSet){ + isObjectUpdated = true; break; + } + if(m_tx1_antenna_path_isSet){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOSettings.h b/swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOSettings.h new file mode 100644 index 000000000..9b383300a --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGPlutoSdrMIMOSettings.h @@ -0,0 +1,280 @@ +/** + * 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 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: 6.0.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. + */ + +/* + * SWGPlutoSdrMIMOSettings.h + * + * PlutoSDR + */ + +#ifndef SWGPlutoSdrMIMOSettings_H_ +#define SWGPlutoSdrMIMOSettings_H_ + +#include + + + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGPlutoSdrMIMOSettings: public SWGObject { +public: + SWGPlutoSdrMIMOSettings(); + SWGPlutoSdrMIMOSettings(QString* json); + virtual ~SWGPlutoSdrMIMOSettings(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGPlutoSdrMIMOSettings* fromJson(QString &jsonString) override; + + qint32 getDevSampleRate(); + void setDevSampleRate(qint32 dev_sample_rate); + + qint32 getLOppmTenths(); + void setLOppmTenths(qint32 l_oppm_tenths); + + qint64 getRxCenterFrequency(); + void setRxCenterFrequency(qint64 rx_center_frequency); + + qint32 getDcBlock(); + void setDcBlock(qint32 dc_block); + + qint32 getIqCorrection(); + void setIqCorrection(qint32 iq_correction); + + qint32 getHwBbdcBlock(); + void setHwBbdcBlock(qint32 hw_bbdc_block); + + qint32 getHwRfdcBlock(); + void setHwRfdcBlock(qint32 hw_rfdc_block); + + qint32 getHwIqCorrection(); + void setHwIqCorrection(qint32 hw_iq_correction); + + qint32 getFcPosRx(); + void setFcPosRx(qint32 fc_pos_rx); + + qint32 getRxTransverterMode(); + void setRxTransverterMode(qint32 rx_transverter_mode); + + qint64 getRxTransverterDeltaFrequency(); + void setRxTransverterDeltaFrequency(qint64 rx_transverter_delta_frequency); + + qint32 getIqOrder(); + void setIqOrder(qint32 iq_order); + + qint32 getLpfBwRx(); + void setLpfBwRx(qint32 lpf_bw_rx); + + qint32 getLpfRxFirEnable(); + void setLpfRxFirEnable(qint32 lpf_rx_fir_enable); + + qint32 getLpfRxFirbw(); + void setLpfRxFirbw(qint32 lpf_rx_firbw); + + qint32 getLpfRxFiRlog2Decim(); + void setLpfRxFiRlog2Decim(qint32 lpf_rx_fi_rlog2_decim); + + qint32 getLpfRxFirGain(); + void setLpfRxFirGain(qint32 lpf_rx_fir_gain); + + qint32 getLog2Decim(); + void setLog2Decim(qint32 log2_decim); + + qint32 getRx0Gain(); + void setRx0Gain(qint32 rx0_gain); + + qint32 getRx0GainMode(); + void setRx0GainMode(qint32 rx0_gain_mode); + + qint32 getRx0AntennaPath(); + void setRx0AntennaPath(qint32 rx0_antenna_path); + + qint32 getRx1Gain(); + void setRx1Gain(qint32 rx1_gain); + + qint32 getRx1GainMode(); + void setRx1GainMode(qint32 rx1_gain_mode); + + qint32 getRx1AntennaPath(); + void setRx1AntennaPath(qint32 rx1_antenna_path); + + qint64 getTxCenterFrequency(); + void setTxCenterFrequency(qint64 tx_center_frequency); + + qint32 getFcPosTx(); + void setFcPosTx(qint32 fc_pos_tx); + + qint32 getTxTransverterMode(); + void setTxTransverterMode(qint32 tx_transverter_mode); + + qint64 getTxTransverterDeltaFrequency(); + void setTxTransverterDeltaFrequency(qint64 tx_transverter_delta_frequency); + + qint32 getLpfBwTx(); + void setLpfBwTx(qint32 lpf_bw_tx); + + qint32 getLpfTxFirEnable(); + void setLpfTxFirEnable(qint32 lpf_tx_fir_enable); + + qint32 getLpfTxFirbw(); + void setLpfTxFirbw(qint32 lpf_tx_firbw); + + qint32 getLpfTxFiRlog2Interp(); + void setLpfTxFiRlog2Interp(qint32 lpf_tx_fi_rlog2_interp); + + qint32 getLpfTxFirGain(); + void setLpfTxFirGain(qint32 lpf_tx_fir_gain); + + qint32 getLog2Interp(); + void setLog2Interp(qint32 log2_interp); + + qint32 getTx0Att(); + void setTx0Att(qint32 tx0_att); + + qint32 getTx0AntennaPath(); + void setTx0AntennaPath(qint32 tx0_antenna_path); + + qint32 getTx1Att(); + void setTx1Att(qint32 tx1_att); + + qint32 getTx1AntennaPath(); + void setTx1AntennaPath(qint32 tx1_antenna_path); + + + virtual bool isSet() override; + +private: + qint32 dev_sample_rate; + bool m_dev_sample_rate_isSet; + + qint32 l_oppm_tenths; + bool m_l_oppm_tenths_isSet; + + qint64 rx_center_frequency; + bool m_rx_center_frequency_isSet; + + qint32 dc_block; + bool m_dc_block_isSet; + + qint32 iq_correction; + bool m_iq_correction_isSet; + + qint32 hw_bbdc_block; + bool m_hw_bbdc_block_isSet; + + qint32 hw_rfdc_block; + bool m_hw_rfdc_block_isSet; + + qint32 hw_iq_correction; + bool m_hw_iq_correction_isSet; + + qint32 fc_pos_rx; + bool m_fc_pos_rx_isSet; + + qint32 rx_transverter_mode; + bool m_rx_transverter_mode_isSet; + + qint64 rx_transverter_delta_frequency; + bool m_rx_transverter_delta_frequency_isSet; + + qint32 iq_order; + bool m_iq_order_isSet; + + qint32 lpf_bw_rx; + bool m_lpf_bw_rx_isSet; + + qint32 lpf_rx_fir_enable; + bool m_lpf_rx_fir_enable_isSet; + + qint32 lpf_rx_firbw; + bool m_lpf_rx_firbw_isSet; + + qint32 lpf_rx_fi_rlog2_decim; + bool m_lpf_rx_fi_rlog2_decim_isSet; + + qint32 lpf_rx_fir_gain; + bool m_lpf_rx_fir_gain_isSet; + + qint32 log2_decim; + bool m_log2_decim_isSet; + + qint32 rx0_gain; + bool m_rx0_gain_isSet; + + qint32 rx0_gain_mode; + bool m_rx0_gain_mode_isSet; + + qint32 rx0_antenna_path; + bool m_rx0_antenna_path_isSet; + + qint32 rx1_gain; + bool m_rx1_gain_isSet; + + qint32 rx1_gain_mode; + bool m_rx1_gain_mode_isSet; + + qint32 rx1_antenna_path; + bool m_rx1_antenna_path_isSet; + + qint64 tx_center_frequency; + bool m_tx_center_frequency_isSet; + + qint32 fc_pos_tx; + bool m_fc_pos_tx_isSet; + + qint32 tx_transverter_mode; + bool m_tx_transverter_mode_isSet; + + qint64 tx_transverter_delta_frequency; + bool m_tx_transverter_delta_frequency_isSet; + + qint32 lpf_bw_tx; + bool m_lpf_bw_tx_isSet; + + qint32 lpf_tx_fir_enable; + bool m_lpf_tx_fir_enable_isSet; + + qint32 lpf_tx_firbw; + bool m_lpf_tx_firbw_isSet; + + qint32 lpf_tx_fi_rlog2_interp; + bool m_lpf_tx_fi_rlog2_interp_isSet; + + qint32 lpf_tx_fir_gain; + bool m_lpf_tx_fir_gain_isSet; + + qint32 log2_interp; + bool m_log2_interp_isSet; + + qint32 tx0_att; + bool m_tx0_att_isSet; + + qint32 tx0_antenna_path; + bool m_tx0_antenna_path_isSet; + + qint32 tx1_att; + bool m_tx1_att_isSet; + + qint32 tx1_antenna_path; + bool m_tx1_antenna_path_isSet; + +}; + +} + +#endif /* SWGPlutoSdrMIMOSettings_H_ */