From c27acf086ea472d4c8b05057e101fc8063454eb5 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 29 Sep 2018 05:49:14 +0200 Subject: [PATCH] BladeRF output (1) and some cosmetic changes --- devices/bladerf2/devicebladerf2shared.h | 2 + plugins/samplesink/CMakeLists.txt | 2 + .../bladerf1output/bladerf1output.cpp | 3 +- .../bladerf1output/bladerf1outputthread.h | 1 - .../samplesink/bladerf2output/CMakeLists.txt | 80 ++ .../bladerf2output/bladerf2output.cpp | 991 ++++++++++++++++++ .../bladerf2output/bladerf2output.h | 176 ++++ .../bladerf2output/bladerf2outputgui.ui | 464 ++++++++ .../bladerf2output/bladerf2outputplugin.cpp | 157 +++ .../bladerf2output/bladerf2outputplugin.h | 54 + .../bladerf2output/bladerf2outputsettings.cpp | 85 ++ .../bladerf2output/bladerf2outputsettings.h | 40 + .../bladerf2output/bladerf2outputthread.cpp | 223 ++++ .../bladerf2output/bladerf2outputthread.h | 81 ++ .../bladerf2input/bladerf2input.cpp | 17 +- .../bladerf2input/bladerf2inputthread.cpp | 2 + .../bladerf2input/bladerf2inputthread.h | 23 +- sdrbase/resources/webapi/doc/html2/index.html | 58 +- .../webapi/doc/swagger/include/BladeRF2.yaml | 35 + .../resources/webapi/doc/swagger/swagger.yaml | 4 + .../api/swagger/include/BladeRF2.yaml | 35 + swagger/sdrangel/api/swagger/swagger.yaml | 4 + swagger/sdrangel/code/html2/index.html | 58 +- .../qt5/client/SWGBladeRF2OutputReport.cpp | 204 ++++ .../code/qt5/client/SWGBladeRF2OutputReport.h | 86 ++ .../qt5/client/SWGBladeRF2OutputSettings.cpp | 232 ++++ .../qt5/client/SWGBladeRF2OutputSettings.h | 94 ++ .../code/qt5/client/SWGDeviceReport.cpp | 23 + .../code/qt5/client/SWGDeviceReport.h | 7 + .../code/qt5/client/SWGDeviceSettings.cpp | 23 + .../code/qt5/client/SWGDeviceSettings.h | 7 + .../code/qt5/client/SWGModelFactory.h | 8 + 32 files changed, 3253 insertions(+), 26 deletions(-) create mode 100644 plugins/samplesink/bladerf2output/CMakeLists.txt create mode 100644 plugins/samplesink/bladerf2output/bladerf2output.cpp create mode 100644 plugins/samplesink/bladerf2output/bladerf2output.h create mode 100644 plugins/samplesink/bladerf2output/bladerf2outputgui.ui create mode 100644 plugins/samplesink/bladerf2output/bladerf2outputplugin.cpp create mode 100644 plugins/samplesink/bladerf2output/bladerf2outputplugin.h create mode 100644 plugins/samplesink/bladerf2output/bladerf2outputsettings.cpp create mode 100644 plugins/samplesink/bladerf2output/bladerf2outputsettings.h create mode 100644 plugins/samplesink/bladerf2output/bladerf2outputthread.cpp create mode 100644 plugins/samplesink/bladerf2output/bladerf2outputthread.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputReport.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputReport.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputSettings.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputSettings.h diff --git a/devices/bladerf2/devicebladerf2shared.h b/devices/bladerf2/devicebladerf2shared.h index 946d0ea40..fbb2c9c55 100644 --- a/devices/bladerf2/devicebladerf2shared.h +++ b/devices/bladerf2/devicebladerf2shared.h @@ -23,6 +23,7 @@ class SampleSinkFifo; class SampleSourceFifo; class BladeRF2Input; +class BladeRF2Output; /** * Structure shared by a buddy with other buddies @@ -77,6 +78,7 @@ public: DeviceBladeRF2 *m_dev; int m_channel; //!< allocated channel (-1 if none) BladeRF2Input *m_source; + BladeRF2Output *m_sink; }; diff --git a/plugins/samplesink/CMakeLists.txt b/plugins/samplesink/CMakeLists.txt index eab0b27a9..2ea30aa73 100644 --- a/plugins/samplesink/CMakeLists.txt +++ b/plugins/samplesink/CMakeLists.txt @@ -5,6 +5,7 @@ find_package(LibUSB) find_package(LibBLADERF) if(LIBUSB_FOUND AND LIBBLADERF_FOUND) add_subdirectory(bladerf1output) + add_subdirectory(bladerf2output) endif(LIBUSB_FOUND AND LIBBLADERF_FOUND) find_package(LibHACKRF) @@ -29,6 +30,7 @@ endif(CM256CC_FOUND) if (BUILD_DEBIAN) add_subdirectory(bladerf1output) + add_subdirectory(bladerf2output) add_subdirectory(hackrfoutput) add_subdirectory(limesdroutput) add_subdirectory(plutosdroutput) diff --git a/plugins/samplesink/bladerf1output/bladerf1output.cpp b/plugins/samplesink/bladerf1output/bladerf1output.cpp index 0704443a1..75d15f593 100644 --- a/plugins/samplesink/bladerf1output/bladerf1output.cpp +++ b/plugins/samplesink/bladerf1output/bladerf1output.cpp @@ -23,12 +23,11 @@ #include "SWGDeviceSettings.h" #include "SWGDeviceState.h" -#include "util/simpleserializer.h" #include "dsp/dspcommands.h" #include "dsp/dspengine.h" #include "device/devicesinkapi.h" #include "device/devicesourceapi.h" -#include "../../../devices/bladerf1/devicebladerf1shared.h" +#include "bladerf1/devicebladerf1shared.h" #include "bladerf1outputthread.h" MESSAGE_CLASS_DEFINITION(Bladerf1Output::MsgConfigureBladerf1, Message) diff --git a/plugins/samplesink/bladerf1output/bladerf1outputthread.h b/plugins/samplesink/bladerf1output/bladerf1outputthread.h index 42e9ee14d..c9b17d228 100644 --- a/plugins/samplesink/bladerf1output/bladerf1outputthread.h +++ b/plugins/samplesink/bladerf1output/bladerf1outputthread.h @@ -36,7 +36,6 @@ public: void startWork(); void stopWork(); void setLog2Interpolation(unsigned int log2_interp); - void setFcPos(int fcPos); bool isRunning() const { return m_running; } private: diff --git a/plugins/samplesink/bladerf2output/CMakeLists.txt b/plugins/samplesink/bladerf2output/CMakeLists.txt new file mode 100644 index 000000000..907d1d0da --- /dev/null +++ b/plugins/samplesink/bladerf2output/CMakeLists.txt @@ -0,0 +1,80 @@ +project(bladerf2output) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +set(bladerf2output_SOURCES +# bladerf2outputgui.cpp + bladerf2output.cpp +# bladerf2outputplugin.cpp + bladerf2outputsettings.cpp + bladerf2outputthread.cpp +) + +set(bladerf2output_HEADERS +# bladerf2outputgui.h + bladerf2output.h +# bladerf1soutputplugin.h + bladerf2outputsettings.h + bladerf2outputthread.h +) + +set(bladerf2output_FORMS + bladerf2outputgui.ui +) + +if (BUILD_DEBIAN) +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${CMAKE_SOURCE_DIR}/devices + ${LIBBLADERFLIBSRC}/include + ${LIBBLADERFLIBSRC}/src +) +else (BUILD_DEBIAN) +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${CMAKE_SOURCE_DIR}/devices + ${LIBBLADERF_INCLUDE_DIR} +) +endif (BUILD_DEBIAN) + +#include(${QT_USE_FILE}) +add_definitions(${QT_DEFINITIONS}) +add_definitions(-DQT_PLUGIN) +add_definitions(-DQT_SHARED) + +#qt4_wrap_cpp(bladerf2output_HEADERS_MOC ${bladerf2output_HEADERS}) +qt5_wrap_ui(bladerf2output_FORMS_HEADERS ${bladerf2output_FORMS}) + +add_library(outputbladerf2 SHARED + ${bladerf2output_SOURCES} + ${bladerf2output_HEADERS_MOC} + ${bladerf2output_FORMS_HEADERS} +) + +if (BUILD_DEBIAN) +target_link_libraries(outputbladerf2 + ${QT_LIBRARIES} + bladerf + sdrbase + sdrgui + swagger + bladerf2device +) +else (BUILD_DEBIAN) +target_link_libraries(outputbladerf2 + ${QT_LIBRARIES} + ${LIBBLADERF_LIBRARIES} + sdrbase + sdrgui + swagger + bladerf2device +) +endif (BUILD_DEBIAN) + +target_link_libraries(outputbladerf2 Qt5::Core Qt5::Widgets) + +install(TARGETS outputbladerf2 DESTINATION lib/plugins/samplesink) diff --git a/plugins/samplesink/bladerf2output/bladerf2output.cpp b/plugins/samplesink/bladerf2output/bladerf2output.cpp new file mode 100644 index 000000000..83a58081f --- /dev/null +++ b/plugins/samplesink/bladerf2output/bladerf2output.cpp @@ -0,0 +1,991 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 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 // +// // +// 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 "SWGDeviceState.h" +#include "SWGDeviceSettings.h" +#include "SWGBladeRF2InputSettings.h" +#include "SWGDeviceReport.h" +#include "SWGBladeRF2OutputReport.h" + +#include "dsp/dspcommands.h" +#include "dsp/dspengine.h" +#include "device/devicesinkapi.h" +#include "device/devicesourceapi.h" +#include "bladerf2/devicebladerf2shared.h" +#include "bladerf2/devicebladerf2.h" + +#include "bladerf2outputthread.h" +#include "bladerf2output.h" + +MESSAGE_CLASS_DEFINITION(BladeRF2Output::MsgConfigureBladeRF2, Message) +MESSAGE_CLASS_DEFINITION(BladeRF2Output::MsgStartStop, Message) +MESSAGE_CLASS_DEFINITION(BladeRF2Output::MsgReportGainRange, Message) + +BladeRF2Output::BladeRF2Output(DeviceSinkAPI *deviceAPI) : + m_deviceAPI(deviceAPI), + m_settings(), + m_dev(0), + m_thread(0), + m_deviceDescription("BladeRF2Output"), + m_running(false) +{ + openDevice(); + + if (m_deviceShared.m_dev) + { + const bladerf_gain_modes *modes = 0; + int nbModes = m_deviceShared.m_dev->getGainModesRx(&modes); + + if (modes) + { + for (int i = 0; i < nbModes; i++) { + m_gainModes.push_back(GainMode{QString(modes[i].name), modes[i].mode}); + } + } + } +} + +BladeRF2Output::~BladeRF2Output() +{ + if (m_running) { + stop(); + } + + closeDevice(); +} + +void BladeRF2Output::destroy() +{ + delete this; +} + +bool BladeRF2Output::openDevice() +{ + m_sampleSourceFifo.resize(m_settings.m_devSampleRate/(1<<(m_settings.m_log2Interp <= 4 ? m_settings.m_log2Interp : 4))); + + // look for Tx buddies and get reference to the device object + if (m_deviceAPI->getSinkBuddies().size() > 0) // look sink sibling first + { + qDebug("BladeRF2Output::openDevice: look in Tx buddies"); + + DeviceSinkAPI *sinkBuddy = m_deviceAPI->getSinkBuddies()[0]; + DeviceBladeRF2Shared *deviceBladeRF2Shared = (DeviceBladeRF2Shared*) sinkBuddy->getBuddySharedPtr(); + + if (deviceBladeRF2Shared == 0) + { + qCritical("BladeRF2Output::openDevice: the sink buddy shared pointer is null"); + return false; + } + + DeviceBladeRF2 *device = deviceBladeRF2Shared->m_dev; + + if (device == 0) + { + qCritical("BladeRF2Output::openDevice: cannot get device pointer from Tx buddy"); + return false; + } + + m_deviceShared.m_dev = device; + } + // look for Rx buddies and get reference to the device object + else if (m_deviceAPI->getSourceBuddies().size() > 0) // then source + { + qDebug("BladeRF2Output::openDevice: look in Rx buddies"); + + DeviceSourceAPI *sourceBuddy = m_deviceAPI->getSourceBuddies()[0]; + DeviceBladeRF2Shared *deviceBladeRF2Shared = (DeviceBladeRF2Shared*) sourceBuddy->getBuddySharedPtr(); + + if (deviceBladeRF2Shared == 0) + { + qCritical("BladeRF2Output::openDevice: the source buddy shared pointer is null"); + return false; + } + + DeviceBladeRF2 *device = deviceBladeRF2Shared->m_dev; + + if (device == 0) + { + qCritical("BladeRF2Output::openDevice: cannot get device pointer from Rx buddy"); + return false; + } + + m_deviceShared.m_dev = device; + } + // There are no buddies then create the first BladeRF2 device + else + { + qDebug("BladeRF2Output::openDevice: open device here"); + + m_deviceShared.m_dev = new DeviceBladeRF2(); + char serial[256]; + strcpy(serial, qPrintable(m_deviceAPI->getSampleSinkSerial())); + + if (!m_deviceShared.m_dev->open(serial)) + { + qCritical("BladeRF2Output::openDevice: cannot open BladeRF2 device"); + return false; + } + } + + m_deviceShared.m_channel = m_deviceAPI->getItemIndex(); // publicly allocate channel + m_deviceShared.m_sink = this; + m_deviceAPI->setBuddySharedPtr(&m_deviceShared); // propagate common parameters to API + return true; +} + +void BladeRF2Output::closeDevice() +{ + if (m_deviceShared.m_dev == 0) { // was never open + return; + } + + if (m_running) { + stop(); + } + + if (m_thread) { // stills own the thread => transfer to a buddy + moveThreadToBuddy(); + } + + m_deviceShared.m_channel = -1; // publicly release channel + m_deviceShared.m_sink = 0; + + // No buddies so effectively close the device + + if ((m_deviceAPI->getSinkBuddies().size() == 0) && (m_deviceAPI->getSourceBuddies().size() == 0)) + { + m_deviceShared.m_dev->close(); + delete m_deviceShared.m_dev; + m_deviceShared.m_dev = 0; + } +} + +void BladeRF2Output::init() +{ + applySettings(m_settings, true); +} + +BladeRF2OutputThread *BladeRF2Output::findThread() +{ + if (m_thread == 0) // this does not own the thread + { + BladeRF2OutputThread *BladeRF2OutputThread = 0; + + // find a buddy that has allocated the thread + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator it = sinkBuddies.begin(); + + for (; it != sinkBuddies.end(); ++it) + { + BladeRF2Output *buddySink = ((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_sink; + + if (buddySink) + { + BladeRF2OutputThread = buddySink->getThread(); + + if (BladeRF2OutputThread) { + break; + } + } + } + + return BladeRF2OutputThread; + } + else + { + return m_thread; // own thread + } +} + +void BladeRF2Output::moveThreadToBuddy() +{ + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator it = sinkBuddies.begin(); + + for (; it != sinkBuddies.end(); ++it) + { + BladeRF2Output *buddySink = ((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_sink; + + if (buddySink) + { + buddySink->setThread(m_thread); + m_thread = 0; // zero for others + } + } +} + +bool BladeRF2Output::start() +{ + // There is a single thread per physical device (Tx side). This thread is unique and referenced by a unique + // buddy in the group of sink buddies associated with this physical device. + // + // This start method is responsible for managing the thread and channel enabling when the streaming of a Tx channel is started + // + // It checks the following conditions + // - the thread is allocated or not (by itself or one of its buddies). If it is it grabs the thread pointer. + // - the requested channel is the first (0) or the following (just 1 in BladeRF 2 case) + // + // The BladeRF support library lets you work in two possible modes: + // - Single Output (SO) with only one channel streaming. This HAS to be channel 0. + // - Multiple Output (MO) with two channels streaming using interleaved samples. It MUST be in this configuration if channel 1 + // is used. When we will run with only channel 1 streaming from the client perspective the channel 0 will actually be enabled + // and streaming but zero samples will be sent to it. + // + // It manages the transition form SO where only one channel (the first or channel 0) should be running to the + // Multiple Output (MO) if the requested channel is 1. More generally it checks if the requested channel is within the current + // channel range allocated in the thread or past it. To perform the transition it stops the thread, deletes it and creates a new one. + // It marks the thread as needing start. + // + // If the requested channel is within the thread channel range (this thread being already allocated) it simply removes its FIFO reference + // so that the samples are not taken from the FIFO anymore and leaves the thread unchanged (no stop, no delete/new) + // + // If there is no thread allocated it creates a new one with a number of channels that fits the requested channel. That is + // 1 if channel 0 is requested (SO mode) and 2 if channel 1 is requested (MO mode). It marks the thread as needing start. + // + // Eventually it registers the FIFO in the thread. If the thread has to be started it enables the channels up to the number of channels + // allocated in the thread and starts the thread. + + if (!m_deviceShared.m_dev) + { + qDebug("BladeRF2Output::start: no device object"); + return false; + } + + int requestedChannel = m_deviceAPI->getItemIndex(); + BladeRF2OutputThread *bladeRF2OutputThread = findThread(); + bool needsStart = false; + + if (bladeRF2OutputThread) // if thread is already allocated + { + qDebug("BladeRF2Output::start: thread is already allocated"); + + int nbOriginalChannels = bladeRF2OutputThread->getNbChannels(); + + if (requestedChannel+1 > nbOriginalChannels) // expansion by deleting and re-creating the thread + { + qDebug("BladeRF2Output::start: expand channels. Re-allocate thread and take ownership"); + + SampleSourceFifo **fifos = new SampleSourceFifo*[nbOriginalChannels]; + unsigned int *log2Interps = new unsigned int[nbOriginalChannels]; + + for (int i = 0; i < nbOriginalChannels; i++) // save original FIFO references and data + { + fifos[i] = bladeRF2OutputThread->getFifo(i); + log2Interps[i] = bladeRF2OutputThread->getLog2Interpolation(i); + } + + bladeRF2OutputThread->stopWork(); + delete bladeRF2OutputThread; + bladeRF2OutputThread = new BladeRF2OutputThread(m_deviceShared.m_dev->getDev(), requestedChannel+1); + m_thread = bladeRF2OutputThread; // take ownership + + for (int i = 0; i < nbOriginalChannels; i++) // restore original FIFO references + { + bladeRF2OutputThread->setFifo(i, fifos[i]); + bladeRF2OutputThread->setLog2Interpolation(i, log2Interps[i]); + } + + // remove old thread address from buddies (reset in all buddies) + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator it = sinkBuddies.begin(); + + for (; it != sinkBuddies.end(); ++it) { + ((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_sink->setThread(0); + } + + needsStart = true; + } + else + { + qDebug("BladeRF2Output::start: keep buddy thread"); + } + } + else // first allocation + { + qDebug("BladeRF2Output::start: allocate thread and take ownership"); + bladeRF2OutputThread = new BladeRF2OutputThread(m_deviceShared.m_dev->getDev(), requestedChannel+1); + m_thread = bladeRF2OutputThread; // take ownership + needsStart = true; + } + + bladeRF2OutputThread->setFifo(requestedChannel, &m_sampleSourceFifo); + bladeRF2OutputThread->setLog2Interpolation(requestedChannel, m_settings.m_log2Interp); + + if (needsStart) + { + qDebug("BladeRF2Output::start: enabling channel(s) and (re)sart buddy thread"); + + int nbChannels = bladeRF2OutputThread->getNbChannels(); + + for (int i = 0; i < nbChannels; i++) + { + if (!m_deviceShared.m_dev->openTx(i)) { + qCritical("BladeRF2Output::start: channel %u cannot be enabled", i); + } + } + + bladeRF2OutputThread->startWork(); + } + + applySettings(m_settings, true); + + qDebug("BladeRF2Output::start: started"); + m_running = true; + + return true; +} + +void BladeRF2Output::stop() +{ + // This stop method is responsible for managing the thread and channel disabling when the streaming of + // a Tx channel is stopped + // + // If the thread is currently managing only one channel (SO mode). The thread can be just stopped and deleted. + // Then the channel is closed (disabled). + // + // If the thread is currently managing many channels (MO mode) and we are removing the last channel. The transition + // from MO to SO or reduction of MO size is handled by stopping the thread, deleting it and creating a new one + // with one channel less if (and only if) there is still a channel active. + // + // If the thread is currently managing many channels (MO mode) but the channel being stopped is not the last + // channel then the FIFO reference is simply removed from the thread so that this FIFO will not be used anymore. + // In this case the channel is not closed (disabled) so that other channels can continue with the + // same configuration. The device continues streaming on this channel but the samples are set to all zeros. + + if (!m_running) { + return; + } + + int requestedChannel = m_deviceAPI->getItemIndex(); + BladeRF2OutputThread *bladeRF2OutputThread = findThread(); + + if (bladeRF2OutputThread == 0) { // no thread allocated + return; + } + + int nbOriginalChannels = bladeRF2OutputThread->getNbChannels(); + + if (nbOriginalChannels == 1) // SO mode => just stop and delete the thread + { + qDebug("BladeRF2Output::stop: SO mode. Just stop and delete the thread"); + bladeRF2OutputThread->stopWork(); + delete bladeRF2OutputThread; + m_thread = 0; + + // remove old thread address from buddies (reset in all buddies) + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator it = sinkBuddies.begin(); + + for (; it != sinkBuddies.end(); ++it) { + ((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_sink->setThread(0); + } + + m_deviceShared.m_dev->closeTx(0); // close the unique channel + } + else if (requestedChannel == nbOriginalChannels - 1) // remove last MO channel => reduce by deleting and re-creating the thread + { + qDebug("BladeRF2Output::stop: MO mode. Reduce by deleting and re-creating the thread"); + bladeRF2OutputThread->stopWork(); + SampleSourceFifo **fifos = new SampleSourceFifo*[nbOriginalChannels-1]; + unsigned int *log2Interps = new unsigned int[nbOriginalChannels-1]; + bool stillActiveFIFO = false; + + for (int i = 0; i < nbOriginalChannels-1; i++) // save original FIFO references + { + fifos[i] = bladeRF2OutputThread->getFifo(i); + stillActiveFIFO = stillActiveFIFO || (bladeRF2OutputThread->getFifo(i) != 0); + log2Interps[i] = bladeRF2OutputThread->getLog2Interpolation(i); + } + + delete bladeRF2OutputThread; + m_thread = 0; + + if (stillActiveFIFO) + { + bladeRF2OutputThread = new BladeRF2OutputThread(m_deviceShared.m_dev->getDev(), nbOriginalChannels-1); + m_thread = bladeRF2OutputThread; // take ownership + + for (int i = 0; i < nbOriginalChannels-1; i++) // restore original FIFO references + { + bladeRF2OutputThread->setFifo(i, fifos[i]); + bladeRF2OutputThread->setLog2Interpolation(i, log2Interps[i]); + } + } + else + { + qDebug("BladeRF2Output::stop: do not re-create thread as there are no more FIFOs active"); + } + + // remove old thread address from buddies (reset in all buddies) + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator it = sinkBuddies.begin(); + + for (; it != sinkBuddies.end(); ++it) { + ((DeviceBladeRF2Shared*) (*it)->getBuddySharedPtr())->m_sink->setThread(0); + } + + m_deviceShared.m_dev->closeTx(requestedChannel); // close the last channel + + if (stillActiveFIFO) { + bladeRF2OutputThread->startWork(); + } + } + else // remove channel from existing thread + { + qDebug("BladeRF2Output::stop: MO mode. Not changing MO configuration. Just remove FIFO reference"); + bladeRF2OutputThread->setFifo(requestedChannel, 0); // remove FIFO + } + + m_running = false; +} + +QByteArray BladeRF2Output::serialize() const +{ + return m_settings.serialize(); +} + +bool BladeRF2Output::deserialize(const QByteArray& data) +{ + bool success = true; + + if (!m_settings.deserialize(data)) + { + m_settings.resetToDefaults(); + success = false; + } + + MsgConfigureBladeRF2* message = MsgConfigureBladeRF2::create(m_settings, true); + m_inputMessageQueue.push(message); + + if (m_guiMessageQueue) + { + MsgConfigureBladeRF2* messageToGUI = MsgConfigureBladeRF2::create(m_settings, true); + m_guiMessageQueue->push(messageToGUI); + } + + return success; +} + +const QString& BladeRF2Output::getDeviceDescription() const +{ + return m_deviceDescription; +} + +int BladeRF2Output::getSampleRate() const +{ + int rate = m_settings.m_devSampleRate; + return (rate / (1<push(messageToGUI); + } +} + +void BladeRF2Output::getFrequencyRange(uint64_t& min, uint64_t& max, int& step) +{ + if (m_deviceShared.m_dev) { + m_deviceShared.m_dev->getFrequencyRangeTx(min, max, step); + } +} + +void BladeRF2Output::getSampleRateRange(int& min, int& max, int& step) +{ + if (m_deviceShared.m_dev) { + m_deviceShared.m_dev->getSampleRateRangeTx(min, max, step); + } +} + +void BladeRF2Output::getBandwidthRange(int& min, int& max, int& step) +{ + if (m_deviceShared.m_dev) { + m_deviceShared.m_dev->getBandwidthRangeTx(min, max, step); + } +} + +void BladeRF2Output::getGlobalGainRange(int& min, int& max, int& step) +{ + if (m_deviceShared.m_dev) { + m_deviceShared.m_dev->getGlobalGainRangeTx(min, max, step); + } +} + +bool BladeRF2Output::handleMessage(const Message& message) +{ + if (MsgConfigureBladeRF2::match(message)) + { + MsgConfigureBladeRF2& conf = (MsgConfigureBladeRF2&) message; + qDebug() << "BladeRF2Output::handleMessage: MsgConfigureBladeRF2"; + + if (!applySettings(conf.getSettings(), conf.getForce())) + { + qDebug("BladeRF2Output::handleMessage: MsgConfigureBladeRF2 config error"); + } + + return true; + } + else if (DeviceBladeRF2Shared::MsgReportBuddyChange::match(message)) + { + DeviceBladeRF2Shared::MsgReportBuddyChange& report = (DeviceBladeRF2Shared::MsgReportBuddyChange&) message; + struct bladerf *dev = m_deviceShared.m_dev->getDev(); + BladeRF2OutputSettings settings = m_settings; + int status; + unsigned int tmp_uint; + bool tmp_bool; + + // evaluate changes that may have been introduced by changes in a buddy + + if (dev) // The BladeRF device must have been open to do so + { + int requestedChannel = m_deviceAPI->getItemIndex(); + + if (report.getRxElseTx()) // Rx buddy change: check for sample rate change only + { + status = bladerf_get_sample_rate(dev, BLADERF_CHANNEL_TX(requestedChannel), &tmp_uint); + + if (status < 0) { + qCritical("BladeRF2Output::handleMessage: MsgReportBuddyChange: bladerf_get_sample_rate error: %s", bladerf_strerror(status)); + } else { + settings.m_devSampleRate = tmp_uint+1; + } + } + else // Tx buddy change: check for: frequency, gain mode and value, bias tee, sample rate, bandwidth + { + settings.m_devSampleRate = report.getDevSampleRate(); + settings.m_centerFrequency = report.getCenterFrequency(); + + status = bladerf_get_bandwidth(dev, BLADERF_CHANNEL_TX(requestedChannel), &tmp_uint); + + if (status < 0) { + qCritical("BladeRF2Output::handleMessage: MsgReportBuddyChange: bladerf_get_bandwidth error: %s", bladerf_strerror(status)); + } else { + settings.m_bandwidth = tmp_uint; + } + + status = bladerf_get_bias_tee(dev, BLADERF_CHANNEL_TX(requestedChannel), &tmp_bool); + + if (status < 0) { + qCritical("BladeRF2Output::handleMessage: MsgReportBuddyChange: bladerf_get_bias_tee error: %s", bladerf_strerror(status)); + } else { + settings.m_biasTee = tmp_bool; + } + } + + // change DSP settings if buddy change introduced a change in center frequency or base rate + if ((settings.m_centerFrequency != m_settings.m_centerFrequency) || (settings.m_devSampleRate != m_settings.m_devSampleRate)) + { + int sampleRate = settings.m_devSampleRate/(1<getDeviceEngineInputMessageQueue()->push(notif); + } + + m_settings = settings; // acknowledge the new settings + + // propagate settings to GUI if any + if (getMessageQueueToGUI()) + { + MsgConfigureBladeRF2 *reportToGUI = MsgConfigureBladeRF2::create(m_settings, false); + getMessageQueueToGUI()->push(reportToGUI); + } + } + + return true; + } + else if (MsgStartStop::match(message)) + { + MsgStartStop& cmd = (MsgStartStop&) message; + qDebug() << "BladeRF2Input::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop"); + + if (cmd.getStartStop()) + { + if (m_deviceAPI->initGeneration()) + { + m_deviceAPI->startGeneration(); + } + } + else + { + m_deviceAPI->stopGeneration(); + } + + return true; + } + else + { + return false; + } +} + +bool BladeRF2Output::applySettings(const BladeRF2OutputSettings& settings, bool force) +{ + bool forwardChangeOwnDSP = false; + bool forwardChangeRxBuddies = false; + bool forwardChangeTxBuddies = false; + + struct bladerf *dev = m_deviceShared.m_dev->getDev(); + int requestedChannel = m_deviceAPI->getItemIndex(); + + if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force) + { + forwardChangeOwnDSP = true; + forwardChangeRxBuddies = true; + forwardChangeTxBuddies = true; + + if (dev != 0) + { + unsigned int actualSamplerate; + int status = bladerf_set_sample_rate(dev, BLADERF_CHANNEL_TX(requestedChannel), settings.m_devSampleRate, &actualSamplerate); + + if (status < 0) + { + qCritical("BladeRF2Output::applySettings: could not set sample rate: %d: %s", + settings.m_devSampleRate, bladerf_strerror(status)); + } + else + { + qDebug() << "BladeRF2Output::applySettings: bladerf_set_sample_rate(BLADERF_MODULE_RX) actual sample rate is " << actualSamplerate; + } + } + } + + if ((m_settings.m_bandwidth != settings.m_bandwidth) || force) + { + forwardChangeTxBuddies = true; + + if (dev != 0) + { + unsigned int actualBandwidth; + int status = bladerf_set_bandwidth(dev, BLADERF_CHANNEL_TX(requestedChannel), settings.m_bandwidth, &actualBandwidth); + + if(status < 0) + { + qCritical("BladeRF2Output::applySettings: could not set bandwidth: %d: %s", + settings.m_bandwidth, bladerf_strerror(status)); + } + else + { + qDebug() << "BladeRF2Output::applySettings: bladerf_set_bandwidth(BLADERF_MODULE_RX) actual bandwidth is " << actualBandwidth; + } + } + } + + if ((m_settings.m_log2Interp != settings.m_log2Interp) || force) + { + forwardChangeOwnDSP = true; + BladeRF2OutputThread *outputThread = findThread(); + + if (outputThread != 0) + { + outputThread->setLog2Interpolation(requestedChannel, settings.m_log2Interp); + qDebug() << "BladeRF2Output::applySettings: set interpolation to " << (1<push(msg); + } + } + } + } + + if ((m_settings.m_biasTee != settings.m_biasTee) || force) + { + forwardChangeTxBuddies = true; + m_deviceShared.m_dev->setBiasTeeTx(settings.m_biasTee); + } + + if ((m_settings.m_gainMode != settings.m_gainMode) || force) + { + forwardChangeTxBuddies = true; + + if (dev) + { + int status = bladerf_set_gain_mode(dev, BLADERF_CHANNEL_TX(requestedChannel), (bladerf_gain_mode) settings.m_gainMode); + + if (status < 0) { + qWarning("BladeRF2Output::applySettings: bladerf_set_gain_mode(%d) failed: %s", + settings.m_gainMode, bladerf_strerror(status)); + } else { + qDebug("BladeRF2Output::applySettings: bladerf_set_gain_mode(%d)", settings.m_gainMode); + } + } + } + + if ((m_settings.m_globalGain != settings.m_globalGain) + || ((m_settings.m_gainMode != settings.m_gainMode) && (settings.m_gainMode == BLADERF_GAIN_MANUAL)) || force) + { + forwardChangeTxBuddies = true; + + if (dev) + { +// qDebug("BladeRF2Output::applySettings: channel: %d gain: %d", requestedChannel, settings.m_globalGain); + int status = bladerf_set_gain(dev, BLADERF_CHANNEL_TX(requestedChannel), settings.m_globalGain); + + if (status < 0) { + qWarning("BladeRF2Output::applySettings: bladerf_set_gain(%d) failed: %s", + settings.m_globalGain, bladerf_strerror(status)); + } else { + qDebug("BladeRF2Output::applySettings: bladerf_set_gain(%d)", settings.m_globalGain); + } + } + } + + if (forwardChangeOwnDSP) + { + int sampleRate = settings.m_devSampleRate/(1<getDeviceEngineInputMessageQueue()->push(notif); + } + + if (forwardChangeRxBuddies) + { + // send to source buddies + const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); + std::vector::const_iterator itSource = sourceBuddies.begin(); + + for (; itSource != sourceBuddies.end(); ++itSource) + { + DeviceBladeRF2Shared::MsgReportBuddyChange *report = DeviceBladeRF2Shared::MsgReportBuddyChange::create( + settings.m_centerFrequency, + 0, + settings.m_devSampleRate, + false); + (*itSource)->getSampleSourceInputMessageQueue()->push(report); + } + } + + if (forwardChangeTxBuddies) + { + // send to sink buddies + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator itSink = sinkBuddies.begin(); + + for (; itSink != sinkBuddies.end(); ++itSink) + { + DeviceBladeRF2Shared::MsgReportBuddyChange *report = DeviceBladeRF2Shared::MsgReportBuddyChange::create( + settings.m_centerFrequency, + 0, + settings.m_devSampleRate, + false); + (*itSink)->getSampleSinkInputMessageQueue()->push(report); + } + } + + m_settings = settings; + + qDebug() << "BladeRF2Output::applySettings: " + << " m_centerFrequency: " << m_settings.m_centerFrequency << " Hz" + << " m_bandwidth: " << m_settings.m_bandwidth + << " m_log2Interp: " << m_settings.m_log2Interp + << " m_devSampleRate: " << m_settings.m_devSampleRate + << " m_globalGain: " << m_settings.m_globalGain + << " m_gainMode: " << m_settings.m_gainMode + << " m_biasTee: " << m_settings.m_biasTee; + + return true; +} + +int BladeRF2Output::webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage __attribute__((unused))) +{ + response.setBladeRf2OutputSettings(new SWGSDRangel::SWGBladeRF2OutputSettings()); + response.getBladeRf2OutputSettings()->init(); + webapiFormatDeviceSettings(response, m_settings); + return 200; +} + +int BladeRF2Output::webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage __attribute__((unused))) +{ + BladeRF2OutputSettings settings = m_settings; + + if (deviceSettingsKeys.contains("centerFrequency")) { + settings.m_centerFrequency = response.getBladeRf2OutputSettings()->getCenterFrequency(); + } + if (deviceSettingsKeys.contains("devSampleRate")) { + settings.m_devSampleRate = response.getBladeRf2OutputSettings()->getDevSampleRate(); + } + if (deviceSettingsKeys.contains("bandwidth")) { + settings.m_bandwidth = response.getBladeRf2OutputSettings()->getBandwidth(); + } + if (deviceSettingsKeys.contains("log2Interp")) { + settings.m_log2Interp = response.getBladeRf2OutputSettings()->getLog2Interp(); + } + if (deviceSettingsKeys.contains("biasTee")) { + settings.m_biasTee = response.getBladeRf2OutputSettings()->getBiasTee() != 0; + } + if (deviceSettingsKeys.contains("gainMode")) { + settings.m_gainMode = response.getBladeRf2OutputSettings()->getGainMode(); + } + if (deviceSettingsKeys.contains("globalGain")) { + settings.m_globalGain = response.getBladeRf2OutputSettings()->getGlobalGain(); + } + + MsgConfigureBladeRF2 *msg = MsgConfigureBladeRF2::create(settings, force); + m_inputMessageQueue.push(msg); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigureBladeRF2 *msgToGUI = MsgConfigureBladeRF2::create(settings, force); + m_guiMessageQueue->push(msgToGUI); + } + + webapiFormatDeviceSettings(response, settings); + return 200; +} + +int BladeRF2Output::webapiReportGet(SWGSDRangel::SWGDeviceReport& response, QString& errorMessage __attribute__((unused))) +{ + response.setBladeRf2OutputReport(new SWGSDRangel::SWGBladeRF2OutputReport()); + response.getBladeRf2OutputReport()->init(); + webapiFormatDeviceReport(response); + return 200; +} + +void BladeRF2Output::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const BladeRF2OutputSettings& settings) +{ + response.getBladeRf2OutputSettings()->setCenterFrequency(settings.m_centerFrequency); + response.getBladeRf2OutputSettings()->setDevSampleRate(settings.m_devSampleRate); + response.getBladeRf2OutputSettings()->setBandwidth(settings.m_bandwidth); + response.getBladeRf2OutputSettings()->setLog2Interp(settings.m_log2Interp); + response.getBladeRf2OutputSettings()->setBiasTee(settings.m_biasTee ? 1 : 0); + response.getBladeRf2OutputSettings()->setGainMode(settings.m_gainMode); + response.getBladeRf2OutputSettings()->setGlobalGain(settings.m_globalGain); +} + +void BladeRF2Output::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response) +{ + DeviceBladeRF2 *device = m_deviceShared.m_dev; + + if (device) + { + int min, max, step; + uint64_t f_min, f_max; + + device->getBandwidthRangeTx(min, max, step); + + response.getBladeRf2OutputReport()->setBandwidthRange(new SWGSDRangel::SWGRange); + response.getBladeRf2OutputReport()->getBandwidthRange()->setMin(min); + response.getBladeRf2OutputReport()->getBandwidthRange()->setMax(max); + response.getBladeRf2OutputReport()->getBandwidthRange()->setStep(step); + + device->getFrequencyRangeTx(f_min, f_max, step); + + response.getBladeRf2OutputReport()->setFrequencyRange(new SWGSDRangel::SWGFrequencyRange); + response.getBladeRf2OutputReport()->getFrequencyRange()->setMin(f_min); + response.getBladeRf2OutputReport()->getFrequencyRange()->setMax(f_max); + response.getBladeRf2OutputReport()->getFrequencyRange()->setStep(step); + + device->getGlobalGainRangeTx(min, max, step); + + response.getBladeRf2OutputReport()->setGlobalGainRange(new SWGSDRangel::SWGRange); + response.getBladeRf2OutputReport()->getGlobalGainRange()->setMin(min); + response.getBladeRf2OutputReport()->getGlobalGainRange()->setMax(max); + response.getBladeRf2OutputReport()->getGlobalGainRange()->setStep(step); + + device->getSampleRateRangeTx(min, max, step); + + response.getBladeRf2OutputReport()->setSampleRateRange(new SWGSDRangel::SWGRange); + response.getBladeRf2OutputReport()->getSampleRateRange()->setMin(min); + response.getBladeRf2OutputReport()->getSampleRateRange()->setMax(max); + response.getBladeRf2OutputReport()->getSampleRateRange()->setStep(step); + + response.getBladeRf2OutputReport()->setGainModes(new QList); + + const std::vector& modes = getGainModes(); + std::vector::const_iterator it = modes.begin(); + + for (; it != modes.end(); ++it) + { + response.getBladeRf2OutputReport()->getGainModes()->append(new SWGSDRangel::SWGNamedEnum); + response.getBladeRf2OutputReport()->getGainModes()->back()->setName(new QString(it->m_name)); + response.getBladeRf2OutputReport()->getGainModes()->back()->setValue(it->m_value); + } + } +} + +int BladeRF2Output::webapiRunGet( + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage __attribute__((unused))) +{ + m_deviceAPI->getDeviceEngineStateStr(*response.getState()); + return 200; +} + +int BladeRF2Output::webapiRun( + bool run, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage __attribute__((unused))) +{ + m_deviceAPI->getDeviceEngineStateStr(*response.getState()); + MsgStartStop *message = MsgStartStop::create(run); + m_inputMessageQueue.push(message); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgStartStop *msgToGUI = MsgStartStop::create(run); + m_guiMessageQueue->push(msgToGUI); + } + + return 200; +} + diff --git a/plugins/samplesink/bladerf2output/bladerf2output.h b/plugins/samplesink/bladerf2output/bladerf2output.h new file mode 100644 index 000000000..f67e79165 --- /dev/null +++ b/plugins/samplesink/bladerf2output/bladerf2output.h @@ -0,0 +1,176 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 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 // +// // +// 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 PLUGINS_SAMPLESINK_BLADERF2OUTPUT_BLADERF2OUTPUT_H_ +#define PLUGINS_SAMPLESINK_BLADERF2OUTPUT_BLADERF2OUTPUT_H_ + +#include +#include + +#include "dsp/devicesamplesink.h" +#include "bladerf2/devicebladerf2shared.h" +#include "bladerf2outputsettings.h" + +class DeviceSinkAPI; +class BladeRF2OutputThread; +struct bladerf_gain_modes; + +class BladeRF2Output : public DeviceSampleSink { +public: + class MsgConfigureBladeRF2 : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const BladeRF2OutputSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureBladeRF2* create(const BladeRF2OutputSettings& settings, bool force) + { + return new MsgConfigureBladeRF2(settings, force); + } + + private: + BladeRF2OutputSettings m_settings; + bool m_force; + + MsgConfigureBladeRF2(const BladeRF2OutputSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + class MsgStartStop : public Message { + MESSAGE_CLASS_DECLARATION + + public: + bool getStartStop() const { return m_startStop; } + + static MsgStartStop* create(bool startStop) { + return new MsgStartStop(startStop); + } + + protected: + bool m_startStop; + + MsgStartStop(bool startStop) : + Message(), + m_startStop(startStop) + { } + }; + + class MsgReportGainRange : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getMin() const { return m_min; } + int getMax() const { return m_max; } + int getStep() const { return m_step; } + + static MsgReportGainRange* create(int min, int max, int step) { + return new MsgReportGainRange(min, max, step); + } + + protected: + int m_min; + int m_max; + int m_step; + + MsgReportGainRange(int min, int max, int step) : + Message(), + m_min(min), + m_max(max), + m_step(step) + {} + }; + + struct GainMode + { + QString m_name; + int m_value; + }; + + BladeRF2Output(DeviceSinkAPI *deviceAPI); + virtual ~BladeRF2Output(); + virtual void destroy(); + + virtual void init(); + virtual bool start(); + virtual void stop(); + BladeRF2OutputThread *getThread() { return m_thread; } + void setThread(BladeRF2OutputThread *thread) { m_thread = thread; } + + 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 getSampleRate() const; + virtual quint64 getCenterFrequency() const; + virtual void setCenterFrequency(qint64 centerFrequency); + + void getFrequencyRange(uint64_t& min, uint64_t& max, int& step); + void getSampleRateRange(int& min, int& max, int& step); + void getBandwidthRange(int& min, int& max, int& step); + void getGlobalGainRange(int& min, int& max, int& step); + const std::vector& getGainModes() { return m_gainModes; } + + 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( + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage); + + virtual int webapiRun( + bool run, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage); + +private: + bool openDevice(); + void closeDevice(); + BladeRF2OutputThread *findThread(); + void moveThreadToBuddy(); + bool applySettings(const BladeRF2OutputSettings& settings, bool force); + void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const BladeRF2OutputSettings& settings); + void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response); + + DeviceSinkAPI *m_deviceAPI; + QMutex m_mutex; + BladeRF2OutputSettings m_settings; + struct bladerf* m_dev; + BladeRF2OutputThread* m_thread; + QString m_deviceDescription; + DeviceBladeRF2Shared m_deviceShared; + bool m_running; + std::vector m_gainModes; +}; + +#endif /* PLUGINS_SAMPLESINK_BLADERF2OUTPUT_BLADERF2OUTPUT_H_ */ diff --git a/plugins/samplesink/bladerf2output/bladerf2outputgui.ui b/plugins/samplesink/bladerf2output/bladerf2outputgui.ui new file mode 100644 index 000000000..751a8db80 --- /dev/null +++ b/plugins/samplesink/bladerf2output/bladerf2outputgui.ui @@ -0,0 +1,464 @@ + + + Bladerf2OutputGui + + + + 0 + 0 + 350 + 200 + + + + + 0 + 0 + + + + + 350 + 200 + + + + + Liberation Sans + 9 + + + + BladeRF2 + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + 4 + + + + + + + + + start/stop acquisition + + + + + + + :/play.png + :/stop.png:/play.png + + + + + + + + + + + I/Q sample rate kS/s + + + 00000k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 20 + + + + PointingHandCursor + + + Qt::StrongFocus + + + Tuner center frequency in kHz + + + + + + + kHz + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + + Qt::Horizontal + + + + + + + + + kHz + + + + + + + + 0 + 0 + + + + BW + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 12 + + + + PointingHandCursor + + + RF bandwidth + + + + + + + Bias Tee + + + BT + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + 2 + + + 2 + + + + + + 0 + 0 + + + + SR + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 12 + + + + PointingHandCursor + + + Device sample rate + + + + + + + S/s + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + I + + + + + + + + 50 + 16777215 + + + + Decimation factor + + + 0 + + + + 1 + + + + + 2 + + + + + 4 + + + + + 8 + + + + + 16 + + + + + 32 + + + + + + + + + + 3 + + + + + Gain value + + + Qt::Horizontal + + + + + + + Gain mode + + + + + + + Gain + + + + + + + + 45 + 0 + + + + 000 dB + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + Qt::Horizontal + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + ValueDial + QWidget +
gui/valuedial.h
+ 1 +
+ + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
+
+ + + + +
diff --git a/plugins/samplesink/bladerf2output/bladerf2outputplugin.cpp b/plugins/samplesink/bladerf2output/bladerf2outputplugin.cpp new file mode 100644 index 000000000..5c950c6df --- /dev/null +++ b/plugins/samplesink/bladerf2output/bladerf2outputplugin.cpp @@ -0,0 +1,157 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 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 // +// // +// 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 "plugin/pluginapi.h" +#include "util/simpleserializer.h" +#include "device/devicesourceapi.h" + +#include "bladerf2outputplugin.h" + +#ifdef SERVER_MODE +#include "bladerf2output.h" +#else +#include "bladerf2outputgui.h" +#endif + +const PluginDescriptor Bladerf2OutputPlugin::m_pluginDescriptor = { + QString("BladeRF2 Output"), + QString("4.2.0"), + QString("(c) Edouard Griffiths, F4EXB"), + QString("https://github.com/f4exb/sdrangel"), + true, + QString("https://github.com/f4exb/sdrangel") +}; + +const QString Bladerf2OutputPlugin::m_hardwareID = "BladeRF2"; +const QString Bladerf2OutputPlugin::m_deviceTypeID = BLADERF2OUTPUT_DEVICE_TYPE_ID; + +Bladerf2OutputPlugin::Bladerf1OutputPlugin(QObject* parent) : + QObject(parent) +{ +} + +const PluginDescriptor& Bladerf2OutputPlugin::getPluginDescriptor() const +{ + return m_pluginDescriptor; +} + +void Bladerf2OutputPlugin::initPlugin(PluginAPI* pluginAPI) +{ + pluginAPI->registerSampleSink(m_deviceTypeID, this); +} + +PluginInterface::SamplingDevices Bladerf2OutputPlugin::enumSampleSinks() +{ + SamplingDevices result; + struct bladerf_devinfo *devinfo = 0; + + int count = bladerf_get_device_list(&devinfo); + + if (devinfo) + { + for(int i = 0; i < count; i++) + { + struct bladerf *dev; + + int status = bladerf_open_with_devinfo(&dev, &devinfo[i]); + + if (status == BLADERF_ERR_NODEV) + { + qCritical("Bladerf2OutputPlugin::enumSampleSinks: No device at index %d", i); + continue; + } + else if (status != 0) + { + qCritical("Bladerf2OutputPlugin::enumSampleSinks: Failed to open device at index %d", i); + continue; + } + + const char *boardName = bladerf_get_board_name(dev); + + if (strcmp(boardName, "bladerf2") == 0) + { + unsigned int nbTxChannels = bladerf_get_channel_count(dev, BLADERF_TX); + + for (unsigned int j = 0; j < nbTxChannels; j++) + { + qDebug("Blderf2InputPlugin::enumSampleSinks: device #%d (%s) channel %u", i, devinfo[i].serial, j); + QString displayedName(QString("BladeRF2[%1:%2] %3").arg(devinfo[i].instance).arg(j).arg(devinfo[i].serial)); + result.append(SamplingDevice(displayedName, + m_hardwareID, + m_deviceTypeID, + QString(devinfo[i].serial), + i, + PluginInterface::SamplingDevice::PhysicalDevice, + false, + nbTxChannels, + j)); + } + } + + bladerf_close(dev); + } + + bladerf_free_device_list(devinfo); // Valgrind memcheck + } + + return result; +} + +#ifdef SERVER_MODE +PluginInstanceGUI* Bladerf2OutputPlugin::createSampleSinkPluginInstanceGUI( + const QString& sinkId __attribute__((unused)), + QWidget **widget __attribute__((unused)), + DeviceUISet *deviceUISet __attribute__((unused))) +{ + return 0; +} +#else +PluginInstanceGUI* Bladerf2OutputPlugin::createSampleSinkPluginInstanceGUI( + const QString& sinkId, + QWidget **widget, + DeviceUISet *deviceUISet) +{ + if(sinkId == m_deviceTypeID) + { + Bladerf2OutputGui* gui = new Bladerf2OutputGui(deviceUISet); + *widget = gui; + return gui; + } + else + { + return 0; + } +} +#endif + +DeviceSampleSink* Bladerf2OutputPlugin::createSampleSinkPluginInstanceOutput(const QString& sinkId, DeviceSinkAPI *deviceAPI) +{ + if(sinkId == m_deviceTypeID) + { + Bladerf2Output* output = new Bladerf2Output(deviceAPI); + return output; + } + else + { + return 0; + } +} + + + + diff --git a/plugins/samplesink/bladerf2output/bladerf2outputplugin.h b/plugins/samplesink/bladerf2output/bladerf2outputplugin.h new file mode 100644 index 000000000..0f46a254e --- /dev/null +++ b/plugins/samplesink/bladerf2output/bladerf2outputplugin.h @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 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 // +// // +// 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 PLUGINS_SAMPLESINK_BLADERF2OUTPUT_BLADERF2OUTPUTPLUGIN_H_ +#define PLUGINS_SAMPLESINK_BLADERF2OUTPUT_BLADERF2OUTPUTPLUGIN_H_ + +#include +#include "plugin/plugininterface.h" + +class PluginAPI; + +#define BLADERF2OUTPUT_DEVICE_TYPE_ID "sdrangel.samplesource.bladerf2output" + +class Bladerf2OutputPlugin : public QObject, public PluginInterface { + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID BLADERF2OUTPUT_DEVICE_TYPE_ID) + +public: + explicit Bladerf2OutputPlugin(QObject* parent = 0); + + const PluginDescriptor& getPluginDescriptor() const; + void initPlugin(PluginAPI* pluginAPI); + + virtual SamplingDevices enumSampleSinks(); + + virtual PluginInstanceGUI* createSampleSinkPluginInstanceGUI( + const QString& sinkId, + QWidget **widget, + DeviceUISet *deviceUISet); + + virtual DeviceSampleSink* createSampleSinkPluginInstanceOutput(const QString& sinkId, DeviceSinkAPI *deviceAPI); + + static const QString m_hardwareID; + static const QString m_deviceTypeID; + +private: + static const PluginDescriptor m_pluginDescriptor; +}; + +#endif /* PLUGINS_SAMPLESINK_BLADERF2OUTPUT_BLADERF2OUTPUTPLUGIN_H_ */ diff --git a/plugins/samplesink/bladerf2output/bladerf2outputsettings.cpp b/plugins/samplesink/bladerf2output/bladerf2outputsettings.cpp new file mode 100644 index 000000000..111f6d06b --- /dev/null +++ b/plugins/samplesink/bladerf2output/bladerf2outputsettings.cpp @@ -0,0 +1,85 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 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 // +// // +// 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 "bladerf2outputsettings.h" + +#include +#include "util/simpleserializer.h" + + +BladeRF2OutputSettings::BladeRF2OutputSettings() +{ + resetToDefaults(); +} + +void BladeRF2OutputSettings::resetToDefaults() +{ + m_centerFrequency = 435000*1000; + m_devSampleRate = 3072000; + m_bandwidth = 1500000; + m_gainMode = 0; + m_globalGain = 0; + m_biasTee = false; + m_log2Interp = 0; +} + +QByteArray BladeRF2OutputSettings::serialize() const +{ + SimpleSerializer s(1); + + s.writeS32(1, m_devSampleRate); + s.writeS32(2, m_bandwidth); + s.writeS32(3, m_gainMode); + s.writeS32(4, m_globalGain); + s.writeBool(5, m_biasTee); + s.writeU32(6, m_log2Interp); + + return s.final(); +} + +bool BladeRF2OutputSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if (!d.isValid()) + { + resetToDefaults(); + return false; + } + + if (d.getVersion() == 1) + { + int intval; + + d.readS32(1, &m_devSampleRate); + d.readS32(2, &m_bandwidth); + d.readS32(3, &m_gainMode); + d.readS32(4, &m_globalGain); + d.readBool(5, &m_biasTee); + d.readU32(6, &m_log2Interp); + + return true; + } + else + { + resetToDefaults(); + return false; + } +} + + + + diff --git a/plugins/samplesink/bladerf2output/bladerf2outputsettings.h b/plugins/samplesink/bladerf2output/bladerf2outputsettings.h new file mode 100644 index 000000000..29132165a --- /dev/null +++ b/plugins/samplesink/bladerf2output/bladerf2outputsettings.h @@ -0,0 +1,40 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 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 // +// // +// 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 PLUGINS_SAMPLESINK_BLADERF2OUTPUT_BLADERF2OUTPUTSETTINGS_H_ +#define PLUGINS_SAMPLESINK_BLADERF2OUTPUT_BLADERF2OUTPUTSETTINGS_H_ + +#include +#include + +struct BladeRF2OutputSettings { + quint64 m_centerFrequency; + qint32 m_devSampleRate; + qint32 m_bandwidth; + int m_gainMode; + int m_globalGain; + bool m_biasTee; + quint32 m_log2Interp; + + BladeRF2OutputSettings(); + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); +}; + + + +#endif /* PLUGINS_SAMPLESINK_BLADERF2OUTPUT_BLADERF2OUTPUTSETTINGS_H_ */ diff --git a/plugins/samplesink/bladerf2output/bladerf2outputthread.cpp b/plugins/samplesink/bladerf2output/bladerf2outputthread.cpp new file mode 100644 index 000000000..87fd1cfdd --- /dev/null +++ b/plugins/samplesink/bladerf2output/bladerf2outputthread.cpp @@ -0,0 +1,223 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 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 // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "dsp/samplesourcefifo.h" + +#include "bladerf2outputthread.h" + +BladeRF2OutputThread::BladeRF2OutputThread(struct bladerf* dev, unsigned int nbTxChannels, QObject* parent) : + QThread(parent), + m_running(false), + m_dev(dev), + m_nbChannels(nbTxChannels) +{ + qDebug("BladeRF2OutputThread::BladeRF2OutputThread"); + m_channels = new Channel[nbTxChannels]; + m_buf = new qint16[2*DeviceBladeRF2::blockSize*nbTxChannels]; +} + +BladeRF2OutputThread::~BladeRF2OutputThread() +{ + qDebug("BladeRF2OutputThread::~BladeRF2OutputThread"); + + if (m_running) { + stopWork(); + } + + delete[] m_buf; + delete[] m_channels; +} + +void BladeRF2OutputThread::startWork() +{ + m_startWaitMutex.lock(); + start(); + + while(!m_running) { + m_startWaiter.wait(&m_startWaitMutex, 100); + } + + m_startWaitMutex.unlock(); +} + +void BladeRF2OutputThread::stopWork() +{ + m_running = false; + wait(); +} + +void BladeRF2OutputThread::run() +{ + int res; + + m_running = true; + m_startWaiter.wakeAll(); + + unsigned int nbFifos = getNbFifos(); + + if ((m_nbChannels > 0) && (nbFifos > 0)) + { + int status; + + if (m_nbChannels > 1) { + status = bladerf_sync_config(m_dev, BLADERF_TX_X2, BLADERF_FORMAT_SC16_Q11, 64, 8192, 32, 10000); + } else { + status = bladerf_sync_config(m_dev, BLADERF_TX_X1, BLADERF_FORMAT_SC16_Q11, 64, 8192, 32, 10000); + } + + if (status < 0) + { + qCritical("BladeRF2OutputThread::run: cannot configure streams: %s", bladerf_strerror(status)); + } + else + { + qDebug("BladeRF2OutputThread::run: start running loop"); + while (m_running) + { + if (m_nbChannels > 1) { + callbackMO(m_buf, DeviceBladeRF2::blockSize); + } else { + callbackSO(m_buf, 2*DeviceBladeRF2::blockSize); + } + + res = bladerf_sync_tx(m_dev, m_buf, DeviceBladeRF2::blockSize, NULL, 10000); + + if (res < 0) + { + qCritical("BladeRF2OutputThread::run sync Rx error: %s", bladerf_strerror(res)); + break; + } + } + qDebug("BladeRF2OutputThread::run: stop running loop"); + } + } + else + { + qWarning("BladeRF2OutputThread::run: no channels or FIFO allocated. Aborting"); + } + + + m_running = false; +} + +unsigned int BladeRF2OutputThread::getNbFifos() +{ + unsigned int fifoCount = 0; + + for (unsigned int i = 0; i < m_nbChannels; i++) + { + if (m_channels[i].m_sampleFifo) { + fifoCount++; + } + } + + return fifoCount; +} + +void BladeRF2OutputThread::setLog2Interpolation(unsigned int channel, unsigned int log2_interp) +{ + if (channel < m_nbChannels) { + m_channels[channel].m_log2Interp = log2_interp; + } +} + +unsigned int BladeRF2OutputThread::getLog2Interpolation(unsigned int channel) const +{ + if (channel < m_nbChannels) { + return m_channels[channel].m_log2Interp; + } else { + return 0; + } +} + +void BladeRF2OutputThread::setFifo(unsigned int channel, SampleSourceFifo *sampleFifo) +{ + if (channel < m_nbChannels) { + m_channels[channel].m_sampleFifo = sampleFifo; + } +} + +SampleSourceFifo *BladeRF2OutputThread::getFifo(unsigned int channel) +{ + if (channel < m_nbChannels) { + return m_channels[channel].m_sampleFifo; + } else { + return 0; + } +} + +void BladeRF2OutputThread::callbackMO(qint16* buf, qint32 samplesPerChannel) +{ + for (unsigned int channel = 0; channel < m_nbChannels; channel++) + { + if (m_channels[channel].m_sampleFifo) { + callbackSO(&buf[2*samplesPerChannel*channel], 2*samplesPerChannel, channel); + } else { + std::fill(&buf[2*samplesPerChannel*channel], &buf[2*samplesPerChannel*channel]+2*samplesPerChannel, 0); // fill with zero samples + } + } + + // TODO: write a set of interpolators that can write interleaved samples in output directly + int status = bladerf_interleave_stream_buffer(BLADERF_TX_X2, BLADERF_FORMAT_SC16_Q11 , samplesPerChannel*m_nbChannels, (void *) buf); + + if (status < 0) + { + qCritical("BladeRF2OutputThread::callbackMI: cannot interleave buffer: %s", bladerf_strerror(status)); + return; + } +} + +// Interpolate according to specified log2 (ex: log2=4 => decim=16) +void BladeRF2OutputThread::callbackSO(qint16* buf, qint32 len, unsigned int channel) +{ + SampleVector::iterator beginRead; + m_channels[channel].m_sampleFifo->readAdvance(beginRead, len/(1<. // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_SAMPLESINK_BLADERF2OUTPUT_BLADERF2OUTPUTTHREAD_H_ +#define PLUGINS_SAMPLESINK_BLADERF2OUTPUT_BLADERF2OUTPUTTHREAD_H_ + +#include +#include +#include +#include + +#include "bladerf2/devicebladerf2shared.h" +#include "dsp/interpolators.h" + +class SampleSinkFifo; + +class BladeRF2OutputThread : public QThread { + Q_OBJECT + +public: + BladeRF2OutputThread(struct bladerf* dev, unsigned int nbTxChannels, QObject* parent = 0); + ~BladeRF2OutputThread(); + + void startWork(); + void stopWork(); + bool isRunning() const { return m_running; } + unsigned int getNbChannels() const { return m_nbChannels; } + void setLog2Interpolation(unsigned int channel, unsigned int log2_interp); + unsigned int getLog2Interpolation(unsigned int channel) const; + void setFcPos(unsigned int channel, int fcPos); + int getFcPos(unsigned int channel) const; + void setFifo(unsigned int channel, SampleSourceFifo *sampleFifo); + SampleSourceFifo *getFifo(unsigned int channel); + +private: + struct Channel + { + SampleSourceFifo* m_sampleFifo; + unsigned int m_log2Interp; + Interpolators m_interpolators; + + Channel() : + m_sampleFifo(0), + m_log2Interp(0) + {} + + ~Channel() + {} + }; + + QMutex m_startWaitMutex; + QWaitCondition m_startWaiter; + bool m_running; + struct bladerf* m_dev; + + Channel *m_channels; //!< Array of channels dynamically allocated for the given number of Rx channels + qint16 *m_buf; //!< Full buffer for SISO or MIMO operation + unsigned int m_nbChannels; + + void run(); + unsigned int getNbFifos(); + void callbackSO(qint16* buf, qint32 len, unsigned int channel = 0); + void callbackMO(qint16* buf, qint32 samplesPerChannel); +}; + + + +#endif /* PLUGINS_SAMPLESINK_BLADERF2OUTPUT_BLADERF2OUTPUTTHREAD_H_ */ diff --git a/plugins/samplesource/bladerf2input/bladerf2input.cpp b/plugins/samplesource/bladerf2input/bladerf2input.cpp index 4faccd6a6..0eba5ae8b 100644 --- a/plugins/samplesource/bladerf2input/bladerf2input.cpp +++ b/plugins/samplesource/bladerf2input/bladerf2input.cpp @@ -96,7 +96,6 @@ bool BladeRF2Input::openDevice() } // look for Rx buddies and get reference to the device object - // if there is a channel left take the first available if (m_deviceAPI->getSourceBuddies().size() > 0) // look source sibling first { qDebug("BladeRF2Input::openDevice: look in Rx buddies"); @@ -121,7 +120,6 @@ bool BladeRF2Input::openDevice() m_deviceShared.m_dev = device; } // look for Tx buddies and get reference to the device object - // allocate the Rx channel unconditionally else if (m_deviceAPI->getSinkBuddies().size() > 0) // then sink { qDebug("BladeRF2Input::openDevice: look in Tx buddies"); @@ -139,14 +137,13 @@ bool BladeRF2Input::openDevice() if (device == 0) { - qCritical("BladeRF2Input::openDevice: cannot get device pointer from Rx buddy"); + qCritical("BladeRF2Input::openDevice: cannot get device pointer from Tx buddy"); return false; } m_deviceShared.m_dev = device; } // There are no buddies then create the first BladeRF2 device - // allocate the Rx channel unconditionally else { qDebug("BladeRF2Input::openDevice: open device here"); @@ -283,7 +280,7 @@ bool BladeRF2Input::start() if (!m_deviceShared.m_dev) { - qDebug("BladerfInput::start: no device object"); + qDebug("BladeRF2Input::start: no device object"); return false; } @@ -293,13 +290,13 @@ bool BladeRF2Input::start() if (bladerf2InputThread) // if thread is already allocated { - qDebug("BladerfInput::start: thread is already allocated"); + qDebug("BladeRF2Input::start: thread is already allocated"); int nbOriginalChannels = bladerf2InputThread->getNbChannels(); if (requestedChannel+1 > nbOriginalChannels) // expansion by deleting and re-creating the thread { - qDebug("BladerfInput::start: expand channels. Re-allocate thread and take ownership"); + qDebug("BladeRF2Input::start: expand channels. Re-allocate thread and take ownership"); SampleSinkFifo **fifos = new SampleSinkFifo*[nbOriginalChannels]; unsigned int *log2Decims = new unsigned int[nbOriginalChannels]; @@ -336,12 +333,12 @@ bool BladeRF2Input::start() } else { - qDebug("BladerfInput::start: keep buddy thread"); + qDebug("BladeRF2Input::start: keep buddy thread"); } } else // first allocation { - qDebug("BladerfInput::start: allocate thread and take ownership"); + qDebug("BladeRF2Input::start: allocate thread and take ownership"); bladerf2InputThread = new BladeRF2InputThread(m_deviceShared.m_dev->getDev(), requestedChannel+1); m_thread = bladerf2InputThread; // take ownership needsStart = true; @@ -353,7 +350,7 @@ bool BladeRF2Input::start() if (needsStart) { - qDebug("BladerfInput::start: enabling channel(s) and (re)sart buddy thread"); + qDebug("BladeRF2Input::start: enabling channel(s) and (re)sart buddy thread"); int nbChannels = bladerf2InputThread->getNbChannels(); diff --git a/plugins/samplesource/bladerf2input/bladerf2inputthread.cpp b/plugins/samplesource/bladerf2input/bladerf2inputthread.cpp index f9de1c623..d4d10e512 100644 --- a/plugins/samplesource/bladerf2input/bladerf2inputthread.cpp +++ b/plugins/samplesource/bladerf2input/bladerf2inputthread.cpp @@ -14,6 +14,8 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// +#include "dsp/samplesinkfifo.h" + #include "bladerf2inputthread.h" BladeRF2InputThread::BladeRF2InputThread(struct bladerf* dev, unsigned int nbRxChannels, QObject* parent) : diff --git a/plugins/samplesource/bladerf2input/bladerf2inputthread.h b/plugins/samplesource/bladerf2input/bladerf2inputthread.h index ad033c768..ad5886620 100644 --- a/plugins/samplesource/bladerf2input/bladerf2inputthread.h +++ b/plugins/samplesource/bladerf2input/bladerf2inputthread.h @@ -29,9 +29,10 @@ #include #include "bladerf2/devicebladerf2shared.h" -#include "dsp/samplesinkfifo.h" #include "dsp/decimators.h" +class SampleSinkFifo; + class BladeRF2InputThread : public QThread { Q_OBJECT @@ -39,16 +40,16 @@ public: BladeRF2InputThread(struct bladerf* dev, unsigned int nbRxChannels, QObject* parent = NULL); ~BladeRF2InputThread(); - virtual void startWork(); - virtual void stopWork(); - virtual bool isRunning() const { return m_running; } - virtual unsigned int getNbChannels() const { return m_nbChannels; } - virtual void setLog2Decimation(unsigned int channel, unsigned int log2_decim); - virtual unsigned int getLog2Decimation(unsigned int channel) const; - virtual void setFcPos(unsigned int channel, int fcPos); - virtual int getFcPos(unsigned int channel) const; - virtual void setFifo(unsigned int channel, SampleSinkFifo *sampleFifo); - virtual SampleSinkFifo *getFifo(unsigned int channel); + void startWork(); + void stopWork(); + bool isRunning() const { return m_running; } + unsigned int getNbChannels() const { return m_nbChannels; } + void setLog2Decimation(unsigned int channel, unsigned int log2_decim); + unsigned int getLog2Decimation(unsigned int channel) const; + void setFcPos(unsigned int channel, int fcPos); + int getFcPos(unsigned int channel) const; + void setFifo(unsigned int channel, SampleSinkFifo *sampleFifo); + SampleSinkFifo *getFifo(unsigned int channel); private: struct Channel diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 52d4b1fa3..30babd580 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -1363,6 +1363,56 @@ margin-bottom: 20px; } }, "description" : "BladeRF2" +}; + defs.BladeRF2OutputReport = { + "properties" : { + "frequencyRange" : { + "$ref" : "#/definitions/FrequencyRange" + }, + "sampleRateRange" : { + "$ref" : "#/definitions/Range" + }, + "bandwidthRange" : { + "$ref" : "#/definitions/Range" + }, + "globalGainRange" : { + "$ref" : "#/definitions/Range" + }, + "gainModes" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/NamedEnum" + } + } + }, + "description" : "BladeRF2" +}; + defs.BladeRF2OutputSettings = { + "properties" : { + "centerFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "devSampleRate" : { + "type" : "integer" + }, + "bandwidth" : { + "type" : "integer" + }, + "gainMode" : { + "type" : "integer" + }, + "globalGain" : { + "type" : "integer" + }, + "biasTee" : { + "type" : "integer" + }, + "log2Interp" : { + "type" : "integer" + } + }, + "description" : "BladeRF2" }; defs.CWKeyerSettings = { "properties" : { @@ -1903,6 +1953,9 @@ margin-bottom: 20px; "bladeRF2InputReport" : { "$ref" : "#/definitions/BladeRF2InputReport" }, + "bladeRF2OutputReport" : { + "$ref" : "#/definitions/BladeRF2OutputReport" + }, "fileSourceReport" : { "$ref" : "#/definitions/FileSourceReport" }, @@ -2003,6 +2056,9 @@ margin-bottom: 20px; "bladeRF1OutputSettings" : { "$ref" : "#/definitions/BladeRF1OutputSettings" }, + "bladeRF2OutputSettings" : { + "$ref" : "#/definitions/BladeRF2OutputSettings" + }, "fcdProSettings" : { "$ref" : "#/definitions/FCDProSettings" }, @@ -23175,7 +23231,7 @@ except ApiException as e:
- Generated 2018-09-25T16:51:16.493+02:00 + Generated 2018-09-29T05:36:53.044+02:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/BladeRF2.yaml b/sdrbase/resources/webapi/doc/swagger/include/BladeRF2.yaml index 39332634b..61f00b5d2 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/BladeRF2.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/BladeRF2.yaml @@ -40,3 +40,38 @@ BladeRF2InputReport: type: array items: $ref: "/doc/swagger/include/Structs.yaml#/NamedEnum" + +BladeRF2OutputSettings: + description: BladeRF2 + properties: + centerFrequency: + type: integer + format: int64 + devSampleRate: + type: integer + bandwidth: + type: integer + gainMode: + type: integer + globalGain: + type: integer + biasTee: + type: integer + log2Interp: + type: integer + +BladeRF2OutputReport: + description: BladeRF2 + properties: + frequencyRange: + $ref: "/doc/swagger/include/Structs.yaml#/FrequencyRange" + sampleRateRange: + $ref: "/doc/swagger/include/Structs.yaml#/Range" + bandwidthRange: + $ref: "/doc/swagger/include/Structs.yaml#/Range" + globalGainRange: + $ref: "/doc/swagger/include/Structs.yaml#/Range" + gainModes: + type: array + items: + $ref: "/doc/swagger/include/Structs.yaml#/NamedEnum" diff --git a/sdrbase/resources/webapi/doc/swagger/swagger.yaml b/sdrbase/resources/webapi/doc/swagger/swagger.yaml index 1e5a16dba..2a8ca35ba 100644 --- a/sdrbase/resources/webapi/doc/swagger/swagger.yaml +++ b/sdrbase/resources/webapi/doc/swagger/swagger.yaml @@ -1769,6 +1769,8 @@ definitions: $ref: "/doc/swagger/include/BladeRF2.yaml#/BladeRF2InputSettings" bladeRF1OutputSettings: $ref: "/doc/swagger/include/BladeRF1.yaml#/BladeRF1OutputSettings" + bladeRF2OutputSettings: + $ref: "/doc/swagger/include/BladeRF2.yaml#/BladeRF2OutputSettings" fcdProSettings: $ref: "/doc/swagger/include/FCDPro.yaml#/FCDProSettings" fcdProPlusSettings: @@ -1820,6 +1822,8 @@ definitions: $ref: "/doc/swagger/include/AirspyHF.yaml#/AirspyHFReport" bladeRF2InputReport: $ref: "/doc/swagger/include/BladeRF2.yaml#/BladeRF2InputReport" + bladeRF2OutputReport: + $ref: "/doc/swagger/include/BladeRF2.yaml#/BladeRF2OutputReport" fileSourceReport: $ref: "/doc/swagger/include/FileSource.yaml#/FileSourceReport" limeSdrInputReport: diff --git a/swagger/sdrangel/api/swagger/include/BladeRF2.yaml b/swagger/sdrangel/api/swagger/include/BladeRF2.yaml index c87dc8d81..0198207d3 100644 --- a/swagger/sdrangel/api/swagger/include/BladeRF2.yaml +++ b/swagger/sdrangel/api/swagger/include/BladeRF2.yaml @@ -40,3 +40,38 @@ BladeRF2InputReport: type: array items: $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/NamedEnum" + +BladeRF2OutputSettings: + description: BladeRF2 + properties: + centerFrequency: + type: integer + format: int64 + devSampleRate: + type: integer + bandwidth: + type: integer + gainMode: + type: integer + globalGain: + type: integer + biasTee: + type: integer + log2Interp: + type: integer + +BladeRF2OutputReport: + description: BladeRF2 + properties: + frequencyRange: + $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/FrequencyRange" + sampleRateRange: + $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/Range" + bandwidthRange: + $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/Range" + globalGainRange: + $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/Range" + gainModes: + type: array + items: + $ref: "http://localhost:8081/api/swagger/include/Structs.yaml#/NamedEnum" diff --git a/swagger/sdrangel/api/swagger/swagger.yaml b/swagger/sdrangel/api/swagger/swagger.yaml index 1598f5faf..a9d37464d 100644 --- a/swagger/sdrangel/api/swagger/swagger.yaml +++ b/swagger/sdrangel/api/swagger/swagger.yaml @@ -1769,6 +1769,8 @@ definitions: $ref: "http://localhost:8081/api/swagger/include/BladeRF2.yaml#/BladeRF2InputSettings" bladeRF1OutputSettings: $ref: "http://localhost:8081/api/swagger/include/BladeRF1.yaml#/BladeRF1OutputSettings" + bladeRF2OutputSettings: + $ref: "http://localhost:8081/api/swagger/include/BladeRF2.yaml#/BladeRF2OutputSettings" fcdProSettings: $ref: "http://localhost:8081/api/swagger/include/FCDPro.yaml#/FCDProSettings" fcdProPlusSettings: @@ -1820,6 +1822,8 @@ definitions: $ref: "http://localhost:8081/api/swagger/include/AirspyHF.yaml#/AirspyHFReport" bladeRF2InputReport: $ref: "http://localhost:8081/api/swagger/include/BladeRF2.yaml#/BladeRF2InputReport" + bladeRF2OutputReport: + $ref: "http://localhost:8081/api/swagger/include/BladeRF2.yaml#/BladeRF2OutputReport" fileSourceReport: $ref: "http://localhost:8081/api/swagger/include/FileSource.yaml#/FileSourceReport" limeSdrInputReport: diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 52d4b1fa3..30babd580 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -1363,6 +1363,56 @@ margin-bottom: 20px; } }, "description" : "BladeRF2" +}; + defs.BladeRF2OutputReport = { + "properties" : { + "frequencyRange" : { + "$ref" : "#/definitions/FrequencyRange" + }, + "sampleRateRange" : { + "$ref" : "#/definitions/Range" + }, + "bandwidthRange" : { + "$ref" : "#/definitions/Range" + }, + "globalGainRange" : { + "$ref" : "#/definitions/Range" + }, + "gainModes" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/NamedEnum" + } + } + }, + "description" : "BladeRF2" +}; + defs.BladeRF2OutputSettings = { + "properties" : { + "centerFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "devSampleRate" : { + "type" : "integer" + }, + "bandwidth" : { + "type" : "integer" + }, + "gainMode" : { + "type" : "integer" + }, + "globalGain" : { + "type" : "integer" + }, + "biasTee" : { + "type" : "integer" + }, + "log2Interp" : { + "type" : "integer" + } + }, + "description" : "BladeRF2" }; defs.CWKeyerSettings = { "properties" : { @@ -1903,6 +1953,9 @@ margin-bottom: 20px; "bladeRF2InputReport" : { "$ref" : "#/definitions/BladeRF2InputReport" }, + "bladeRF2OutputReport" : { + "$ref" : "#/definitions/BladeRF2OutputReport" + }, "fileSourceReport" : { "$ref" : "#/definitions/FileSourceReport" }, @@ -2003,6 +2056,9 @@ margin-bottom: 20px; "bladeRF1OutputSettings" : { "$ref" : "#/definitions/BladeRF1OutputSettings" }, + "bladeRF2OutputSettings" : { + "$ref" : "#/definitions/BladeRF2OutputSettings" + }, "fcdProSettings" : { "$ref" : "#/definitions/FCDProSettings" }, @@ -23175,7 +23231,7 @@ except ApiException as e:
- Generated 2018-09-25T16:51:16.493+02:00 + Generated 2018-09-29T05:36:53.044+02:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputReport.cpp b/swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputReport.cpp new file mode 100644 index 000000000..8ce6ae808 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputReport.cpp @@ -0,0 +1,204 @@ +/** + * 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: 4.2.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 "SWGBladeRF2OutputReport.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGBladeRF2OutputReport::SWGBladeRF2OutputReport(QString* json) { + init(); + this->fromJson(*json); +} + +SWGBladeRF2OutputReport::SWGBladeRF2OutputReport() { + frequency_range = nullptr; + m_frequency_range_isSet = false; + sample_rate_range = nullptr; + m_sample_rate_range_isSet = false; + bandwidth_range = nullptr; + m_bandwidth_range_isSet = false; + global_gain_range = nullptr; + m_global_gain_range_isSet = false; + gain_modes = nullptr; + m_gain_modes_isSet = false; +} + +SWGBladeRF2OutputReport::~SWGBladeRF2OutputReport() { + this->cleanup(); +} + +void +SWGBladeRF2OutputReport::init() { + frequency_range = new SWGFrequencyRange(); + m_frequency_range_isSet = false; + sample_rate_range = new SWGRange(); + m_sample_rate_range_isSet = false; + bandwidth_range = new SWGRange(); + m_bandwidth_range_isSet = false; + global_gain_range = new SWGRange(); + m_global_gain_range_isSet = false; + gain_modes = new QList(); + m_gain_modes_isSet = false; +} + +void +SWGBladeRF2OutputReport::cleanup() { + if(frequency_range != nullptr) { + delete frequency_range; + } + if(sample_rate_range != nullptr) { + delete sample_rate_range; + } + if(bandwidth_range != nullptr) { + delete bandwidth_range; + } + if(global_gain_range != nullptr) { + delete global_gain_range; + } + if(gain_modes != nullptr) { + auto arr = gain_modes; + for(auto o: *arr) { + delete o; + } + delete gain_modes; + } +} + +SWGBladeRF2OutputReport* +SWGBladeRF2OutputReport::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGBladeRF2OutputReport::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&frequency_range, pJson["frequencyRange"], "SWGFrequencyRange", "SWGFrequencyRange"); + + ::SWGSDRangel::setValue(&sample_rate_range, pJson["sampleRateRange"], "SWGRange", "SWGRange"); + + ::SWGSDRangel::setValue(&bandwidth_range, pJson["bandwidthRange"], "SWGRange", "SWGRange"); + + ::SWGSDRangel::setValue(&global_gain_range, pJson["globalGainRange"], "SWGRange", "SWGRange"); + + + ::SWGSDRangel::setValue(&gain_modes, pJson["gainModes"], "QList", "SWGNamedEnum"); +} + +QString +SWGBladeRF2OutputReport::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGBladeRF2OutputReport::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if((frequency_range != nullptr) && (frequency_range->isSet())){ + toJsonValue(QString("frequencyRange"), frequency_range, obj, QString("SWGFrequencyRange")); + } + if((sample_rate_range != nullptr) && (sample_rate_range->isSet())){ + toJsonValue(QString("sampleRateRange"), sample_rate_range, obj, QString("SWGRange")); + } + if((bandwidth_range != nullptr) && (bandwidth_range->isSet())){ + toJsonValue(QString("bandwidthRange"), bandwidth_range, obj, QString("SWGRange")); + } + if((global_gain_range != nullptr) && (global_gain_range->isSet())){ + toJsonValue(QString("globalGainRange"), global_gain_range, obj, QString("SWGRange")); + } + if(gain_modes->size() > 0){ + toJsonArray((QList*)gain_modes, obj, "gainModes", "SWGNamedEnum"); + } + + return obj; +} + +SWGFrequencyRange* +SWGBladeRF2OutputReport::getFrequencyRange() { + return frequency_range; +} +void +SWGBladeRF2OutputReport::setFrequencyRange(SWGFrequencyRange* frequency_range) { + this->frequency_range = frequency_range; + this->m_frequency_range_isSet = true; +} + +SWGRange* +SWGBladeRF2OutputReport::getSampleRateRange() { + return sample_rate_range; +} +void +SWGBladeRF2OutputReport::setSampleRateRange(SWGRange* sample_rate_range) { + this->sample_rate_range = sample_rate_range; + this->m_sample_rate_range_isSet = true; +} + +SWGRange* +SWGBladeRF2OutputReport::getBandwidthRange() { + return bandwidth_range; +} +void +SWGBladeRF2OutputReport::setBandwidthRange(SWGRange* bandwidth_range) { + this->bandwidth_range = bandwidth_range; + this->m_bandwidth_range_isSet = true; +} + +SWGRange* +SWGBladeRF2OutputReport::getGlobalGainRange() { + return global_gain_range; +} +void +SWGBladeRF2OutputReport::setGlobalGainRange(SWGRange* global_gain_range) { + this->global_gain_range = global_gain_range; + this->m_global_gain_range_isSet = true; +} + +QList* +SWGBladeRF2OutputReport::getGainModes() { + return gain_modes; +} +void +SWGBladeRF2OutputReport::setGainModes(QList* gain_modes) { + this->gain_modes = gain_modes; + this->m_gain_modes_isSet = true; +} + + +bool +SWGBladeRF2OutputReport::isSet(){ + bool isObjectUpdated = false; + do{ + if(frequency_range != nullptr && frequency_range->isSet()){ isObjectUpdated = true; break;} + if(sample_rate_range != nullptr && sample_rate_range->isSet()){ isObjectUpdated = true; break;} + if(bandwidth_range != nullptr && bandwidth_range->isSet()){ isObjectUpdated = true; break;} + if(global_gain_range != nullptr && global_gain_range->isSet()){ isObjectUpdated = true; break;} + if(gain_modes->size() > 0){ isObjectUpdated = true; break;} + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputReport.h b/swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputReport.h new file mode 100644 index 000000000..e6ea9646e --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputReport.h @@ -0,0 +1,86 @@ +/** + * 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: 4.2.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. + */ + +/* + * SWGBladeRF2OutputReport.h + * + * BladeRF2 + */ + +#ifndef SWGBladeRF2OutputReport_H_ +#define SWGBladeRF2OutputReport_H_ + +#include + + +#include "SWGFrequencyRange.h" +#include "SWGNamedEnum.h" +#include "SWGRange.h" +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGBladeRF2OutputReport: public SWGObject { +public: + SWGBladeRF2OutputReport(); + SWGBladeRF2OutputReport(QString* json); + virtual ~SWGBladeRF2OutputReport(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGBladeRF2OutputReport* fromJson(QString &jsonString) override; + + SWGFrequencyRange* getFrequencyRange(); + void setFrequencyRange(SWGFrequencyRange* frequency_range); + + SWGRange* getSampleRateRange(); + void setSampleRateRange(SWGRange* sample_rate_range); + + SWGRange* getBandwidthRange(); + void setBandwidthRange(SWGRange* bandwidth_range); + + SWGRange* getGlobalGainRange(); + void setGlobalGainRange(SWGRange* global_gain_range); + + QList* getGainModes(); + void setGainModes(QList* gain_modes); + + + virtual bool isSet() override; + +private: + SWGFrequencyRange* frequency_range; + bool m_frequency_range_isSet; + + SWGRange* sample_rate_range; + bool m_sample_rate_range_isSet; + + SWGRange* bandwidth_range; + bool m_bandwidth_range_isSet; + + SWGRange* global_gain_range; + bool m_global_gain_range_isSet; + + QList* gain_modes; + bool m_gain_modes_isSet; + +}; + +} + +#endif /* SWGBladeRF2OutputReport_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputSettings.cpp new file mode 100644 index 000000000..f28ca0d5c --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputSettings.cpp @@ -0,0 +1,232 @@ +/** + * 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: 4.2.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 "SWGBladeRF2OutputSettings.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGBladeRF2OutputSettings::SWGBladeRF2OutputSettings(QString* json) { + init(); + this->fromJson(*json); +} + +SWGBladeRF2OutputSettings::SWGBladeRF2OutputSettings() { + center_frequency = 0L; + m_center_frequency_isSet = false; + dev_sample_rate = 0; + m_dev_sample_rate_isSet = false; + bandwidth = 0; + m_bandwidth_isSet = false; + gain_mode = 0; + m_gain_mode_isSet = false; + global_gain = 0; + m_global_gain_isSet = false; + bias_tee = 0; + m_bias_tee_isSet = false; + log2_interp = 0; + m_log2_interp_isSet = false; +} + +SWGBladeRF2OutputSettings::~SWGBladeRF2OutputSettings() { + this->cleanup(); +} + +void +SWGBladeRF2OutputSettings::init() { + center_frequency = 0L; + m_center_frequency_isSet = false; + dev_sample_rate = 0; + m_dev_sample_rate_isSet = false; + bandwidth = 0; + m_bandwidth_isSet = false; + gain_mode = 0; + m_gain_mode_isSet = false; + global_gain = 0; + m_global_gain_isSet = false; + bias_tee = 0; + m_bias_tee_isSet = false; + log2_interp = 0; + m_log2_interp_isSet = false; +} + +void +SWGBladeRF2OutputSettings::cleanup() { + + + + + + + +} + +SWGBladeRF2OutputSettings* +SWGBladeRF2OutputSettings::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGBladeRF2OutputSettings::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(¢er_frequency, pJson["centerFrequency"], "qint64", ""); + + ::SWGSDRangel::setValue(&dev_sample_rate, pJson["devSampleRate"], "qint32", ""); + + ::SWGSDRangel::setValue(&bandwidth, pJson["bandwidth"], "qint32", ""); + + ::SWGSDRangel::setValue(&gain_mode, pJson["gainMode"], "qint32", ""); + + ::SWGSDRangel::setValue(&global_gain, pJson["globalGain"], "qint32", ""); + + ::SWGSDRangel::setValue(&bias_tee, pJson["biasTee"], "qint32", ""); + + ::SWGSDRangel::setValue(&log2_interp, pJson["log2Interp"], "qint32", ""); + +} + +QString +SWGBladeRF2OutputSettings::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGBladeRF2OutputSettings::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_center_frequency_isSet){ + obj->insert("centerFrequency", QJsonValue(center_frequency)); + } + if(m_dev_sample_rate_isSet){ + obj->insert("devSampleRate", QJsonValue(dev_sample_rate)); + } + if(m_bandwidth_isSet){ + obj->insert("bandwidth", QJsonValue(bandwidth)); + } + if(m_gain_mode_isSet){ + obj->insert("gainMode", QJsonValue(gain_mode)); + } + if(m_global_gain_isSet){ + obj->insert("globalGain", QJsonValue(global_gain)); + } + if(m_bias_tee_isSet){ + obj->insert("biasTee", QJsonValue(bias_tee)); + } + if(m_log2_interp_isSet){ + obj->insert("log2Interp", QJsonValue(log2_interp)); + } + + return obj; +} + +qint64 +SWGBladeRF2OutputSettings::getCenterFrequency() { + return center_frequency; +} +void +SWGBladeRF2OutputSettings::setCenterFrequency(qint64 center_frequency) { + this->center_frequency = center_frequency; + this->m_center_frequency_isSet = true; +} + +qint32 +SWGBladeRF2OutputSettings::getDevSampleRate() { + return dev_sample_rate; +} +void +SWGBladeRF2OutputSettings::setDevSampleRate(qint32 dev_sample_rate) { + this->dev_sample_rate = dev_sample_rate; + this->m_dev_sample_rate_isSet = true; +} + +qint32 +SWGBladeRF2OutputSettings::getBandwidth() { + return bandwidth; +} +void +SWGBladeRF2OutputSettings::setBandwidth(qint32 bandwidth) { + this->bandwidth = bandwidth; + this->m_bandwidth_isSet = true; +} + +qint32 +SWGBladeRF2OutputSettings::getGainMode() { + return gain_mode; +} +void +SWGBladeRF2OutputSettings::setGainMode(qint32 gain_mode) { + this->gain_mode = gain_mode; + this->m_gain_mode_isSet = true; +} + +qint32 +SWGBladeRF2OutputSettings::getGlobalGain() { + return global_gain; +} +void +SWGBladeRF2OutputSettings::setGlobalGain(qint32 global_gain) { + this->global_gain = global_gain; + this->m_global_gain_isSet = true; +} + +qint32 +SWGBladeRF2OutputSettings::getBiasTee() { + return bias_tee; +} +void +SWGBladeRF2OutputSettings::setBiasTee(qint32 bias_tee) { + this->bias_tee = bias_tee; + this->m_bias_tee_isSet = true; +} + +qint32 +SWGBladeRF2OutputSettings::getLog2Interp() { + return log2_interp; +} +void +SWGBladeRF2OutputSettings::setLog2Interp(qint32 log2_interp) { + this->log2_interp = log2_interp; + this->m_log2_interp_isSet = true; +} + + +bool +SWGBladeRF2OutputSettings::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_center_frequency_isSet){ isObjectUpdated = true; break;} + if(m_dev_sample_rate_isSet){ isObjectUpdated = true; break;} + if(m_bandwidth_isSet){ isObjectUpdated = true; break;} + if(m_gain_mode_isSet){ isObjectUpdated = true; break;} + if(m_global_gain_isSet){ isObjectUpdated = true; break;} + if(m_bias_tee_isSet){ isObjectUpdated = true; break;} + if(m_log2_interp_isSet){ isObjectUpdated = true; break;} + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputSettings.h b/swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputSettings.h new file mode 100644 index 000000000..89daff30f --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGBladeRF2OutputSettings.h @@ -0,0 +1,94 @@ +/** + * 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: 4.2.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. + */ + +/* + * SWGBladeRF2OutputSettings.h + * + * BladeRF2 + */ + +#ifndef SWGBladeRF2OutputSettings_H_ +#define SWGBladeRF2OutputSettings_H_ + +#include + + + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGBladeRF2OutputSettings: public SWGObject { +public: + SWGBladeRF2OutputSettings(); + SWGBladeRF2OutputSettings(QString* json); + virtual ~SWGBladeRF2OutputSettings(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGBladeRF2OutputSettings* fromJson(QString &jsonString) override; + + qint64 getCenterFrequency(); + void setCenterFrequency(qint64 center_frequency); + + qint32 getDevSampleRate(); + void setDevSampleRate(qint32 dev_sample_rate); + + qint32 getBandwidth(); + void setBandwidth(qint32 bandwidth); + + qint32 getGainMode(); + void setGainMode(qint32 gain_mode); + + qint32 getGlobalGain(); + void setGlobalGain(qint32 global_gain); + + qint32 getBiasTee(); + void setBiasTee(qint32 bias_tee); + + qint32 getLog2Interp(); + void setLog2Interp(qint32 log2_interp); + + + virtual bool isSet() override; + +private: + qint64 center_frequency; + bool m_center_frequency_isSet; + + qint32 dev_sample_rate; + bool m_dev_sample_rate_isSet; + + qint32 bandwidth; + bool m_bandwidth_isSet; + + qint32 gain_mode; + bool m_gain_mode_isSet; + + qint32 global_gain; + bool m_global_gain_isSet; + + qint32 bias_tee; + bool m_bias_tee_isSet; + + qint32 log2_interp; + bool m_log2_interp_isSet; + +}; + +} + +#endif /* SWGBladeRF2OutputSettings_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp index a153e10a1..2620b44b0 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp @@ -38,6 +38,8 @@ SWGDeviceReport::SWGDeviceReport() { m_airspy_hf_report_isSet = false; blade_rf2_input_report = nullptr; m_blade_rf2_input_report_isSet = false; + blade_rf2_output_report = nullptr; + m_blade_rf2_output_report_isSet = false; file_source_report = nullptr; m_file_source_report_isSet = false; lime_sdr_input_report = nullptr; @@ -76,6 +78,8 @@ SWGDeviceReport::init() { m_airspy_hf_report_isSet = false; blade_rf2_input_report = new SWGBladeRF2InputReport(); m_blade_rf2_input_report_isSet = false; + blade_rf2_output_report = new SWGBladeRF2OutputReport(); + m_blade_rf2_output_report_isSet = false; file_source_report = new SWGFileSourceReport(); m_file_source_report_isSet = false; lime_sdr_input_report = new SWGLimeSdrInputReport(); @@ -113,6 +117,9 @@ SWGDeviceReport::cleanup() { if(blade_rf2_input_report != nullptr) { delete blade_rf2_input_report; } + if(blade_rf2_output_report != nullptr) { + delete blade_rf2_output_report; + } if(file_source_report != nullptr) { delete file_source_report; } @@ -166,6 +173,8 @@ SWGDeviceReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&blade_rf2_input_report, pJson["bladeRF2InputReport"], "SWGBladeRF2InputReport", "SWGBladeRF2InputReport"); + ::SWGSDRangel::setValue(&blade_rf2_output_report, pJson["bladeRF2OutputReport"], "SWGBladeRF2OutputReport", "SWGBladeRF2OutputReport"); + ::SWGSDRangel::setValue(&file_source_report, pJson["fileSourceReport"], "SWGFileSourceReport", "SWGFileSourceReport"); ::SWGSDRangel::setValue(&lime_sdr_input_report, pJson["limeSdrInputReport"], "SWGLimeSdrInputReport", "SWGLimeSdrInputReport"); @@ -217,6 +226,9 @@ SWGDeviceReport::asJsonObject() { if((blade_rf2_input_report != nullptr) && (blade_rf2_input_report->isSet())){ toJsonValue(QString("bladeRF2InputReport"), blade_rf2_input_report, obj, QString("SWGBladeRF2InputReport")); } + if((blade_rf2_output_report != nullptr) && (blade_rf2_output_report->isSet())){ + toJsonValue(QString("bladeRF2OutputReport"), blade_rf2_output_report, obj, QString("SWGBladeRF2OutputReport")); + } if((file_source_report != nullptr) && (file_source_report->isSet())){ toJsonValue(QString("fileSourceReport"), file_source_report, obj, QString("SWGFileSourceReport")); } @@ -301,6 +313,16 @@ SWGDeviceReport::setBladeRf2InputReport(SWGBladeRF2InputReport* blade_rf2_input_ this->m_blade_rf2_input_report_isSet = true; } +SWGBladeRF2OutputReport* +SWGDeviceReport::getBladeRf2OutputReport() { + return blade_rf2_output_report; +} +void +SWGDeviceReport::setBladeRf2OutputReport(SWGBladeRF2OutputReport* blade_rf2_output_report) { + this->blade_rf2_output_report = blade_rf2_output_report; + this->m_blade_rf2_output_report_isSet = true; +} + SWGFileSourceReport* SWGDeviceReport::getFileSourceReport() { return file_source_report; @@ -411,6 +433,7 @@ SWGDeviceReport::isSet(){ if(airspy_report != nullptr && airspy_report->isSet()){ isObjectUpdated = true; break;} if(airspy_hf_report != nullptr && airspy_hf_report->isSet()){ isObjectUpdated = true; break;} if(blade_rf2_input_report != nullptr && blade_rf2_input_report->isSet()){ isObjectUpdated = true; break;} + if(blade_rf2_output_report != nullptr && blade_rf2_output_report->isSet()){ isObjectUpdated = true; break;} if(file_source_report != nullptr && file_source_report->isSet()){ isObjectUpdated = true; break;} if(lime_sdr_input_report != nullptr && lime_sdr_input_report->isSet()){ isObjectUpdated = true; break;} if(lime_sdr_output_report != nullptr && lime_sdr_output_report->isSet()){ isObjectUpdated = true; break;} diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h index 068ea5a1a..22987625f 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h @@ -25,6 +25,7 @@ #include "SWGAirspyHFReport.h" #include "SWGAirspyReport.h" #include "SWGBladeRF2InputReport.h" +#include "SWGBladeRF2OutputReport.h" #include "SWGFileSourceReport.h" #include "SWGLimeSdrInputReport.h" #include "SWGLimeSdrOutputReport.h" @@ -70,6 +71,9 @@ public: SWGBladeRF2InputReport* getBladeRf2InputReport(); void setBladeRf2InputReport(SWGBladeRF2InputReport* blade_rf2_input_report); + SWGBladeRF2OutputReport* getBladeRf2OutputReport(); + void setBladeRf2OutputReport(SWGBladeRF2OutputReport* blade_rf2_output_report); + SWGFileSourceReport* getFileSourceReport(); void setFileSourceReport(SWGFileSourceReport* file_source_report); @@ -119,6 +123,9 @@ private: SWGBladeRF2InputReport* blade_rf2_input_report; bool m_blade_rf2_input_report_isSet; + SWGBladeRF2OutputReport* blade_rf2_output_report; + bool m_blade_rf2_output_report_isSet; + SWGFileSourceReport* file_source_report; bool m_file_source_report_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp index 8f581f8ec..d64fa15fe 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp @@ -42,6 +42,8 @@ SWGDeviceSettings::SWGDeviceSettings() { m_blade_rf2_input_settings_isSet = false; blade_rf1_output_settings = nullptr; m_blade_rf1_output_settings_isSet = false; + blade_rf2_output_settings = nullptr; + m_blade_rf2_output_settings_isSet = false; fcd_pro_settings = nullptr; m_fcd_pro_settings_isSet = false; fcd_pro_plus_settings = nullptr; @@ -94,6 +96,8 @@ SWGDeviceSettings::init() { m_blade_rf2_input_settings_isSet = false; blade_rf1_output_settings = new SWGBladeRF1OutputSettings(); m_blade_rf1_output_settings_isSet = false; + blade_rf2_output_settings = new SWGBladeRF2OutputSettings(); + m_blade_rf2_output_settings_isSet = false; fcd_pro_settings = new SWGFCDProSettings(); m_fcd_pro_settings_isSet = false; fcd_pro_plus_settings = new SWGFCDProPlusSettings(); @@ -147,6 +151,9 @@ SWGDeviceSettings::cleanup() { if(blade_rf1_output_settings != nullptr) { delete blade_rf1_output_settings; } + if(blade_rf2_output_settings != nullptr) { + delete blade_rf2_output_settings; + } if(fcd_pro_settings != nullptr) { delete fcd_pro_settings; } @@ -219,6 +226,8 @@ SWGDeviceSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&blade_rf1_output_settings, pJson["bladeRF1OutputSettings"], "SWGBladeRF1OutputSettings", "SWGBladeRF1OutputSettings"); + ::SWGSDRangel::setValue(&blade_rf2_output_settings, pJson["bladeRF2OutputSettings"], "SWGBladeRF2OutputSettings", "SWGBladeRF2OutputSettings"); + ::SWGSDRangel::setValue(&fcd_pro_settings, pJson["fcdProSettings"], "SWGFCDProSettings", "SWGFCDProSettings"); ::SWGSDRangel::setValue(&fcd_pro_plus_settings, pJson["fcdProPlusSettings"], "SWGFCDProPlusSettings", "SWGFCDProPlusSettings"); @@ -286,6 +295,9 @@ SWGDeviceSettings::asJsonObject() { if((blade_rf1_output_settings != nullptr) && (blade_rf1_output_settings->isSet())){ toJsonValue(QString("bladeRF1OutputSettings"), blade_rf1_output_settings, obj, QString("SWGBladeRF1OutputSettings")); } + if((blade_rf2_output_settings != nullptr) && (blade_rf2_output_settings->isSet())){ + toJsonValue(QString("bladeRF2OutputSettings"), blade_rf2_output_settings, obj, QString("SWGBladeRF2OutputSettings")); + } if((fcd_pro_settings != nullptr) && (fcd_pro_settings->isSet())){ toJsonValue(QString("fcdProSettings"), fcd_pro_settings, obj, QString("SWGFCDProSettings")); } @@ -405,6 +417,16 @@ SWGDeviceSettings::setBladeRf1OutputSettings(SWGBladeRF1OutputSettings* blade_rf this->m_blade_rf1_output_settings_isSet = true; } +SWGBladeRF2OutputSettings* +SWGDeviceSettings::getBladeRf2OutputSettings() { + return blade_rf2_output_settings; +} +void +SWGDeviceSettings::setBladeRf2OutputSettings(SWGBladeRF2OutputSettings* blade_rf2_output_settings) { + this->blade_rf2_output_settings = blade_rf2_output_settings; + this->m_blade_rf2_output_settings_isSet = true; +} + SWGFCDProSettings* SWGDeviceSettings::getFcdProSettings() { return fcd_pro_settings; @@ -567,6 +589,7 @@ SWGDeviceSettings::isSet(){ if(blade_rf1_input_settings != nullptr && blade_rf1_input_settings->isSet()){ isObjectUpdated = true; break;} if(blade_rf2_input_settings != nullptr && blade_rf2_input_settings->isSet()){ isObjectUpdated = true; break;} if(blade_rf1_output_settings != nullptr && blade_rf1_output_settings->isSet()){ isObjectUpdated = true; break;} + if(blade_rf2_output_settings != nullptr && blade_rf2_output_settings->isSet()){ isObjectUpdated = true; break;} if(fcd_pro_settings != nullptr && fcd_pro_settings->isSet()){ isObjectUpdated = true; break;} if(fcd_pro_plus_settings != nullptr && fcd_pro_plus_settings->isSet()){ isObjectUpdated = true; break;} if(file_source_settings != nullptr && file_source_settings->isSet()){ isObjectUpdated = true; break;} diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h index 9ed650e38..047cd48e9 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h @@ -27,6 +27,7 @@ #include "SWGBladeRF1InputSettings.h" #include "SWGBladeRF1OutputSettings.h" #include "SWGBladeRF2InputSettings.h" +#include "SWGBladeRF2OutputSettings.h" #include "SWGFCDProPlusSettings.h" #include "SWGFCDProSettings.h" #include "SWGFileSourceSettings.h" @@ -83,6 +84,9 @@ public: SWGBladeRF1OutputSettings* getBladeRf1OutputSettings(); void setBladeRf1OutputSettings(SWGBladeRF1OutputSettings* blade_rf1_output_settings); + SWGBladeRF2OutputSettings* getBladeRf2OutputSettings(); + void setBladeRf2OutputSettings(SWGBladeRF2OutputSettings* blade_rf2_output_settings); + SWGFCDProSettings* getFcdProSettings(); void setFcdProSettings(SWGFCDProSettings* fcd_pro_settings); @@ -153,6 +157,9 @@ private: SWGBladeRF1OutputSettings* blade_rf1_output_settings; bool m_blade_rf1_output_settings_isSet; + SWGBladeRF2OutputSettings* blade_rf2_output_settings; + bool m_blade_rf2_output_settings_isSet; + SWGFCDProSettings* fcd_pro_settings; bool m_fcd_pro_settings_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h index 1ac604c66..a1526953b 100644 --- a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h +++ b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h @@ -34,6 +34,8 @@ #include "SWGBladeRF1OutputSettings.h" #include "SWGBladeRF2InputReport.h" #include "SWGBladeRF2InputSettings.h" +#include "SWGBladeRF2OutputReport.h" +#include "SWGBladeRF2OutputSettings.h" #include "SWGCWKeyerSettings.h" #include "SWGChannel.h" #include "SWGChannelListItem.h" @@ -182,6 +184,12 @@ namespace SWGSDRangel { if(QString("SWGBladeRF2InputSettings").compare(type) == 0) { return new SWGBladeRF2InputSettings(); } + if(QString("SWGBladeRF2OutputReport").compare(type) == 0) { + return new SWGBladeRF2OutputReport(); + } + if(QString("SWGBladeRF2OutputSettings").compare(type) == 0) { + return new SWGBladeRF2OutputSettings(); + } if(QString("SWGCWKeyerSettings").compare(type) == 0) { return new SWGCWKeyerSettings(); }