From 73a32a8cd73331f3dc670457b98c66237fe081de Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 2 Jan 2019 15:35:43 +0100 Subject: [PATCH] XTRX output --- devices/xtrx/devicextrxshared.cpp | 4 +- devices/xtrx/devicextrxshared.h | 3 +- plugins/samplesink/CMakeLists.txt | 5 + plugins/samplesink/xtrxoutput/CMakeLists.txt | 56 + plugins/samplesink/xtrxoutput/xtrxoutput.cpp | 1377 +++++++++++++++++ plugins/samplesink/xtrxoutput/xtrxoutput.h | 234 +++ .../samplesink/xtrxoutput/xtrxoutputgui.cpp | 513 ++++++ plugins/samplesink/xtrxoutput/xtrxoutputgui.h | 99 ++ .../samplesink/xtrxoutput/xtrxoutputgui.ui | 913 +++++++++++ .../xtrxoutput/xtrxoutputplugin.cpp | 127 ++ .../samplesink/xtrxoutput/xtrxoutputplugin.h | 53 + .../xtrxoutput/xtrxoutputsettings.cpp | 117 ++ .../xtrxoutput/xtrxoutputsettings.h | 58 + .../xtrxoutput/xtrxoutputthread.cpp | 333 ++++ .../samplesink/xtrxoutput/xtrxoutputthread.h | 82 + plugins/samplesource/xtrxinput/xtrxinput.cpp | 117 +- plugins/samplesource/xtrxinput/xtrxinput.h | 4 +- .../xtrxinput/xtrxinputplugin.cpp | 24 +- .../samplesource/xtrxinput/xtrxinputplugin.h | 1 - .../xtrxinput/xtrxinputthread.cpp | 2 - .../samplesource/xtrxinput/xtrxinputthread.h | 2 +- pluginssrv/samplesink/CMakeLists.txt | 5 + .../samplesink/xtrxoutput/CMakeLists.txt | 47 + sdrbase/resources/webapi/doc/html2/index.html | 98 +- .../webapi/doc/swagger/include/Xtrx.yaml | 66 +- .../resources/webapi/doc/swagger/swagger.yaml | 4 + .../sdrangel/api/swagger/include/Xtrx.yaml | 65 +- swagger/sdrangel/api/swagger/swagger.yaml | 4 + swagger/sdrangel/code/html2/index.html | 98 +- .../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 + .../code/qt5/client/SWGXtrxInputReport.cpp | 21 - .../code/qt5/client/SWGXtrxInputReport.h | 6 - .../code/qt5/client/SWGXtrxOutputReport.cpp | 190 +++ .../code/qt5/client/SWGXtrxOutputReport.h | 82 + .../code/qt5/client/SWGXtrxOutputSettings.cpp | 423 +++++ .../code/qt5/client/SWGXtrxOutputSettings.h | 149 ++ 40 files changed, 5321 insertions(+), 129 deletions(-) create mode 100644 plugins/samplesink/xtrxoutput/CMakeLists.txt create mode 100644 plugins/samplesink/xtrxoutput/xtrxoutput.cpp create mode 100644 plugins/samplesink/xtrxoutput/xtrxoutput.h create mode 100644 plugins/samplesink/xtrxoutput/xtrxoutputgui.cpp create mode 100644 plugins/samplesink/xtrxoutput/xtrxoutputgui.h create mode 100644 plugins/samplesink/xtrxoutput/xtrxoutputgui.ui create mode 100644 plugins/samplesink/xtrxoutput/xtrxoutputplugin.cpp create mode 100644 plugins/samplesink/xtrxoutput/xtrxoutputplugin.h create mode 100644 plugins/samplesink/xtrxoutput/xtrxoutputsettings.cpp create mode 100644 plugins/samplesink/xtrxoutput/xtrxoutputsettings.h create mode 100644 plugins/samplesink/xtrxoutput/xtrxoutputthread.cpp create mode 100644 plugins/samplesink/xtrxoutput/xtrxoutputthread.h create mode 100644 pluginssrv/samplesink/xtrxoutput/CMakeLists.txt create mode 100644 swagger/sdrangel/code/qt5/client/SWGXtrxOutputReport.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGXtrxOutputReport.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGXtrxOutputSettings.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGXtrxOutputSettings.h diff --git a/devices/xtrx/devicextrxshared.cpp b/devices/xtrx/devicextrxshared.cpp index fc3c93ae2..6057a9ff2 100644 --- a/devices/xtrx/devicextrxshared.cpp +++ b/devices/xtrx/devicextrxshared.cpp @@ -33,7 +33,9 @@ DeviceXTRXShared::DeviceXTRXShared() : m_sink(0), m_inputRate(0), m_outputRate(0), - m_masterRate(0) + m_masterRate(0), + m_thread(0), + m_threadWasRunning(false) {} DeviceXTRXShared::~DeviceXTRXShared() diff --git a/devices/xtrx/devicextrxshared.h b/devices/xtrx/devicextrxshared.h index 671b7c0d1..37dde9d2f 100644 --- a/devices/xtrx/devicextrxshared.h +++ b/devices/xtrx/devicextrxshared.h @@ -129,7 +129,6 @@ public: public: virtual void startWork() = 0; virtual void stopWork() = 0; - virtual void setDeviceSampleRate(int sampleRate) = 0; virtual bool isRunning() = 0; }; @@ -140,6 +139,8 @@ public: double m_inputRate; double m_outputRate; double m_masterRate; + ThreadInterface *m_thread; //!< holds the thread address if started else 0 + bool m_threadWasRunning; //!< flag to know if thread needs to be resumed after suspend static const float m_sampleFifoLengthInSeconds; static const int m_sampleFifoMinSize; diff --git a/plugins/samplesink/CMakeLists.txt b/plugins/samplesink/CMakeLists.txt index ecedfd0d6..fbc2060dc 100644 --- a/plugins/samplesink/CMakeLists.txt +++ b/plugins/samplesink/CMakeLists.txt @@ -33,6 +33,11 @@ if(SOAPYSDR_FOUND) add_subdirectory(soapysdroutput) endif() +find_package(LibXTRX) +if(LIBXTRX_FOUND) + add_subdirectory(xtrxoutput) +endif(LIBXTRX_FOUND) + if (BUILD_DEBIAN) add_subdirectory(bladerf1output) add_subdirectory(bladerf2output) diff --git a/plugins/samplesink/xtrxoutput/CMakeLists.txt b/plugins/samplesink/xtrxoutput/CMakeLists.txt new file mode 100644 index 000000000..8b8fe601a --- /dev/null +++ b/plugins/samplesink/xtrxoutput/CMakeLists.txt @@ -0,0 +1,56 @@ +project(xtrxoutput) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +set(xtrxoutput_SOURCES + xtrxoutputgui.cpp + xtrxoutput.cpp + xtrxoutputplugin.cpp + xtrxoutputsettings.cpp + xtrxoutputthread.cpp +) + +set(xtrxoutput_HEADERS + xtrxoutputgui.h + xtrxoutput.h + xtrxoutputplugin.h + xtrxoutputsettings.h + xtrxoutputthread.h +) + +set(xtrxoutput_FORMS + xtrxoutputgui.ui +) + +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${CMAKE_SOURCE_DIR}/devices + ${LIBXTRX_INCLUDE_DIRS} +) + +add_definitions(${QT_DEFINITIONS}) +add_definitions(-DQT_PLUGIN) +add_definitions(-DQT_SHARED) + +qt5_wrap_ui(xtrxoutput_FORMS_HEADERS ${xtrxoutput_FORMS}) + +add_library(outputxtrx SHARED + ${xtrxoutput_SOURCES} + ${xtrxoutput_HEADERS_MOC} + ${xtrxoutput_FORMS_HEADERS} +) + +target_link_libraries(outputxtrx + ${QT_LIBRARIES} + ${LIBXTRX_LIBRARIES} + sdrbase + sdrgui + swagger + xtrxdevice +) + +target_link_libraries(outputxtrx Qt5::Core Qt5::Widgets) + +install(TARGETS outputxtrx DESTINATION lib/plugins/samplesink) diff --git a/plugins/samplesink/xtrxoutput/xtrxoutput.cpp b/plugins/samplesink/xtrxoutput/xtrxoutput.cpp new file mode 100644 index 000000000..1df21031c --- /dev/null +++ b/plugins/samplesink/xtrxoutput/xtrxoutput.cpp @@ -0,0 +1,1377 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017, 2018 Edouard Griffiths, F4EXB // +// Copyright (C) 2017 Sergey Kostanbaev, Fairwaves Inc. // +// // +// 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 "xtrx_api.h" + +#include +#include +#include +#include + +#include "SWGDeviceSettings.h" +#include "SWGXtrxOutputSettings.h" +#include "SWGDeviceState.h" +#include "SWGDeviceReport.h" +#include "SWGXtrxOutputReport.h" + +#include "device/devicesourceapi.h" +#include "device/devicesinkapi.h" +#include "dsp/dspcommands.h" +#include "xtrxoutput.h" +#include "xtrxoutputthread.h" +#include "xtrx/devicextrxparam.h" +#include "xtrx/devicextrxshared.h" +#include "xtrx/devicextrx.h" + +MESSAGE_CLASS_DEFINITION(XTRXOutput::MsgConfigureXTRX, Message) +MESSAGE_CLASS_DEFINITION(XTRXOutput::MsgGetStreamInfo, Message) +MESSAGE_CLASS_DEFINITION(XTRXOutput::MsgGetDeviceInfo, Message) +MESSAGE_CLASS_DEFINITION(XTRXOutput::MsgReportStreamInfo, Message) +MESSAGE_CLASS_DEFINITION(XTRXOutput::MsgStartStop, Message) + +XTRXOutput::XTRXOutput(DeviceSinkAPI *deviceAPI) : + m_deviceAPI(deviceAPI), + m_settings(), + m_XTRXOutputThread(0), + m_deviceDescription("XTRXOutput"), + m_running(false) +{ + openDevice(); + + m_networkManager = new QNetworkAccessManager(); + connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); +} + +XTRXOutput::~XTRXOutput() +{ + disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); + delete m_networkManager; + + if (m_running) { + stop(); + } + + closeDevice(); +} + +void XTRXOutput::destroy() +{ + delete this; +} + +bool XTRXOutput::openDevice() +{ + m_sampleSourceFifo.resize(m_settings.m_devSampleRate/(1<<(m_settings.m_log2SoftInterp <= 4 ? m_settings.m_log2SoftInterp : 4))); + + // look for Tx buddies and get reference to the device object + if (m_deviceAPI->getSinkBuddies().size() > 0) // then sink + { + qDebug("XTRXOutput::openDevice: look in Tx buddies"); + + DeviceSinkAPI *sinkBuddy = m_deviceAPI->getSinkBuddies()[0]; + DeviceXTRXShared *deviceXTRXShared = (DeviceXTRXShared*) sinkBuddy->getBuddySharedPtr(); + + if (deviceXTRXShared == 0) + { + qCritical("XTRXOutput::openDevice: the sink buddy shared pointer is null"); + return false; + } + + DeviceXTRX *device = deviceXTRXShared->m_dev; + + if (device == 0) + { + qCritical("XTRXOutput::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) // look source sibling first + { + qDebug("XTRXOutput::openDevice: look in Rx buddies"); + + DeviceSourceAPI *sourceBuddy = m_deviceAPI->getSourceBuddies()[0]; + DeviceXTRXShared *deviceXTRXShared = (DeviceXTRXShared*) sourceBuddy->getBuddySharedPtr(); + + if (deviceXTRXShared == 0) + { + qCritical("XTRXOutput::openDevice: the source buddy shared pointer is null"); + return false; + } + + DeviceXTRX *device = deviceXTRXShared->m_dev; + + if (device == 0) + { + qCritical("XTRXOutput::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("XTRXOutput::openDevice: open device here"); + + m_deviceShared.m_dev = new DeviceXTRX(); + char serial[256]; + strcpy(serial, qPrintable(m_deviceAPI->getSampleSinkSerial())); + + if (!m_deviceShared.m_dev->open(serial)) + { + qCritical("XTRXOutput::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 XTRXOutput::closeDevice() +{ + if (m_deviceShared.m_dev == 0) { // was never open + return; + } + + if (m_running) { + stop(); + } + + if (m_XTRXOutputThread) { // 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 XTRXOutput::init() +{ + applySettings(m_settings, true, false); +} + +XTRXOutputThread *XTRXOutput::findThread() +{ + if (m_XTRXOutputThread == 0) // this does not own the thread + { + XTRXOutputThread *xtrxOutputThread = 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) + { + XTRXOutput *buddySink = ((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_sink; + + if (buddySink) + { + xtrxOutputThread = buddySink->getThread(); + + if (xtrxOutputThread) { + break; + } + } + } + + return xtrxOutputThread; + } + else + { + return m_XTRXOutputThread; // own thread + } +} + +void XTRXOutput::moveThreadToBuddy() +{ + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator it = sinkBuddies.begin(); + + for (; it != sinkBuddies.end(); ++it) + { + XTRXOutput *buddySink = ((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_sink; + + if (buddySink) + { + buddySink->setThread(m_XTRXOutputThread); + m_XTRXOutputThread = 0; // zero for others + } + } +} + +bool XTRXOutput::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 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 another channel (one is already streaming). + // + // The XTRX support library lets you work in two possible modes: + // - Single Output (SO) with only one channel streaming. This can be channel 0 or 1 (channels can be swapped - unlike with BladeRF2). + // - Multiple Output (MO) with two channels streaming using interleaved samples. It MUST be in this configuration if both channels are + // streaming. + // + // It manages the transition form SO where only one channel is running to the Multiple Input (MO) if the both channels are requested. + // To perform the transition it stops the thread, deletes it and creates a new one. + // It marks the thread as needing start. + // + // If there is no thread allocated it means we are in SO mode and it creates a new one with the requested channel. + // 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 || !m_deviceShared.m_dev->getDevice()) + { + qDebug("XTRXOutput::start: no device object"); + return false; + } + + int requestedChannel = m_deviceAPI->getItemIndex(); + XTRXOutputThread *xtrxOutputThread = findThread(); + bool needsStart = false; + + if (xtrxOutputThread) // if thread is already allocated + { + qDebug("XTRXOutput::start: thread is already allocated"); + + unsigned int nbOriginalChannels = xtrxOutputThread->getNbChannels(); + + // if one channel is already allocated it must be the other one so we'll end up with both channels + // thus we expand by deleting and re-creating the thread + if (nbOriginalChannels != 0) + { + qDebug("XTRXOutput::start: expand channels. Re-allocate thread and take ownership"); + + SampleSourceFifo **fifos = new SampleSourceFifo*[2]; + unsigned int *log2Interps = new unsigned int[2]; + + for (int i = 0; i < 2; i++) // save original FIFO references and data + { + fifos[i] = xtrxOutputThread->getFifo(i); + log2Interps[i] = xtrxOutputThread->getLog2Interpolation(i); + } + + xtrxOutputThread->stopWork(); + delete xtrxOutputThread; + xtrxOutputThread = new XTRXOutputThread(m_deviceShared.m_dev->getDevice(), 2); // MO mode (2 channels) + m_XTRXOutputThread = xtrxOutputThread; // take ownership + m_deviceShared.m_thread = xtrxOutputThread; + + for (int i = 0; i < 2; i++) // restore original FIFO references + { + xtrxOutputThread->setFifo(i, fifos[i]); + xtrxOutputThread->setLog2Interpolation(i, log2Interps[i]); + } + + // remove old thread address from buddies (reset in all buddies). The address being held only in the owning source. + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator it = sinkBuddies.begin(); + + for (; it != sinkBuddies.end(); ++it) + { + ((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_sink->setThread(0); + ((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_thread = 0; + } + + // was used as temporary storage: + delete[] fifos; + delete[] log2Interps; + + needsStart = true; + } + else + { + qDebug("XTRXOutput::start: keep buddy thread"); + } + } + else // first allocation + { + qDebug("XTRXOutput::start: allocate thread and take ownership"); + xtrxOutputThread = new XTRXOutputThread(m_deviceShared.m_dev->getDevice(), 1, requestedChannel); + m_XTRXOutputThread = xtrxOutputThread; // take ownership + m_deviceShared.m_thread = xtrxOutputThread; + needsStart = true; + } + + xtrxOutputThread->setFifo(requestedChannel, &m_sampleSourceFifo); + xtrxOutputThread->setLog2Interpolation(requestedChannel, m_settings.m_log2SoftInterp); + + if (needsStart) + { + qDebug("XTRXOutput::start: (re)start thread"); + xtrxOutputThread->startWork(); + } + + applySettings(m_settings, true); + + qDebug("XTRXOutput::start: started"); + m_running = true; + + return true; +} + +void XTRXOutput::stop() +{ + // This stop method is responsible for managing the thread when the streaming of a Rx 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. + // + // If the thread is currently managing both channels (MO mode) then we are removing one channel. Thus we must + // transition from MO to SO. This transition is handled by stopping the thread, deleting it and creating a new one + // managing a single channel. + + if (!m_running) { + return; + } + + int removedChannel = m_deviceAPI->getItemIndex(); // channel to remove + int requestedChannel = removedChannel ^ 1; // channel to keep (opposite channel) + XTRXOutputThread *xtrxOutputThread = findThread(); + + if (xtrxOutputThread == 0) { // no thread allocated + return; + } + + int nbOriginalChannels = xtrxOutputThread->getNbChannels(); + + if (nbOriginalChannels == 1) // SO mode => just stop and delete the thread + { + qDebug("XTRXOutput::stop: SO mode. Just stop and delete the thread"); + xtrxOutputThread->stopWork(); + delete xtrxOutputThread; + m_XTRXOutputThread = 0; + m_deviceShared.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) + { + ((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_sink->setThread(0); + ((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_thread = 0; + } + } + else if (nbOriginalChannels == 2) // Reduce from MO to SO by deleting and re-creating the thread + { + qDebug("XTRXOutput::stop: MO mode. Reduce by deleting and re-creating the thread"); + xtrxOutputThread->stopWork(); + delete xtrxOutputThread; + xtrxOutputThread = new XTRXOutputThread(m_deviceShared.m_dev->getDevice(), 1, requestedChannel); + m_XTRXOutputThread = xtrxOutputThread; // take ownership + m_deviceShared.m_thread = xtrxOutputThread; + + xtrxOutputThread->setFifo(requestedChannel, &m_sampleSourceFifo); + xtrxOutputThread->setLog2Interpolation(requestedChannel, m_settings.m_log2SoftInterp); + + // remove old thread address from buddies (reset in all buddies). The address being held only in the owning source. + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator it = sinkBuddies.begin(); + + for (; it != sinkBuddies.end(); ++it) + { + ((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_sink->setThread(0); + ((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_thread = 0; + } + + xtrxOutputThread->startWork(); + applySettings(m_settings, true); + } + + m_running = false; +} + +void XTRXOutput::suspendRxThread() +{ + const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); + std::vector::const_iterator itSource = sourceBuddies.begin(); + + qDebug("XTRXOutput::suspendRxThread (%lu)", sourceBuddies.size()); + + for (; itSource != sourceBuddies.end(); ++itSource) + { + DeviceXTRXShared *buddySharedPtr = (DeviceXTRXShared *) (*itSource)->getBuddySharedPtr(); + + if (buddySharedPtr->m_thread && buddySharedPtr->m_thread->isRunning()) + { + buddySharedPtr->m_thread->stopWork(); + buddySharedPtr->m_threadWasRunning = true; + } + else + { + buddySharedPtr->m_threadWasRunning = false; + } + } +} + +void XTRXOutput::resumeRxThread() +{ + const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); + std::vector::const_iterator itSource = sourceBuddies.begin(); + + qDebug("XTRXOutput::resumeRxThread (%lu)", sourceBuddies.size()); + + for (; itSource != sourceBuddies.end(); ++itSource) + { + DeviceXTRXShared *buddySharedPtr = (DeviceXTRXShared *) (*itSource)->getBuddySharedPtr(); + + if (buddySharedPtr->m_threadWasRunning) { + buddySharedPtr->m_thread->startWork(); + } + } +} + +QByteArray XTRXOutput::serialize() const +{ + return m_settings.serialize(); +} + +bool XTRXOutput::deserialize(const QByteArray& data) +{ + bool success = true; + + if (!m_settings.deserialize(data)) + { + m_settings.resetToDefaults(); + success = false; + } + + MsgConfigureXTRX* message = MsgConfigureXTRX::create(m_settings, true); + m_inputMessageQueue.push(message); + + if (m_guiMessageQueue) + { + MsgConfigureXTRX* messageToGUI = MsgConfigureXTRX::create(m_settings, true); + m_guiMessageQueue->push(messageToGUI); + } + + return success; +} + +const QString& XTRXOutput::getDeviceDescription() const +{ + return m_deviceDescription; +} + +int XTRXOutput::getSampleRate() const +{ + double rate = m_settings.m_devSampleRate; + return (int)((rate / (1<push(messageToGUI); + } +} + +std::size_t XTRXOutput::getChannelIndex() +{ + return m_deviceShared.m_channel; +} + +void XTRXOutput::getLORange(float& minF, float& maxF, float& stepF) const +{ + minF = 29e6; + maxF = 3840e6; + stepF = 10; + qDebug("XTRXInput::getLORange: min: %f max: %f step: %f", + minF, maxF, stepF); +} + +void XTRXOutput::getSRRange(float& minF, float& maxF, float& stepF) const +{ + minF = 100e3; + maxF = 120e6; + stepF = 10; + qDebug("XTRXInput::getSRRange: min: %f max: %f step: %f", + minF, maxF, stepF); +} + +void XTRXOutput::getLPRange(float& minF, float& maxF, float& stepF) const +{ + minF = 500e3; + maxF = 130e6; + stepF = 10; + qDebug("XTRXInput::getLPRange: min: %f max: %f step: %f", + minF, maxF, stepF); +} + +bool XTRXOutput::handleMessage(const Message& message) +{ + if (MsgConfigureXTRX::match(message)) + { + MsgConfigureXTRX& conf = (MsgConfigureXTRX&) message; + qDebug() << "XTRXOutput::handleMessage: MsgConfigureXTRX"; + + if (!applySettings(conf.getSettings(), conf.getForce())) + { + qDebug("XTRXOutput::handleMessage config error"); + } + + return true; + } + else if (DeviceXTRXShared::MsgReportBuddyChange::match(message)) + { + DeviceXTRXShared::MsgReportBuddyChange& report = (DeviceXTRXShared::MsgReportBuddyChange&) message; + + if (!report.getRxElseTx()) + { + m_settings.m_devSampleRate = report.getDevSampleRate(); + m_settings.m_log2HardInterp = report.getLog2HardDecimInterp(); + m_settings.m_centerFrequency = report.getCenterFrequency(); + } + else + { + m_settings.m_devSampleRate = m_deviceShared.m_inputRate; + m_settings.m_log2HardInterp = log2(m_deviceShared.m_masterRate / m_deviceShared.m_inputRate / 4); + + qDebug() << "XTRXOutput::handleMessage: MsgReportBuddyChange:" + << " host_Hz: " << m_deviceShared.m_inputRate + << " rf_Hz: " << m_deviceShared.m_masterRate / 4 + << " m_log2HardDecim: " << m_settings.m_log2HardInterp; + } + + if (m_settings.m_ncoEnable) // need to reset NCO after sample rate change + { + applySettings(m_settings, true, true); + } + + int ncoShift = m_settings.m_ncoEnable ? m_settings.m_ncoFrequency : 0; + + DSPSignalNotification *notif = new DSPSignalNotification( + m_settings.m_devSampleRate/(1<getDeviceEngineInputMessageQueue()->push(notif); + + if (getMessageQueueToGUI()) + { + DeviceXTRXShared::MsgReportBuddyChange *reportToGUI = DeviceXTRXShared::MsgReportBuddyChange::create( + m_settings.m_devSampleRate, m_settings.m_log2HardInterp, m_settings.m_centerFrequency, true); + getMessageQueueToGUI()->push(reportToGUI); + } + + return true; + } + else if (DeviceXTRXShared::MsgReportClockSourceChange::match(message)) + { + DeviceXTRXShared::MsgReportClockSourceChange& report = (DeviceXTRXShared::MsgReportClockSourceChange&) message; + + m_settings.m_extClock = report.getExtClock(); + m_settings.m_extClockFreq = report.getExtClockFeq(); + + if (getMessageQueueToGUI()) + { + DeviceXTRXShared::MsgReportClockSourceChange *reportToGUI = DeviceXTRXShared::MsgReportClockSourceChange::create( + m_settings.m_extClock, m_settings.m_extClockFreq); + getMessageQueueToGUI()->push(reportToGUI); + } + + return true; + } + else if (MsgGetStreamInfo::match(message)) + { + if (m_deviceAPI->getSampleSinkGUIMessageQueue()) + { + uint64_t fifolevel = 0; + + if (m_deviceShared.m_dev && m_deviceShared.m_dev->getDevice()) { + xtrx_val_get(m_deviceShared.m_dev->getDevice(), XTRX_TX, XTRX_CH_AB, XTRX_PERF_LLFIFO, &fifolevel); + } + + MsgReportStreamInfo *report = MsgReportStreamInfo::create( + true, + true, + fifolevel, + 65536); + + if (m_deviceAPI->getSampleSinkGUIMessageQueue()) { + m_deviceAPI->getSampleSinkGUIMessageQueue()->push(report); + } + } + + return true; + } + else if (MsgGetDeviceInfo::match(message)) + { + double board_temp = 0.0; + bool gps_locked = false; + + if (!m_deviceShared.m_dev->getDevice() || ((board_temp = m_deviceShared.get_board_temperature() / 256.0) == 0.0)) { + qDebug("XTRXOutput::handleMessage: MsgGetDeviceInfo: cannot get board temperature"); + } + + if (!m_deviceShared.m_dev->getDevice()) { + qDebug("XTRXOutput::handleMessage: MsgGetDeviceInfo: cannot get GPS lock status"); + } else { + gps_locked = m_deviceShared.get_gps_status(); + } + + // send to oneself + if (m_deviceAPI->getSampleSinkGUIMessageQueue()) + { + DeviceXTRXShared::MsgReportDeviceInfo *report = DeviceXTRXShared::MsgReportDeviceInfo::create(board_temp, gps_locked); + m_deviceAPI->getSampleSinkGUIMessageQueue()->push(report); + } + + // send to sink buddies + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator itSink = sinkBuddies.begin(); + + for (; itSink != sinkBuddies.end(); ++itSink) + { + if ((*itSink)->getSampleSinkGUIMessageQueue()) + { + DeviceXTRXShared::MsgReportDeviceInfo *report = DeviceXTRXShared::MsgReportDeviceInfo::create(board_temp, gps_locked); + (*itSink)->getSampleSinkGUIMessageQueue()->push(report); + } + } + + // send to source buddies + const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); + std::vector::const_iterator itSource = sourceBuddies.begin(); + + for (; itSource != sourceBuddies.end(); ++itSource) + { + if ((*itSource)->getSampleSourceGUIMessageQueue()) + { + DeviceXTRXShared::MsgReportDeviceInfo *report = DeviceXTRXShared::MsgReportDeviceInfo::create(board_temp, gps_locked); + (*itSource)->getSampleSourceGUIMessageQueue()->push(report); + } + } + + return true; + } + else if (MsgStartStop::match(message)) + { + MsgStartStop& cmd = (MsgStartStop&) message; + qDebug() << "XTRXOutput::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 XTRXOutput::applySettings(const XTRXOutputSettings& settings, bool force, bool forceNCOFrequency) +{ + int requestedChannel = m_deviceAPI->getItemIndex(); + XTRXOutputThread *outputThread = findThread(); + QList reverseAPIKeys; + + bool forwardChangeOwnDSP = false; + bool forwardChangeTxDSP = false; + bool forwardChangeAllDSP = false; + bool forwardClockSource = false; + bool txThreadWasRunning = false; + bool doLPCalibration = false; + bool doChangeSampleRate = false; + bool doChangeFreq = false; + + // apply settings + + if ((m_settings.m_pwrmode != settings.m_pwrmode)) + { + reverseAPIKeys.append("pwrmode"); + + if (m_deviceShared.m_dev->getDevice() != 0) + { + if (xtrx_val_set(m_deviceShared.m_dev->getDevice(), + XTRX_TRX, + m_deviceShared.m_channel == 0 ? XTRX_CH_A : XTRX_CH_B, + XTRX_LMS7_PWR_MODE, + settings.m_pwrmode) < 0) { + qCritical("XTRXOutput::applySettings: could not set power mode %d", settings.m_pwrmode); + } + } + } + + if ((m_settings.m_extClock != settings.m_extClock) || force) { + reverseAPIKeys.append("extClock"); + } + if ((m_settings.m_extClockFreq != settings.m_extClockFreq) || force) { + reverseAPIKeys.append("extClockFreq"); + } + + if ((m_settings.m_extClock != settings.m_extClock) + || (settings.m_extClock && (m_settings.m_extClockFreq != settings.m_extClockFreq)) || force) + { + if (m_deviceShared.m_dev->getDevice() != 0) + { + xtrx_set_ref_clk(m_deviceShared.m_dev->getDevice(), + (settings.m_extClock) ? settings.m_extClockFreq : 0, + (settings.m_extClock) ? XTRX_CLKSRC_EXT : XTRX_CLKSRC_INT); + { + forwardClockSource = true; + doChangeSampleRate = true; + doChangeFreq = true; + qDebug("XTRXOutput::applySettings: clock set to %s (Ext: %d Hz)", + settings.m_extClock ? "external" : "internal", + settings.m_extClockFreq); + } + } + } + + if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force) { + reverseAPIKeys.append("devSampleRate"); + } + if ((m_settings.m_log2HardInterp != settings.m_log2HardInterp) || force) { + reverseAPIKeys.append("log2HardInterp"); + } + + if ((m_settings.m_devSampleRate != settings.m_devSampleRate) + || (m_settings.m_log2HardInterp != settings.m_log2HardInterp) || force) + { + forwardChangeAllDSP = true; //m_settings.m_devSampleRate != settings.m_devSampleRate; + + if (m_deviceShared.m_dev->getDevice() != 0) { + doChangeSampleRate = true; + } + } + + if ((m_settings.m_gain != settings.m_gain) || force) + { + reverseAPIKeys.append("gain"); + + if (m_deviceShared.m_dev->getDevice() != 0) + { + if (xtrx_set_gain(m_deviceShared.m_dev->getDevice(), + m_deviceShared.m_channel == 0 ? XTRX_CH_A : XTRX_CH_B, + XTRX_TX_PAD_GAIN, + settings.m_gain, + 0) < 0) { + qDebug("XTRXOutput::applySettings: xtrx_set_gain(PAD) failed"); + } else { + qDebug() << "XTRXOutput::applySettings: Gain (PAD) set to " << settings.m_gain; + } + } + } + + if ((m_settings.m_lpfBW != settings.m_lpfBW) || force) + { + reverseAPIKeys.append("lpfBW"); + + if (m_deviceShared.m_dev->getDevice() != 0) { + doLPCalibration = true; + } + } + +#if 0 + if ((m_settings.m_lpfFIRBW != settings.m_lpfFIRBW) || + (m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) || force) + { + if (m_deviceShared.m_deviceParams->getDevice() != 0 && m_channelAcquired) + { + if (LMS_SetGFIRLPF(m_deviceShared.m_deviceParams->getDevice(), + LMS_CH_RX, + m_deviceShared.m_channel, + settings.m_lpfFIREnable, + settings.m_lpfFIRBW) < 0) + { + qCritical("XTRXInput::applySettings: could %s and set LPF FIR to %f Hz", + settings.m_lpfFIREnable ? "enable" : "disable", + settings.m_lpfFIRBW); + } + else + { + //doCalibration = true; + qDebug("XTRXInput::applySettings: %sd and set LPF FIR to %f Hz", + settings.m_lpfFIREnable ? "enable" : "disable", + settings.m_lpfFIRBW); + } + } + } +#endif + + if ((m_settings.m_log2SoftInterp != settings.m_log2SoftInterp) || force) + { + reverseAPIKeys.append("log2SoftInterp"); + forwardChangeOwnDSP = true; + + if (outputThread != 0) + { + outputThread->setLog2Interpolation(requestedChannel, settings.m_log2SoftInterp); + qDebug() << "XTRXOutput::applySettings: set soft interpolation to " << (1<getDevice() != 0) + { + if (xtrx_set_antenna(m_deviceShared.m_dev->getDevice(), settings.m_antennaPath) < 0) { + qCritical("XTRXOutput::applySettings: could not set antenna path to %d", (int) settings.m_antennaPath); + } else { + qDebug("XTRXOutput::applySettings: set antenna path to %d", (int) settings.m_antennaPath); + } + } + } + + if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) + { + reverseAPIKeys.append("centerFrequency"); + doChangeFreq = true; + } + + if ((m_settings.m_ncoFrequency != settings.m_ncoFrequency) || force) { + reverseAPIKeys.append("ncoFrequency"); + } + if ((m_settings.m_ncoEnable != settings.m_ncoEnable) || force) { + reverseAPIKeys.append("ncoEnable"); + } + + if ((m_settings.m_ncoFrequency != settings.m_ncoFrequency) + || (m_settings.m_ncoEnable != settings.m_ncoEnable) || force) + { + forceNCOFrequency = true; + } + + if (settings.m_useReverseAPI) + { + bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) || + (m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) || + (m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) || + (m_settings.m_reverseAPIDeviceIndex != settings.m_reverseAPIDeviceIndex); + webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); + } + + m_settings = settings; + + if (doChangeSampleRate) + { + XTRXOutputThread *txThread = findThread(); + + if (txThread && txThread->isRunning()) + { + txThread->stopWork(); + txThreadWasRunning = true; + } + + suspendRxThread(); + + double master = (settings.m_log2HardInterp == 0) ? 0 : (settings.m_devSampleRate * 4 * (1 << settings.m_log2HardInterp)); + + if (m_deviceShared.set_samplerate(settings.m_devSampleRate, + master, //(settings.m_devSampleRate<startWork(); + } + } + + if (doLPCalibration) + { + if (xtrx_tune_tx_bandwidth(m_deviceShared.m_dev->getDevice(), + m_deviceShared.m_channel == 0 ? XTRX_CH_A : XTRX_CH_B, + m_settings.m_lpfBW, + 0) < 0) { + qCritical("XTRXOutput::applySettings: could not set LPF to %f Hz", m_settings.m_lpfBW); + } else { + qDebug("XTRXOutput::applySettings: LPF set to %f Hz", m_settings.m_lpfBW); + } + } + + if (doChangeFreq) + { + forwardChangeTxDSP = true; + + if (m_deviceShared.m_dev->getDevice() != 0) + { + if (xtrx_tune(m_deviceShared.m_dev->getDevice(), + XTRX_TUNE_TX_FDD, + settings.m_centerFrequency, + 0) < 0) { + qCritical("XTRXOutput::applySettings: could not set frequency to %lu", settings.m_centerFrequency); + } else { + //doCalibration = true; + qDebug("XTRXOutput::applySettings: frequency set to %lu", settings.m_centerFrequency); + } + } + } + + if (forceNCOFrequency) + { + if (m_deviceShared.m_dev->getDevice() != 0) + { + if (xtrx_tune_ex(m_deviceShared.m_dev->getDevice(), + XTRX_TUNE_BB_TX, + m_deviceShared.m_channel == 0 ? XTRX_CH_A : XTRX_CH_B, + (settings.m_ncoEnable) ? settings.m_ncoFrequency : 0, + NULL) < 0) + { + qCritical("XTRXOutput::applySettings: could not %s and set NCO to %d Hz", + settings.m_ncoEnable ? "enable" : "disable", + settings.m_ncoFrequency); + } + else + { + forwardChangeOwnDSP = true; + qDebug("XTRXOutput::applySettings: %sd and set NCO to %d Hz", + settings.m_ncoEnable ? "enable" : "disable", + settings.m_ncoFrequency); + } + } + } + + // forward changes to buddies or oneself + + if (forwardChangeAllDSP) + { + qDebug("XTRXOutput::applySettings: forward change to all buddies"); + + int ncoShift = m_settings.m_ncoEnable ? m_settings.m_ncoFrequency : 0; + + // send to self first + DSPSignalNotification *notif = new DSPSignalNotification( + m_settings.m_devSampleRate/(1<getDeviceEngineInputMessageQueue()->push(notif); + + // send to source buddies + const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); + std::vector::const_iterator itSource = sourceBuddies.begin(); + + for (; itSource != sourceBuddies.end(); ++itSource) + { + DeviceXTRXShared::MsgReportBuddyChange *report = DeviceXTRXShared::MsgReportBuddyChange::create( + m_settings.m_devSampleRate, m_settings.m_log2HardInterp, m_settings.m_centerFrequency, true); + (*itSource)->getSampleSourceInputMessageQueue()->push(report); + } + + // send to sink buddies + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator itSink = sinkBuddies.begin(); + + for (; itSink != sinkBuddies.end(); ++itSink) + { + DeviceXTRXShared::MsgReportBuddyChange *report = DeviceXTRXShared::MsgReportBuddyChange::create( + m_settings.m_devSampleRate, m_settings.m_log2HardInterp, m_settings.m_centerFrequency, true); + (*itSink)->getSampleSinkInputMessageQueue()->push(report); + } + } + else if (forwardChangeTxDSP) + { + qDebug("XTRXOutput::applySettings: forward change to Tx buddies"); + + int sampleRate = m_settings.m_devSampleRate/(1<getDeviceEngineInputMessageQueue()->push(notif); + + // send to sink buddies + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator itSink = sinkBuddies.begin(); + + for (; itSink != sinkBuddies.end(); ++itSink) + { + DeviceXTRXShared::MsgReportBuddyChange *report = DeviceXTRXShared::MsgReportBuddyChange::create( + m_settings.m_devSampleRate, m_settings.m_log2HardInterp, m_settings.m_centerFrequency, true); + (*itSink)->getSampleSinkInputMessageQueue()->push(report); + } + } + else if (forwardChangeOwnDSP) + { + qDebug("XTRXOutput::applySettings: forward change to self only"); + + int sampleRate = m_settings.m_devSampleRate/(1<getDeviceEngineInputMessageQueue()->push(notif); + } + + if (forwardClockSource) + { + // send to source buddies + const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); + std::vector::const_iterator itSource = sourceBuddies.begin(); + + for (; itSource != sourceBuddies.end(); ++itSource) + { + DeviceXTRXShared::MsgReportClockSourceChange *report = DeviceXTRXShared::MsgReportClockSourceChange::create( + m_settings.m_extClock, m_settings.m_extClockFreq); + (*itSource)->getSampleSourceInputMessageQueue()->push(report); + } + + // send to sink buddies + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator itSink = sinkBuddies.begin(); + + for (; itSink != sinkBuddies.end(); ++itSink) + { + DeviceXTRXShared::MsgReportClockSourceChange *report = DeviceXTRXShared::MsgReportClockSourceChange::create( + m_settings.m_extClock, m_settings.m_extClockFreq); + (*itSink)->getSampleSinkInputMessageQueue()->push(report); + } + } + + qDebug() << "XTRXInput::applySettings: center freq: " << m_settings.m_centerFrequency << " Hz" + << " device stream sample rate: " << m_settings.m_devSampleRate << "S/s" + << " sample rate with soft interpolation: " << m_settings.m_devSampleRate/(1<init(); + webapiFormatDeviceSettings(response, m_settings); + return 200; +} + +int XTRXOutput::webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage) +{ + (void) errorMessage; + XTRXOutputSettings settings = m_settings; + + if (deviceSettingsKeys.contains("centerFrequency")) { + settings.m_centerFrequency = response.getXtrxOutputSettings()->getCenterFrequency(); + } + if (deviceSettingsKeys.contains("devSampleRate")) { + settings.m_devSampleRate = response.getXtrxOutputSettings()->getDevSampleRate(); + } + if (deviceSettingsKeys.contains("log2HardInterp")) { + settings.m_log2HardInterp = response.getXtrxOutputSettings()->getLog2HardInterp(); + } + if (deviceSettingsKeys.contains("log2SoftInterp")) { + settings.m_log2SoftInterp = response.getXtrxOutputSettings()->getLog2SoftInterp(); + } + if (deviceSettingsKeys.contains("lpfBW")) { + settings.m_lpfBW = response.getXtrxOutputSettings()->getLpfBw(); + } + if (deviceSettingsKeys.contains("gain")) { + settings.m_gain = response.getXtrxOutputSettings()->getGain(); + } + if (deviceSettingsKeys.contains("ncoEnable")) { + settings.m_ncoEnable = response.getXtrxOutputSettings()->getNcoEnable() != 0; + } + if (deviceSettingsKeys.contains("ncoFrequency")) { + settings.m_ncoFrequency = response.getXtrxOutputSettings()->getNcoFrequency(); + } + if (deviceSettingsKeys.contains("antennaPath")) { + settings.m_antennaPath = (xtrx_antenna_t) response.getXtrxOutputSettings()->getAntennaPath(); + } + if (deviceSettingsKeys.contains("extClock")) { + settings.m_extClock = response.getXtrxOutputSettings()->getExtClock() != 0; + } + if (deviceSettingsKeys.contains("extClockFreq")) { + settings.m_extClockFreq = response.getXtrxOutputSettings()->getExtClockFreq(); + } + if (deviceSettingsKeys.contains("pwrmode")) { + settings.m_pwrmode = response.getXtrxOutputSettings()->getPwrmode(); + } + if (deviceSettingsKeys.contains("useReverseAPI")) { + settings.m_useReverseAPI = response.getXtrxOutputSettings()->getUseReverseApi() != 0; + } + if (deviceSettingsKeys.contains("reverseAPIAddress")) { + settings.m_reverseAPIAddress = *response.getXtrxOutputSettings()->getReverseApiAddress() != 0; + } + if (deviceSettingsKeys.contains("reverseAPIPort")) { + settings.m_reverseAPIPort = response.getXtrxOutputSettings()->getReverseApiPort(); + } + if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) { + settings.m_reverseAPIDeviceIndex = response.getXtrxOutputSettings()->getReverseApiDeviceIndex(); + } + + MsgConfigureXTRX *msg = MsgConfigureXTRX::create(settings, force); + m_inputMessageQueue.push(msg); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigureXTRX *msgToGUI = MsgConfigureXTRX::create(settings, force); + m_guiMessageQueue->push(msgToGUI); + } + + webapiFormatDeviceSettings(response, settings); + return 200; +} + +void XTRXOutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const XTRXOutputSettings& settings) +{ + response.getXtrxOutputSettings()->setCenterFrequency(settings.m_centerFrequency); + response.getXtrxOutputSettings()->setDevSampleRate(settings.m_devSampleRate); + response.getXtrxOutputSettings()->setLog2HardInterp(settings.m_log2HardInterp); + response.getXtrxOutputSettings()->setLog2SoftInterp(settings.m_log2SoftInterp); + response.getXtrxOutputSettings()->setLpfBw(settings.m_lpfBW); + response.getXtrxOutputSettings()->setGain(settings.m_gain); + response.getXtrxOutputSettings()->setNcoEnable(settings.m_ncoEnable ? 1 : 0); + response.getXtrxOutputSettings()->setNcoFrequency(settings.m_ncoFrequency); + response.getXtrxOutputSettings()->setAntennaPath((int) settings.m_antennaPath); + response.getXtrxOutputSettings()->setExtClock(settings.m_extClock ? 1 : 0); + response.getXtrxOutputSettings()->setExtClockFreq(settings.m_extClockFreq); + response.getXtrxOutputSettings()->setPwrmode(settings.m_pwrmode); + response.getXtrxOutputSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); + + if (response.getXtrxOutputSettings()->getReverseApiAddress()) { + *response.getXtrxOutputSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress; + } else { + response.getXtrxOutputSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress)); + } + + response.getXtrxOutputSettings()->setReverseApiPort(settings.m_reverseAPIPort); + response.getXtrxOutputSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex); +} + +int XTRXOutput::webapiReportGet( + SWGSDRangel::SWGDeviceReport& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setXtrxOutputReport(new SWGSDRangel::SWGXtrxOutputReport()); + response.getXtrxInputReport()->init(); + webapiFormatDeviceReport(response); + return 200; +} + +int XTRXOutput::webapiRunGet( + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage) +{ + (void) errorMessage; + m_deviceAPI->getDeviceEngineStateStr(*response.getState()); + return 200; +} + +int XTRXOutput::webapiRun( + bool run, + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage) +{ + (void) errorMessage; + 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; +} + +void XTRXOutput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response) +{ + int ret; + bool success = false; + double temp = 0.0; + bool gpsStatus = false; + uint64_t fifolevel = 0; + uint32_t fifosize = 1<<16; + + if (m_deviceShared.m_dev && m_deviceShared.m_dev->getDevice()) + { + ret = xtrx_val_get(m_deviceShared.m_dev->getDevice(), + XTRX_TX, XTRX_CH_AB, XTRX_PERF_LLFIFO, &fifolevel); + success = (ret >= 0); + temp = m_deviceShared.get_board_temperature() / 256.0; + gpsStatus = m_deviceShared.get_gps_status(); + } + + response.getXtrxOutputReport()->setSuccess(success ? 1 : 0); + response.getXtrxOutputReport()->setFifoSize(fifosize); + response.getXtrxOutputReport()->setFifoFill(fifolevel); + response.getXtrxOutputReport()->setTemperature(temp); + response.getXtrxOutputReport()->setGpsLock(gpsStatus ? 1 : 0); +} + +void XTRXOutput::webapiReverseSendSettings(QList& deviceSettingsKeys, const XTRXOutputSettings& settings, bool force) +{ + SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings(); + swgDeviceSettings->setTx(1); + swgDeviceSettings->setDeviceHwType(new QString("XTRX")); + swgDeviceSettings->setXtrxOutputSettings(new SWGSDRangel::SWGXtrxOutputSettings()); + SWGSDRangel::SWGXtrxOutputSettings *swgXtrxOutputSettings = swgDeviceSettings->getXtrxOutputSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (deviceSettingsKeys.contains("centerFrequency") || force) { + swgXtrxOutputSettings->setCenterFrequency(settings.m_centerFrequency); + } + if (deviceSettingsKeys.contains("devSampleRate") || force) { + swgXtrxOutputSettings->setDevSampleRate(settings.m_devSampleRate); + } + if (deviceSettingsKeys.contains("log2HardInterp") || force) { + swgXtrxOutputSettings->setLog2HardInterp(settings.m_log2HardInterp); + } + if (deviceSettingsKeys.contains("log2SoftInterp") || force) { + swgXtrxOutputSettings->setLog2SoftInterp(settings.m_log2SoftInterp); + } + if (deviceSettingsKeys.contains("ncoEnable") || force) { + swgXtrxOutputSettings->setNcoEnable(settings.m_ncoEnable ? 1 : 0); + } + if (deviceSettingsKeys.contains("ncoFrequency") || force) { + swgXtrxOutputSettings->setNcoFrequency(settings.m_ncoFrequency); + } + if (deviceSettingsKeys.contains("lpfBW") || force) { + swgXtrxOutputSettings->setLpfBw(settings.m_lpfBW); + } + if (deviceSettingsKeys.contains("antennaPath") || force) { + swgXtrxOutputSettings->setAntennaPath((int) settings.m_antennaPath); + } + if (deviceSettingsKeys.contains("gain") || force) { + swgXtrxOutputSettings->setGain(settings.m_gain); + } + if (deviceSettingsKeys.contains("extClock") || force) { + swgXtrxOutputSettings->setExtClock(settings.m_extClock ? 1 : 0); + } + if (deviceSettingsKeys.contains("extClockFreq") || force) { + swgXtrxOutputSettings->setExtClockFreq(settings.m_extClockFreq); + } + if (deviceSettingsKeys.contains("pwrmode") || force) { + swgXtrxOutputSettings->setPwrmode(settings.m_pwrmode); + } + + QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex); + m_networkRequest.setUrl(QUrl(deviceSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer=new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgDeviceSettings->asJson().toUtf8()); + buffer->seek(0); + + // Always use PATCH to avoid passing reverse API settings + m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + + delete swgDeviceSettings; +} + +void XTRXOutput::webapiReverseSendStartStop(bool start) +{ + QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run") + .arg(m_settings.m_reverseAPIAddress) + .arg(m_settings.m_reverseAPIPort) + .arg(m_settings.m_reverseAPIDeviceIndex); + m_networkRequest.setUrl(QUrl(deviceSettingsURL)); + + if (start) { + m_networkManager->sendCustomRequest(m_networkRequest, "POST"); + } else { + m_networkManager->sendCustomRequest(m_networkRequest, "DELETE"); + } +} + +void XTRXOutput::networkManagerFinished(QNetworkReply *reply) +{ + QNetworkReply::NetworkError replyError = reply->error(); + + if (replyError) + { + qWarning() << "XTRXOutput::networkManagerFinished:" + << " error(" << (int) replyError + << "): " << replyError + << ": " << reply->errorString(); + return; + } + + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("XTRXOutput::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); +} diff --git a/plugins/samplesink/xtrxoutput/xtrxoutput.h b/plugins/samplesink/xtrxoutput/xtrxoutput.h new file mode 100644 index 000000000..483d81782 --- /dev/null +++ b/plugins/samplesink/xtrxoutput/xtrxoutput.h @@ -0,0 +1,234 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// 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_XTRXOUTPUT_XTRXOUTPUT_H_ +#define PLUGINS_SAMPLESINK_XTRXOUTPUT_XTRXOUTPUT_H_ +#include + +#include +#include +#include + +#include "dsp/devicesamplesink.h" +#include "xtrx/devicextrxshared.h" +#include "xtrxoutputsettings.h" + +class QNetworkAccessManager; +class QNetworkReply; +class DeviceSinkAPI; +class XTRXOutputThread; +struct DeviceXTRXParams; +class FileRecord; + +class XTRXOutput : public DeviceSampleSink +{ + Q_OBJECT +public: + class MsgConfigureXTRX : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const XTRXOutputSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureXTRX* create(const XTRXOutputSettings& settings, bool force) + { + return new MsgConfigureXTRX(settings, force); + } + + private: + XTRXOutputSettings m_settings; + bool m_force; + + MsgConfigureXTRX(const XTRXOutputSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + class MsgGetStreamInfo : public Message { + MESSAGE_CLASS_DECLARATION + + public: + static MsgGetStreamInfo* create() + { + return new MsgGetStreamInfo(); + } + + private: + MsgGetStreamInfo() : + Message() + { } + }; + + class MsgGetDeviceInfo : public Message { + MESSAGE_CLASS_DECLARATION + + public: + static MsgGetDeviceInfo* create() + { + return new MsgGetDeviceInfo(); + } + + private: + MsgGetDeviceInfo() : + Message() + { } + }; + + class MsgReportStreamInfo : public Message { + MESSAGE_CLASS_DECLARATION + + public: + bool getSuccess() const { return m_success; } + bool getActive() const { return m_active; } + uint32_t getFifoFilledCount() const { return m_fifoFilledCount; } + uint32_t getFifoSize() const { return m_fifoSize; } + + static MsgReportStreamInfo* create( + bool success, + bool active, + uint32_t fifoFilledCount, + uint32_t fifoSize + ) + { + return new MsgReportStreamInfo( + success, + active, + fifoFilledCount, + fifoSize + ); + } + + private: + bool m_success; + // everything from lms_stream_status_t + bool m_active; //!< Indicates whether the stream is currently active + uint32_t m_fifoFilledCount; //!< Number of samples in FIFO buffer + uint32_t m_fifoSize; //!< Size of FIFO buffer + + MsgReportStreamInfo( + bool success, + bool active, + uint32_t fifoFilledCount, + uint32_t fifoSize + ) : + Message(), + m_success(success), + m_active(active), + m_fifoFilledCount(fifoFilledCount), + m_fifoSize(fifoSize) + { } + }; + + 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) + { } + }; + + XTRXOutput(DeviceSinkAPI *deviceAPI); + virtual ~XTRXOutput(); + virtual void destroy(); + + virtual void init(); + virtual bool start(); + virtual void stop(); + XTRXOutputThread *getThread() { return m_XTRXOutputThread; } + void setThread(XTRXOutputThread *thread) { m_XTRXOutputThread = 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); + + 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); + + std::size_t getChannelIndex(); + void getLORange(float& minF, float& maxF, float& stepF) const; + void getSRRange(float& minF, float& maxF, float& stepF) const; + void getLPRange(float& minF, float& maxF, float& stepF) const; + +private: + DeviceSinkAPI *m_deviceAPI; + QMutex m_mutex; + XTRXOutputSettings m_settings; + XTRXOutputThread* m_XTRXOutputThread; + QString m_deviceDescription; + bool m_running; + DeviceXTRXShared m_deviceShared; + QNetworkAccessManager *m_networkManager; + QNetworkRequest m_networkRequest; + + bool openDevice(); + void closeDevice(); + XTRXOutputThread *findThread(); + void moveThreadToBuddy(); + + void suspendRxThread(); + void resumeRxThread(); + bool applySettings(const XTRXOutputSettings& settings, bool force = false, bool forceNCOFrequency = false); + void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const XTRXOutputSettings& settings); + void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response); + void webapiReverseSendSettings(QList& deviceSettingsKeys, const XTRXOutputSettings& settings, bool force); + void webapiReverseSendStartStop(bool start); + +private slots: + void networkManagerFinished(QNetworkReply *reply); +}; + +#endif /* PLUGINS_SAMPLESINK_XTRXOUTPUT_XTRXOUTPUT_H_ */ diff --git a/plugins/samplesink/xtrxoutput/xtrxoutputgui.cpp b/plugins/samplesink/xtrxoutput/xtrxoutputgui.cpp new file mode 100644 index 000000000..53b9db4d1 --- /dev/null +++ b/plugins/samplesink/xtrxoutput/xtrxoutputgui.cpp @@ -0,0 +1,513 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// 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 "ui_xtrxoutputgui.h" +#include "gui/colormapper.h" +#include "gui/glspectrum.h" +#include "gui/crightclickenabler.h" +#include "gui/basicdevicesettingsdialog.h" +#include "dsp/dspengine.h" +#include "dsp/dspcommands.h" +#include "device/devicesinkapi.h" +#include "device/deviceuiset.h" +#include "xtrxoutputgui.h" + +XTRXOutputGUI::XTRXOutputGUI(DeviceUISet *deviceUISet, QWidget* parent) : + QWidget(parent), + ui(new Ui::XTRXOutputGUI), + m_deviceUISet(deviceUISet), + m_settings(), + m_sampleRate(0), + m_lastEngineState((DSPDeviceSinkEngine::State)-1), + m_doApplySettings(true), + m_forceSettings(true), + m_statusCounter(0), + m_deviceStatusCounter(0) +{ + m_XTRXOutput = (XTRXOutput*) m_deviceUISet->m_deviceSinkAPI->getSampleSink(); + + ui->setupUi(this); + + float minF, maxF, stepF; + + m_XTRXOutput->getLORange(minF, maxF, stepF); + ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); + ui->centerFrequency->setValueRange(7, ((uint32_t) minF)/1000, ((uint32_t) maxF)/1000); // frequency dial is in kHz + + m_XTRXOutput->getSRRange(minF, maxF, stepF); + ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow)); + ui->sampleRate->setValueRange(8, (uint32_t) minF, (uint32_t) maxF); + + m_XTRXOutput->getLPRange(minF, maxF, stepF); + ui->lpf->setColorMapper(ColorMapper(ColorMapper::GrayYellow)); + ui->lpf->setValueRange(6, (minF/1000)+1, maxF/1000); + + ui->ncoFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); + + ui->channelNumberText->setText(tr("#%1").arg(m_XTRXOutput->getChannelIndex())); + + ui->hwInterpLabel->setText(QString::fromUtf8("H\u2193")); + ui->swInterpLabel->setText(QString::fromUtf8("S\u2193")); + + connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); + connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); + m_statusTimer.start(500); + + CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop); + connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &))); + + displaySettings(); + + connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection); +} + +XTRXOutputGUI::~XTRXOutputGUI() +{ + delete ui; +} + +void XTRXOutputGUI::destroy() +{ + delete this; +} + +void XTRXOutputGUI::setName(const QString& name) +{ + setObjectName(name); +} + +QString XTRXOutputGUI::getName() const +{ + return objectName(); +} + +void XTRXOutputGUI::resetToDefaults() +{ + m_settings.resetToDefaults(); + displaySettings(); + sendSettings(); +} + +qint64 XTRXOutputGUI::getCenterFrequency() const +{ + return m_settings.m_centerFrequency + (m_settings.m_ncoEnable ? m_settings.m_ncoFrequency : 0); +} + +void XTRXOutputGUI::setCenterFrequency(qint64 centerFrequency) +{ + m_settings.m_centerFrequency = centerFrequency - (m_settings.m_ncoEnable ? m_settings.m_ncoFrequency : 0); + displaySettings(); + sendSettings(); +} + +QByteArray XTRXOutputGUI::serialize() const +{ + return m_settings.serialize(); +} + +bool XTRXOutputGUI::deserialize(const QByteArray& data) +{ + if (m_settings.deserialize(data)) + { + displaySettings(); + m_forceSettings = true; + sendSettings(); + return true; + } + else + { + resetToDefaults(); + return false; + } +} + +bool XTRXOutputGUI::handleMessage(const Message& message) +{ + + if (DeviceXTRXShared::MsgReportBuddyChange::match(message)) + { + DeviceXTRXShared::MsgReportBuddyChange& report = (DeviceXTRXShared::MsgReportBuddyChange&) message; + m_settings.m_devSampleRate = report.getDevSampleRate(); + m_settings.m_log2HardInterp = report.getLog2HardDecimInterp(); + + if (!report.getRxElseTx()) { + m_settings.m_centerFrequency = report.getCenterFrequency(); + } + + blockApplySettings(true); + displaySettings(); + blockApplySettings(false); + + return true; + } + else if (DeviceXTRXShared::MsgReportClockSourceChange::match(message)) + { + DeviceXTRXShared::MsgReportClockSourceChange& report = (DeviceXTRXShared::MsgReportClockSourceChange&) message; + m_settings.m_extClockFreq = report.getExtClockFeq(); + m_settings.m_extClock = report.getExtClock(); + + blockApplySettings(true); + ui->extClock->setExternalClockFrequency(m_settings.m_extClockFreq); + ui->extClock->setExternalClockActive(m_settings.m_extClock); + blockApplySettings(false); + + return true; + } + else if (XTRXOutput::MsgReportStreamInfo::match(message)) + { + XTRXOutput::MsgReportStreamInfo& report = (XTRXOutput::MsgReportStreamInfo&) message; + + if (report.getSuccess()) + { + if (report.getActive()) { + ui->streamStatusLabel->setStyleSheet("QLabel { background-color : green; }"); + } else { + ui->streamStatusLabel->setStyleSheet("QLabel { background-color : blue; }"); + } + + ui->fifoBar->setMaximum(report.getFifoSize()); + ui->fifoBar->setValue(report.getFifoFilledCount()); + ui->fifoBar->setToolTip(tr("FIFO fill %1/%2 samples").arg(QString::number(report.getFifoFilledCount())).arg(QString::number(report.getFifoSize()))); + } + else + { + ui->streamStatusLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }"); + } + + return true; + } + else if (DeviceXTRXShared::MsgReportDeviceInfo::match(message)) + { + DeviceXTRXShared::MsgReportDeviceInfo& report = (DeviceXTRXShared::MsgReportDeviceInfo&) message; + ui->temperatureText->setText(tr("%1C").arg(QString::number(report.getTemperature(), 'f', 0))); + + if (report.getGPSLocked()) { + ui->gpsStatusLabel->setStyleSheet("QLabel { background-color : green; }"); + } else { + ui->gpsStatusLabel->setStyleSheet("QLabel { background:rgb(48,48,48); }"); + } + + return true; + } + else if (XTRXOutput::MsgStartStop::match(message)) + { + XTRXOutput::MsgStartStop& notif = (XTRXOutput::MsgStartStop&) message; + blockApplySettings(true); + ui->startStop->setChecked(notif.getStartStop()); + blockApplySettings(false); + + return true; + } + return false; +} + +void XTRXOutputGUI::handleInputMessages() +{ + Message* message; + + while ((message = m_inputMessageQueue.pop()) != 0) + { + if (DSPSignalNotification::match(*message)) + { + DSPSignalNotification* notif = (DSPSignalNotification*) message; + m_sampleRate = notif->getSampleRate(); + m_deviceCenterFrequency = notif->getCenterFrequency(); + qDebug("XTRXInputGUI::handleInputMessages: DSPSignalNotification: SampleRate: %d, CenterFrequency: %llu", notif->getSampleRate(), notif->getCenterFrequency()); + updateSampleRateAndFrequency(); + + delete message; + } + else + { + if (handleMessage(*message)) { + delete message; + } + } + } +} + +void XTRXOutputGUI::updateDACRate() +{ + uint32_t dacRate = m_settings.m_devSampleRate * (1<dacRateLabel->setText(tr("%1k").arg(QString::number(dacRate / 1000.0f, 'g', 5))); + } else { + ui->dacRateLabel->setText(tr("%1M").arg(QString::number(dacRate / 1000000.0f, 'g', 5))); + } +} + +void XTRXOutputGUI::updateSampleRateAndFrequency() +{ + m_deviceUISet->getSpectrum()->setSampleRate(m_sampleRate); + m_deviceUISet->getSpectrum()->setCenterFrequency(m_deviceCenterFrequency); + ui->deviceRateLabel->setText(tr("%1k").arg(QString::number(m_sampleRate / 1000.0f, 'g', 5))); +} + +void XTRXOutputGUI::displaySettings() +{ + ui->extClock->setExternalClockFrequency(m_settings.m_extClockFreq); + ui->extClock->setExternalClockActive(m_settings.m_extClock); + + setCenterFrequencyDisplay(); + ui->sampleRate->setValue(m_settings.m_devSampleRate); + + ui->hwInterp->setCurrentIndex(m_settings.m_log2HardInterp); + ui->swInterp->setCurrentIndex(m_settings.m_log2SoftInterp); + + updateDACRate(); + + ui->lpf->setValue(m_settings.m_lpfBW / 1000); + + ui->gain->setValue(m_settings.m_gain); + ui->gainText->setText(tr("%1").arg(m_settings.m_gain)); + + ui->antenna->setCurrentIndex((int) m_settings.m_antennaPath - (int) XTRX_TX_H); + + setNCODisplay(); + + ui->ncoEnable->setChecked(m_settings.m_ncoEnable); +} + +void XTRXOutputGUI::setNCODisplay() +{ + int ncoHalfRange = (m_settings.m_devSampleRate * (1<<(m_settings.m_log2HardInterp)))/2; + ui->ncoFrequency->setValueRange( + false, + 8, + -ncoHalfRange, + ncoHalfRange); + + ui->ncoFrequency->blockSignals(true); + ui->ncoFrequency->setToolTip(QString("NCO frequency shift in Hz (Range: +/- %1 kHz)").arg(ncoHalfRange/1000)); + ui->ncoFrequency->setValue(m_settings.m_ncoFrequency); + ui->ncoFrequency->blockSignals(false); +} + +void XTRXOutputGUI::setCenterFrequencyDisplay() +{ + int64_t centerFrequency = m_settings.m_centerFrequency; + ui->centerFrequency->setToolTip(QString("Main center frequency in kHz (LO: %1 kHz)").arg(centerFrequency/1000)); + + if (m_settings.m_ncoEnable) { + centerFrequency += m_settings.m_ncoFrequency; + } + + ui->centerFrequency->blockSignals(true); + ui->centerFrequency->setValue(centerFrequency < 0 ? 0 : (uint64_t) centerFrequency/1000); // kHz + ui->centerFrequency->blockSignals(false); +} + +void XTRXOutputGUI::setCenterFrequencySetting(uint64_t kHzValue) +{ + int64_t centerFrequency = kHzValue*1000; + + if (m_settings.m_ncoEnable) { + centerFrequency -= m_settings.m_ncoFrequency; + } + + m_settings.m_centerFrequency = centerFrequency < 0 ? 0 : (uint64_t) centerFrequency; + ui->centerFrequency->setToolTip(QString("Main center frequency in kHz (LO: %1 kHz)").arg(centerFrequency/1000)); +} + +void XTRXOutputGUI::sendSettings() +{ + if(!m_updateTimer.isActive()) + m_updateTimer.start(100); +} + +void XTRXOutputGUI::updateHardware() +{ + if (m_doApplySettings) + { + qDebug() << "XTRXOutputGUI::updateHardware"; + XTRXOutput::MsgConfigureXTRX* message = XTRXOutput::MsgConfigureXTRX::create(m_settings, m_forceSettings); + m_XTRXOutput->getInputMessageQueue()->push(message); + m_forceSettings = false; + m_updateTimer.stop(); + } +} + +void XTRXOutputGUI::updateStatus() +{ + int state = m_deviceUISet->m_deviceSinkAPI->state(); + + if(m_lastEngineState != state) + { + switch(state) + { + case DSPDeviceSinkEngine::StNotStarted: + ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); + break; + case DSPDeviceSinkEngine::StIdle: + ui->startStop->setStyleSheet("QToolButton { background-color : blue; }"); + break; + case DSPDeviceSinkEngine::StRunning: + ui->startStop->setStyleSheet("QToolButton { background-color : green; }"); + break; + case DSPDeviceSinkEngine::StError: + ui->startStop->setStyleSheet("QToolButton { background-color : red; }"); + QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceSinkAPI->errorMessage()); + break; + default: + break; + } + + m_lastEngineState = state; + } + + if (m_statusCounter < 1) + { + m_statusCounter++; + } + else + { + XTRXOutput::MsgGetStreamInfo* message = XTRXOutput::MsgGetStreamInfo::create(); + m_XTRXOutput->getInputMessageQueue()->push(message); + m_statusCounter = 0; + } + + if (m_deviceStatusCounter < 10) + { + m_deviceStatusCounter++; + } + else + { + if (m_deviceUISet->m_deviceSinkAPI->isBuddyLeader()) + { + XTRXOutput::MsgGetDeviceInfo* message = XTRXOutput::MsgGetDeviceInfo::create(); + m_XTRXOutput->getInputMessageQueue()->push(message); + } + + m_deviceStatusCounter = 0; + } +} + +void XTRXOutputGUI::blockApplySettings(bool block) +{ + m_doApplySettings = !block; +} + +void XTRXOutputGUI::on_startStop_toggled(bool checked) +{ + if (m_doApplySettings) + { + XTRXOutput::MsgStartStop *message = XTRXOutput::MsgStartStop::create(checked); + m_XTRXOutput->getInputMessageQueue()->push(message); + } +} + +void XTRXOutputGUI::on_centerFrequency_changed(quint64 value) +{ + setCenterFrequencySetting(value); + sendSettings(); +} + +void XTRXOutputGUI::on_ncoFrequency_changed(qint64 value) +{ + m_settings.m_ncoFrequency = value; + setCenterFrequencyDisplay(); + sendSettings(); +} + +void XTRXOutputGUI::on_ncoEnable_toggled(bool checked) +{ + m_settings.m_ncoEnable = checked; + setCenterFrequencyDisplay(); + sendSettings(); +} + +void XTRXOutputGUI::on_sampleRate_changed(quint64 value) +{ + m_settings.m_devSampleRate = value; + updateDACRate(); + setNCODisplay(); + sendSettings();} + +void XTRXOutputGUI::on_hwInterp_currentIndexChanged(int index) +{ + if ((index <0) || (index > 5)) + return; + m_settings.m_log2HardInterp = index; + updateDACRate(); + setNCODisplay(); + sendSettings(); +} + +void XTRXOutputGUI::on_swInterp_currentIndexChanged(int index) +{ + if ((index <0) || (index > 6)) + return; + m_settings.m_log2SoftInterp = index; + sendSettings(); +} + +void XTRXOutputGUI::on_lpf_changed(quint64 value) +{ + m_settings.m_lpfBW = value * 1000; + sendSettings(); +} + +void XTRXOutputGUI::on_gain_valueChanged(int value) +{ + m_settings.m_gain = value; + ui->gainText->setText(tr("%1").arg(m_settings.m_gain)); + sendSettings(); +} + +void XTRXOutputGUI::on_antenna_currentIndexChanged(int index) +{ + m_settings.m_antennaPath = (xtrx_antenna_t) (index + (int) XTRX_TX_H); + sendSettings(); +} + +void XTRXOutputGUI::on_extClock_clicked() +{ + m_settings.m_extClock = ui->extClock->getExternalClockActive(); + m_settings.m_extClockFreq = ui->extClock->getExternalClockFrequency(); + qDebug("XTRXOutputGUI::on_extClock_clicked: %u Hz %s", m_settings.m_extClockFreq, m_settings.m_extClock ? "on" : "off"); + sendSettings(); +} + +void XTRXOutputGUI::on_pwrmode_currentIndexChanged(int index) +{ + m_settings.m_pwrmode = index; + sendSettings(); +} + +void XTRXOutputGUI::openDeviceSettingsDialog(const QPoint& p) +{ + BasicDeviceSettingsDialog dialog(this); + dialog.setUseReverseAPI(m_settings.m_useReverseAPI); + dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); + dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); + dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex); + + dialog.move(p); + dialog.exec(); + + m_settings.m_useReverseAPI = dialog.useReverseAPI(); + m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); + m_settings.m_reverseAPIPort = dialog.getReverseAPIPort(); + m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex(); + + sendSettings(); +} diff --git a/plugins/samplesink/xtrxoutput/xtrxoutputgui.h b/plugins/samplesink/xtrxoutput/xtrxoutputgui.h new file mode 100644 index 000000000..6340b0455 --- /dev/null +++ b/plugins/samplesink/xtrxoutput/xtrxoutputgui.h @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// 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_XTRXOUTPUT_XTRXOUTPUTGUI_H_ +#define PLUGINS_SAMPLESINK_XTRXOUTPUT_XTRXOUTPUTGUI_H_ + +#include +#include +#include + +#include "util/messagequeue.h" + +#include "xtrxoutput.h" + +class DeviceUISet; + +namespace Ui { +class XTRXOutputGUI; +} + +class XTRXOutputGUI : public QWidget, public PluginInstanceGUI { + Q_OBJECT + +public: + explicit XTRXOutputGUI(DeviceUISet *deviceUISet, QWidget* parent = 0); + virtual ~XTRXOutputGUI(); + virtual void destroy(); + + void setName(const QString& name); + QString getName() const; + + void resetToDefaults(); + virtual qint64 getCenterFrequency() const; + virtual void setCenterFrequency(qint64 centerFrequency); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual bool handleMessage(const Message& message); + +private: + Ui::XTRXOutputGUI* ui; + + DeviceUISet* m_deviceUISet; + XTRXOutput* m_XTRXOutput; //!< Same object as above but gives easy access to XTRXInput methods and attributes that are used intensively + XTRXOutputSettings m_settings; + QTimer m_updateTimer; + QTimer m_statusTimer; + int m_sampleRate; + quint64 m_deviceCenterFrequency; //!< Center frequency in device + int m_lastEngineState; + bool m_doApplySettings; + bool m_forceSettings; + int m_statusCounter; + int m_deviceStatusCounter; + MessageQueue m_inputMessageQueue; + + void displaySettings(); + void setNCODisplay(); + void setCenterFrequencyDisplay(); + void setCenterFrequencySetting(uint64_t kHzValue); + void sendSettings(); + void updateSampleRateAndFrequency(); + void updateDACRate(); + void blockApplySettings(bool block); + +private slots: + void handleInputMessages(); + void on_startStop_toggled(bool checked); + void on_centerFrequency_changed(quint64 value); + void on_ncoFrequency_changed(qint64 value); + void on_ncoEnable_toggled(bool checked); + void on_sampleRate_changed(quint64 value); + void on_hwInterp_currentIndexChanged(int index); + void on_swInterp_currentIndexChanged(int index); + void on_lpf_changed(quint64 value); + void on_gain_valueChanged(int value); + void on_antenna_currentIndexChanged(int index); + void on_extClock_clicked(); + void on_pwrmode_currentIndexChanged(int index); + + void updateHardware(); + void updateStatus(); + void openDeviceSettingsDialog(const QPoint& p); +}; + +#endif /* PLUGINS_SAMPLESINK_XTRXOUTPUT_XTRXOUTPUTGUI_H_ */ diff --git a/plugins/samplesink/xtrxoutput/xtrxoutputgui.ui b/plugins/samplesink/xtrxoutput/xtrxoutputgui.ui new file mode 100644 index 000000000..b7b14da08 --- /dev/null +++ b/plugins/samplesink/xtrxoutput/xtrxoutputgui.ui @@ -0,0 +1,913 @@ + + + XTRXOutputGUI + + + + 0 + 0 + 370 + 290 + + + + + 0 + 0 + + + + + 360 + 290 + + + + + Liberation Sans + 9 + + + + XTRX output + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + 4 + + + + + + + + + start/stop generation + + + + + + + :/play.png + :/stop.png:/play.png + + + + + + + + + + + + 54 + 0 + + + + ADC rate before hardware downsampling (k or MS/s) + + + 00000k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 20 + 50 + false + + + + PointingHandCursor + + + Qt::StrongFocus + + + Main center frequency in kHz + + + + + + + 6 + + + 6 + + + + + + + kHz + + + + + + + + 20 + 0 + + + + Channel number + + + #0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + 54 + 0 + + + + Baseband I/Q sample rate kS/s + + + 00000k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + 2 + + + + + Enable the TSP NCO + + + NCO + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 12 + 50 + false + + + + PointingHandCursor + + + Center frequency with NCO engaged (kHz) + + + + + + + kHz + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + External clock dialog + + + + + + + :/clocksource.png:/clocksource.png + + + + + + + + + Qt::Horizontal + + + + + + + 2 + + + + + Hw + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + 16777215 + + + + TSP hardware decimation factor + + + 0 + + + + 1 + + + + + 2 + + + + + 4 + + + + + 8 + + + + + 16 + + + + + 32 + + + + + + + + Sw + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + 16777215 + + + + Software decimation factor + + + 0 + + + + 1 + + + + + 2 + + + + + 4 + + + + + 8 + + + + + 16 + + + + + 32 + + + + + 64 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + SR + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 12 + 50 + false + + + + PointingHandCursor + + + Device to host sample rate + + + + + + + S/s + + + + + + + + + Qt::Horizontal + + + + + + + 2 + + + 2 + + + + + LP + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 12 + 50 + false + + + + PointingHandCursor + + + Analog lowpass filer bandwidth (kHz) + + + + + + + kHz + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + LMS Pwr + + + + + + + + 50 + 0 + + + + Power mode + + + 4 + + + + 0 - Save Max + + + + + 1 + + + + + 2 + + + + + 3 - Economy + + + + + 4 - Optimal + + + + + 5 + + + + + 6 + + + + + 7 - Perf Max + + + + + + + + + + 2 + + + 2 + + + + + Gain + + + + + + + Global gain setting (dB) + + + 70 + + + 1 + + + 20 + + + Qt::Horizontal + + + + + + + + 40 + 0 + + + + + 18 + 16777215 + + + + Global gain (dB) + + + 20dB + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + + + :/antenna.png + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + Antenna select: No: none, Lo: 700:900M, Hi: 2:2.6G, Wi: wideband, T1: Tx1 LB, T2: Tx2 LB + + + + Hi + + + + + Wi + + + + + + + + + + Qt::Horizontal + + + + + + + 2 + + + 2 + + + + + + 24 + 24 + + + + + 24 + 24 + + + + Green when stream is reporting data + + + + + + :/stream.png + + + + + + + + 24 + 24 + + + + + 24 + 24 + + + + Green when GPS is locked + + + + + + :/gps.png + + + + + + + + 16777215 + 16 + + + + + 8 + + + + FIFO fill status + + + QProgressBar{border: 2px solid rgb(79, 79, 79); text-align: center;} +QToolTip{background-color: white; color: black;} + + + 0 + + + + + + + Qt::Vertical + + + + + + + + 24 + 0 + + + + Board temperature (degrees C) + + + 00C + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + ValueDial + QWidget +
gui/valuedial.h
+ 1 +
+ + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
+ + ExternalClockButton + QToolButton +
gui/externalclockbutton.h
+
+ + ValueDialZ + QWidget +
gui/valuedialz.h
+ 1 +
+
+ + + + +
diff --git a/plugins/samplesink/xtrxoutput/xtrxoutputplugin.cpp b/plugins/samplesink/xtrxoutput/xtrxoutputplugin.cpp new file mode 100644 index 000000000..a31f263ba --- /dev/null +++ b/plugins/samplesink/xtrxoutput/xtrxoutputplugin.cpp @@ -0,0 +1,127 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 + +#include "xtrx_api.h" +#include "plugin/pluginapi.h" +#include "util/simpleserializer.h" +#include "device/devicesinkapi.h" +#include "xtrx/devicextrxparam.h" + +#ifdef SERVER_MODE +#include "xtrxoutput.h" +#else +#include "xtrxoutputgui.h" +#endif +#include "../xtrxoutput/xtrxoutputplugin.h" + +const PluginDescriptor XTRXOutputPlugin::m_pluginDescriptor = { + QString("XTRX Output"), + QString("4.4.0"), + QString("(c) Edouard Griffiths, F4EXB"), + QString("https://github.com/f4exb/sdrangel"), + true, + QString("https://github.com/f4exb/sdrangel") +}; + +const QString XTRXOutputPlugin::m_hardwareID = "XTRX"; +const QString XTRXOutputPlugin::m_deviceTypeID = XTRXOUTPUT_DEVICE_TYPE_ID; + +XTRXOutputPlugin::XTRXOutputPlugin(QObject* parent) : + QObject(parent) +{ +} + +const PluginDescriptor& XTRXOutputPlugin::getPluginDescriptor() const +{ + return m_pluginDescriptor; +} + +void XTRXOutputPlugin::initPlugin(PluginAPI* pluginAPI) +{ + pluginAPI->registerSampleSink(m_deviceTypeID, this); +} + +PluginInterface::SamplingDevices XTRXOutputPlugin::enumSampleSinks() +{ + SamplingDevices result; + xtrx_device_info_t devs[32]; + int res = xtrx_discovery(devs, 32); + int i; + for (i = 0; i < res; i++) { + DeviceXTRXParams XTRXParams; + for (unsigned int j = 0; j < XTRXParams.m_nbTxChannels; j++) + { + qDebug("XTRXInputPlugin::enumSampleSinks: device #%d channel %u: %s", i, j, devs[i].uniqname); + QString displayedName(QString("XTRX[%1:%2] %3").arg(i).arg(j).arg(devs[i].uniqname)); + result.append(SamplingDevice(displayedName, + m_hardwareID, + m_deviceTypeID, + QString(devs[i].uniqname), + i, + PluginInterface::SamplingDevice::PhysicalDevice, + false, + XTRXParams.m_nbTxChannels, + j)); + } + } + return result; +} + +#ifdef SERVER_MODE +PluginInstanceGUI* XTRXOutputPlugin::createSampleSinkPluginInstanceGUI( + const QString& sinkId __attribute((unused)), + QWidget **widget __attribute((unused)), + DeviceUISet *deviceUISet __attribute((unused))) +{ + return 0; +} +#else +PluginInstanceGUI* XTRXOutputPlugin::createSampleSinkPluginInstanceGUI( + const QString& sinkId, + QWidget **widget, + DeviceUISet *deviceUISet) +{ + if(sinkId == m_deviceTypeID) + { + XTRXOutputGUI* gui = new XTRXOutputGUI(deviceUISet); + *widget = gui; + return gui; + } + else + { + return 0; + } +} +#endif + +DeviceSampleSink* XTRXOutputPlugin::createSampleSinkPluginInstanceOutput(const QString& sinkId, DeviceSinkAPI *deviceAPI) +{ + if(sinkId == m_deviceTypeID) + { + XTRXOutput* output = new XTRXOutput(deviceAPI); + return output; + } + else + { + return 0; + } +} + diff --git a/plugins/samplesink/xtrxoutput/xtrxoutputplugin.h b/plugins/samplesink/xtrxoutput/xtrxoutputplugin.h new file mode 100644 index 000000000..2efc5ef0f --- /dev/null +++ b/plugins/samplesink/xtrxoutput/xtrxoutputplugin.h @@ -0,0 +1,53 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// 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_SAMPLESOURCE_LIMESDROUTPUT_LIMESDROUTPUTPLUGIN_H_ +#define PLUGINS_SAMPLESOURCE_LIMESDROUTPUT_LIMESDROUTPUTPLUGIN_H_ + +#include +#include "plugin/plugininterface.h" + +class PluginAPI; + +#define XTRXOUTPUT_DEVICE_TYPE_ID "sdrangel.samplesink.xtrx" + +class XTRXOutputPlugin : public QObject, public PluginInterface { + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID XTRXOUTPUT_DEVICE_TYPE_ID) + +public: + explicit XTRXOutputPlugin(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_SAMPLESOURCE_LIMESDROUTPUT_LIMESDROUTPUTPLUGIN_H_ */ diff --git a/plugins/samplesink/xtrxoutput/xtrxoutputsettings.cpp b/plugins/samplesink/xtrxoutput/xtrxoutputsettings.cpp new file mode 100644 index 000000000..4d7f2af07 --- /dev/null +++ b/plugins/samplesink/xtrxoutput/xtrxoutputsettings.cpp @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// 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 "../xtrxoutput/xtrxoutputsettings.h" + +#include "util/simpleserializer.h" + +XTRXOutputSettings::XTRXOutputSettings() +{ + resetToDefaults(); +} + +void XTRXOutputSettings::resetToDefaults() +{ + m_centerFrequency = 435000*1000; + m_devSampleRate = 5e6; + m_log2HardInterp = 1; + m_log2SoftInterp = 4; + m_lpfBW = 4.5e6f; + m_gain = 20; + m_ncoEnable = true; + m_ncoFrequency = 500000; + m_antennaPath = XTRX_TX_H; + m_extClock = false; + m_extClockFreq = 0; // Auto + m_pwrmode = 1; + m_useReverseAPI = false; + m_reverseAPIAddress = "127.0.0.1"; + m_reverseAPIPort = 8888; + m_reverseAPIDeviceIndex = 0; +} + +QByteArray XTRXOutputSettings::serialize() const +{ + SimpleSerializer s(1); + + s.writeDouble(1, m_devSampleRate); + s.writeU32(2, m_log2HardInterp); + s.writeU32(3, m_log2SoftInterp); + s.writeFloat(4, m_lpfBW); + s.writeU32(5, m_gain); + s.writeBool(6, m_ncoEnable); + s.writeS32(7, m_ncoFrequency); + s.writeS32(8, (int) m_antennaPath); + s.writeBool(9, m_extClock); + s.writeU32(10, m_extClockFreq); + s.writeU32(11, m_pwrmode); + s.writeBool(12, m_useReverseAPI); + s.writeString(13, m_reverseAPIAddress); + s.writeU32(14, m_reverseAPIPort); + s.writeU32(15, m_reverseAPIDeviceIndex); + + return s.final(); +} + +bool XTRXOutputSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if (!d.isValid()) + { + resetToDefaults(); + return false; + } + + if (d.getVersion() == 1) + { + int intval; + uint32_t uintval; + + d.readDouble(1, &m_devSampleRate, 5e6); + d.readU32(2, &m_log2HardInterp, 2); + d.readU32(3, &m_log2SoftInterp, 0); + d.readFloat(4, &m_lpfBW, 1.5e6); + d.readU32(5, &m_gain, 20); + d.readBool(6, &m_ncoEnable, true); + d.readS32(7, &m_ncoFrequency, 500000); + d.readS32(8, &intval, 0); + m_antennaPath = (xtrx_antenna_t) intval; + d.readBool(9, &m_extClock, false); + d.readU32(10, &m_extClockFreq, 0); + d.readU32(11, &m_pwrmode, 2); + d.readBool(12, &m_useReverseAPI, false); + d.readString(13, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(14, &uintval, 0); + + if ((uintval > 1023) && (uintval < 65535)) { + m_reverseAPIPort = uintval; + } else { + m_reverseAPIPort = 8888; + } + + d.readU32(15, &uintval, 0); + m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval; + + return true; + } + else + { + resetToDefaults(); + return false; + } + +} diff --git a/plugins/samplesink/xtrxoutput/xtrxoutputsettings.h b/plugins/samplesink/xtrxoutput/xtrxoutputsettings.h new file mode 100644 index 000000000..b20193dd8 --- /dev/null +++ b/plugins/samplesink/xtrxoutput/xtrxoutputsettings.h @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// 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_XTRXOUTPUT_XTRXOUTPUTSETTINGS_H_ +#define PLUGINS_SAMPLESINK_XTRXOUTPUT_XTRXOUTPUTSETTINGS_H_ + +#include + +#include +#include + +#include "xtrx_api.h" + +/** + * These are the settings individual to each hardware channel or software Tx chain + * Plus the settings to be saved in the presets + */ +struct XTRXOutputSettings +{ + // global settings to be saved + uint64_t m_centerFrequency; + double m_devSampleRate; + uint32_t m_log2HardInterp; + // channel settings + uint32_t m_log2SoftInterp; + float m_lpfBW; //!< LMS analog lowpass filter bandwidth (Hz) + uint32_t m_gain; //!< Optimally distributed gain (dB) + bool m_ncoEnable; //!< Enable TSP NCO and mixing + int m_ncoFrequency; //!< Actual NCO frequency (the resulting frequency with mixing is displayed) + xtrx_antenna_t m_antennaPath; + bool m_extClock; //!< True if external clock source + uint32_t m_extClockFreq; //!< Frequency (Hz) of external clock source + uint32_t m_pwrmode; + bool m_useReverseAPI; + QString m_reverseAPIAddress; + uint16_t m_reverseAPIPort; + uint16_t m_reverseAPIDeviceIndex; + + XTRXOutputSettings(); + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); +}; + +#endif /* PLUGINS_SAMPLESINK_XTRXOUTPUT_XTRXOUTPUTSETTINGS_H_ */ diff --git a/plugins/samplesink/xtrxoutput/xtrxoutputthread.cpp b/plugins/samplesink/xtrxoutput/xtrxoutputthread.cpp new file mode 100644 index 000000000..518869d0b --- /dev/null +++ b/plugins/samplesink/xtrxoutput/xtrxoutputthread.cpp @@ -0,0 +1,333 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// 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 "xtrx/devicextrx.h" +#include "dsp/samplesourcefifo.h" +#include "xtrxoutputthread.h" + + +XTRXOutputThread::XTRXOutputThread(struct xtrx_dev *dev, unsigned int nbChannels, unsigned int uniqueChannelIndex, QObject* parent) : + QThread(parent), + m_running(false), + m_dev(dev), + m_nbChannels(nbChannels), + m_uniqueChannelIndex(uniqueChannelIndex) +{ + qDebug("XTRXOutputThread::XTRXOutputThread"); + m_channels = new Channel[2]; + m_buf = new qint16[2*DeviceXTRX::blockSize*nbChannels]; +} + +XTRXOutputThread::~XTRXOutputThread() +{ + qDebug("XTRXOutputThread::~XTRXOutputThread"); + + if (m_running) { + stopWork(); + } + + delete[] m_buf; + delete[] m_channels; +} + +void XTRXOutputThread::startWork() +{ + m_startWaitMutex.lock(); + start(); + + while(!m_running) { + m_startWaiter.wait(&m_startWaitMutex, 100); + } + + m_startWaitMutex.unlock(); +} + +void XTRXOutputThread::stopWork() +{ + m_running = false; + wait(); +} + +unsigned int XTRXOutputThread::getNbFifos() +{ + unsigned int fifoCount = 0; + + for (unsigned int i = 0; i < 2; i++) + { + if (m_channels[i].m_sampleFifo) { + fifoCount++; + } + } + + return fifoCount; +} + +void XTRXOutputThread::setLog2Interpolation(unsigned int channel, unsigned int log2_interp) +{ + if (channel < 2) { + m_channels[channel].m_log2Interp = log2_interp; + } +} + +unsigned int XTRXOutputThread::getLog2Interpolation(unsigned int channel) const +{ + if (channel < 2) { + return m_channels[channel].m_log2Interp; + } else { + return 0; + } +} + +void XTRXOutputThread::setFifo(unsigned int channel, SampleSourceFifo *sampleFifo) +{ + if (channel < 2) { + m_channels[channel].m_sampleFifo = sampleFifo; + } +} + +SampleSourceFifo *XTRXOutputThread::getFifo(unsigned int channel) +{ + if (channel < 2) { + return m_channels[channel].m_sampleFifo; + } else { + return 0; + } +} + +void XTRXOutputThread::run() +{ + int res; + + m_running = true; + m_startWaiter.wakeAll(); + + unsigned int nbFifos = getNbFifos(); + + if ((m_nbChannels != 0) && (nbFifos != 0)) + { + xtrx_run_params params; + xtrx_run_params_init(¶ms); + + params.dir = XTRX_TX; + params.tx_repeat_buf = 0; + params.tx.paketsize = DeviceXTRX::blockSize; + params.tx.chs = XTRX_CH_AB; + params.tx.wfmt = XTRX_WF_16; + params.tx.hfmt = XTRX_IQ_INT16; + + if (m_nbChannels == 1) + { + qDebug("XTRXOutputThread::run: SO mode for channel #%u", m_uniqueChannelIndex); + params.tx.flags |= XTRX_RSP_SISO_MODE; + + if (m_uniqueChannelIndex == 1) { + params.tx.flags |= XTRX_RSP_SWAP_AB; + } + } + + res = xtrx_run_ex(m_dev, ¶ms); + + if (res != 0) + { + qCritical("XTRXOutputThread::run: could not start stream err:%d", res); + m_running = false; + } + else + { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + qDebug("XTRXOutputThread::run: stream started"); + } + + const unsigned int elemSize = 4; // XTRX uses 4 byte I+Q samples + std::vector> buffMem(m_nbChannels, std::vector(elemSize*DeviceXTRX::blockSize)); + std::vector buffs(m_nbChannels); + master_ts ts = 4096*1024; + + for (std::size_t i = 0; i < m_nbChannels; i++) { + buffs[i] = buffMem[i].data(); + } + + xtrx_send_ex_info_t nfo; + nfo.samples = DeviceXTRX::blockSize; + nfo.buffer_count = m_nbChannels; + nfo.buffers = (void* const*) buffs.data(); + nfo.flags = 0; //XTRX_TX_SEND_ZEROS; + nfo.ts = ts; + + while (m_running) + { +// if (m_nbChannels > 1) { +// callbackMO((qint16*) buffs[0], (qint16*) buffs[1], nfo.samples); +// } else { +// callbackSO((qint16*) buffs[0], nfo.samples); +// } + + callbackSO((qint16*) buffs[0], nfo.samples); + res = xtrx_send_sync_ex(m_dev, &nfo); + + if (res < 0) + { + qCritical("XTRXOutputThread::run send error: %d", res); + qDebug("XTRXOutputThread::run: out_samples: %u out_flags: %u", nfo.out_samples, nfo.out_flags); + break; + } + + nfo.ts += DeviceXTRX::blockSize; + } + + res = xtrx_stop(m_dev, XTRX_TX); + + if (res != 0) + { + qCritical("XTRXOutputThread::run: could not stop stream"); + } + else + { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + qDebug("XTRXOutputThread::run: stream stopped"); + } + } + else + { + qWarning("XTRXOutputThread::run: no channels or FIFO allocated. Aborting"); + } + + m_running = false; +} + +void XTRXOutputThread::callback(qint16* buf, qint32 len) +{ + if (m_channels[m_uniqueChannelIndex].m_sampleFifo) + { + float bal = m_channels[m_uniqueChannelIndex].m_sampleFifo->getRWBalance(); + + if (bal < -0.25) { + qDebug("XTRXOutputThread::callbackSO: read lags: %f", bal); + } else if (bal > 0.25) { + qDebug("XTRXOutputThread::callbackSO: read leads: %f", bal); + } + + SampleVector::iterator beginRead; + m_channels[m_uniqueChannelIndex].m_sampleFifo->readAdvance(beginRead, len/(1<getRWBalance(); + + if (bal < -0.25) { + qDebug("XTRXOutputThread::callbackSO: read lags: %f", bal); + } else if (bal > 0.25) { + qDebug("XTRXOutputThread::callbackSO: read leads: %f", bal); + } + + SampleVector::iterator beginRead; + m_channels[m_uniqueChannelIndex].m_sampleFifo->readAdvance(beginRead, len/(1<. // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_SAMPLESOURCE_XTRXOUTPUT_XTRXOUTPUTTHREAD_H_ +#define PLUGINS_SAMPLESOURCE_XTRXOUTPUT_XTRXOUTPUTTHREAD_H_ + +#include +#include +#include + +#include "xtrx_api.h" + +#include "dsp/samplesourcefifo.h" +#include "dsp/interpolators.h" +#include "xtrx/devicextrxshared.h" + +struct xtrx_dev; + +class XTRXOutputThread : public QThread, public DeviceXTRXShared::ThreadInterface +{ + Q_OBJECT + +public: + XTRXOutputThread(struct xtrx_dev *dev, unsigned int nbChannels, unsigned int uniqueChannelIndex = 0, QObject* parent = 0); + ~XTRXOutputThread(); + + virtual void startWork(); + virtual void stopWork(); + virtual bool isRunning() { 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 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 xtrx_dev *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; + unsigned int m_uniqueChannelIndex; + + void run(); + unsigned int getNbFifos(); + void callback(qint16* buf, qint32 len); + void callbackSO(qint16* buf, qint32 len); + void callbackMO(qint16* buf0, qint16* buf1, qint32 len); +}; + +#endif /* PLUGINS_SAMPLESOURCE_XTRXOUTPUT_XTRXOUTPUTTHREAD_H_ */ diff --git a/plugins/samplesource/xtrxinput/xtrxinput.cpp b/plugins/samplesource/xtrxinput/xtrxinput.cpp index 8f5ec79fd..0ca83e11b 100644 --- a/plugins/samplesource/xtrxinput/xtrxinput.cpp +++ b/plugins/samplesource/xtrxinput/xtrxinput.cpp @@ -305,6 +305,7 @@ bool XTRXInput::start() delete xtrxInputThread; xtrxInputThread = new XTRXInputThread(m_deviceShared.m_dev->getDevice(), 2); // MI mode (2 channels) m_XTRXInputThread = xtrxInputThread; // take ownership + m_deviceShared.m_thread = xtrxInputThread; for (int i = 0; i < 2; i++) // restore original FIFO references { @@ -316,8 +317,10 @@ bool XTRXInput::start() const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); std::vector::const_iterator it = sourceBuddies.begin(); - for (; it != sourceBuddies.end(); ++it) { + for (; it != sourceBuddies.end(); ++it) + { ((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_source->setThread(0); + ((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_thread = 0; } // was used as temporary storage: @@ -336,6 +339,7 @@ bool XTRXInput::start() qDebug("XTRXInput::start: allocate thread and take ownership"); xtrxInputThread = new XTRXInputThread(m_deviceShared.m_dev->getDevice(), 1, requestedChannel); m_XTRXInputThread = xtrxInputThread; // take ownership + m_deviceShared.m_thread = xtrxInputThread; needsStart = true; } @@ -387,13 +391,16 @@ void XTRXInput::stop() xtrxInputThread->stopWork(); delete xtrxInputThread; m_XTRXInputThread = 0; + m_deviceShared.m_thread = 0; // remove old thread address from buddies (reset in all buddies) const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); std::vector::const_iterator it = sourceBuddies.begin(); - for (; it != sourceBuddies.end(); ++it) { + for (; it != sourceBuddies.end(); ++it) + { ((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_source->setThread(0); + ((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_thread = 0; } } else if (nbOriginalChannels == 2) // Reduce from MI to SI by deleting and re-creating the thread @@ -401,10 +408,10 @@ void XTRXInput::stop() qDebug("XTRXInput::stop: MI mode. Reduce by deleting and re-creating the thread"); xtrxInputThread->stopWork(); delete xtrxInputThread; - m_XTRXInputThread = 0; - xtrxInputThread = new XTRXInputThread(m_deviceShared.m_dev->getDevice(), 1, requestedChannel); m_XTRXInputThread = xtrxInputThread; // take ownership + m_deviceShared.m_thread = xtrxInputThread; + xtrxInputThread->setFifo(requestedChannel, &m_sampleFifo); xtrxInputThread->setLog2Decimation(requestedChannel, m_settings.m_log2SoftDecim); @@ -412,8 +419,10 @@ void XTRXInput::stop() const std::vector& sourceBuddies = m_deviceAPI->getSourceBuddies(); std::vector::const_iterator it = sourceBuddies.begin(); - for (; it != sourceBuddies.end(); ++it) { + for (; it != sourceBuddies.end(); ++it) + { ((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_source->setThread(0); + ((DeviceXTRXShared*) (*it)->getBuddySharedPtr())->m_thread = 0; } xtrxInputThread->startWork(); @@ -425,58 +434,42 @@ void XTRXInput::stop() void XTRXInput::suspendTxThread() { - // TODO: activate when output is managed -// XTRXOutputThread *xtrxOutputThread = 0; -// -// // find a buddy that has allocated the thread -// const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); -// std::vector::const_iterator itSink = sinkBuddies.begin() -// -// for (; itSink != sinkBuddies.end(); ++itSink) -// { -// XTRXOutput *buddySink = ((DeviceXTRXShared*) (*itSink)->getBuddySharedPtr())->m_sink; -// -// if (buddySink) -// { -// xtrxOutputThread = buddySink->getThread(); -// -// if (xtrxOutputThread) { -// break; -// } -// } -// } -// -// if (xtrxOutputThread) { -// xtrxOutputThread->stopWork(); -// } + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator itSink = sinkBuddies.begin(); + + qDebug("XTRXInput::suspendTxThread (%lu)", sinkBuddies.size()); + + for (; itSink != sinkBuddies.end(); ++itSink) + { + DeviceXTRXShared *buddySharedPtr = (DeviceXTRXShared *) (*itSink)->getBuddySharedPtr(); + + if ((buddySharedPtr->m_thread) && buddySharedPtr->m_thread->isRunning()) + { + buddySharedPtr->m_thread->stopWork(); + buddySharedPtr->m_threadWasRunning = true; + } + else + { + buddySharedPtr->m_threadWasRunning = false; + } + } } void XTRXInput::resumeTxThread() { - // TODO: activate when output is managed -// XTRXOutputThread *xtrxOutputThread = 0; -// -// // find a buddy that has allocated the thread -// const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); -// std::vector::const_iterator itSink = sinkBuddies.begin() -// -// for (; itSink != sinkBuddies.end(); ++itSink) -// { -// XTRXOutput *buddySink = ((DeviceXTRXShared*) (*itSink)->getBuddySharedPtr())->m_sink; -// -// if (buddySink) -// { -// xtrxOutputThread = buddySink->getThread(); -// -// if (xtrxOutputThread) { -// break; -// } -// } -// } -// -// if (xtrxOutputThread) { -// xtrxOutputThread->startWork(); -// } + const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); + std::vector::const_iterator itSink = sinkBuddies.begin(); + + qDebug("XTRXInput::resumeTxThread (%lu)", sinkBuddies.size()); + + for (; itSink != sinkBuddies.end(); ++itSink) + { + DeviceXTRXShared *buddySharedPtr = (DeviceXTRXShared *) (*itSink)->getBuddySharedPtr(); + + if (buddySharedPtr->m_threadWasRunning) { + buddySharedPtr->m_thread->startWork(); + } + } } QByteArray XTRXInput::serialize() const @@ -616,9 +609,12 @@ bool XTRXInput::handleMessage(const Message& message) m_settings.m_centerFrequency + ncoShift); m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif); - DeviceXTRXShared::MsgReportBuddyChange *reportToGUI = DeviceXTRXShared::MsgReportBuddyChange::create( - m_settings.m_devSampleRate, m_settings.m_log2HardDecim, m_settings.m_centerFrequency, true); - getMessageQueueToGUI()->push(reportToGUI); + if (getMessageQueueToGUI()) + { + DeviceXTRXShared::MsgReportBuddyChange *reportToGUI = DeviceXTRXShared::MsgReportBuddyChange::create( + m_settings.m_devSampleRate, m_settings.m_log2HardDecim, m_settings.m_centerFrequency, true); + getMessageQueueToGUI()->push(reportToGUI); + } return true; } @@ -629,9 +625,12 @@ bool XTRXInput::handleMessage(const Message& message) m_settings.m_extClock = report.getExtClock(); m_settings.m_extClockFreq = report.getExtClockFeq(); - DeviceXTRXShared::MsgReportClockSourceChange *reportToGUI = DeviceXTRXShared::MsgReportClockSourceChange::create( - m_settings.m_extClock, m_settings.m_extClockFreq); - getMessageQueueToGUI()->push(reportToGUI); + if (getMessageQueueToGUI()) + { + DeviceXTRXShared::MsgReportClockSourceChange *reportToGUI = DeviceXTRXShared::MsgReportClockSourceChange::create( + m_settings.m_extClock, m_settings.m_extClockFreq); + getMessageQueueToGUI()->push(reportToGUI); + } return true; } diff --git a/plugins/samplesource/xtrxinput/xtrxinput.h b/plugins/samplesource/xtrxinput/xtrxinput.h index 3c98aa17f..68830270e 100644 --- a/plugins/samplesource/xtrxinput/xtrxinput.h +++ b/plugins/samplesource/xtrxinput/xtrxinput.h @@ -94,8 +94,8 @@ public: class MsgReportStreamInfo : public Message { MESSAGE_CLASS_DECLARATION - public: - bool getSuccess() const { return m_success; } + public: + bool getSuccess() const { return m_success; } bool getActive() const { return m_active; } uint32_t getFifoFilledCount() const { return m_fifoFilledCount; } uint32_t getFifoSize() const { return m_fifoSize; } diff --git a/plugins/samplesource/xtrxinput/xtrxinputplugin.cpp b/plugins/samplesource/xtrxinput/xtrxinputplugin.cpp index ccc1c820d..d5a363b5c 100644 --- a/plugins/samplesource/xtrxinput/xtrxinputplugin.cpp +++ b/plugins/samplesource/xtrxinput/xtrxinputplugin.cpp @@ -36,10 +36,10 @@ const PluginDescriptor XTRXInputPlugin::m_pluginDescriptor = { QString("XTRX Input"), QString("4.4.0"), - QString("(c) Sergey Kostanbaev, Fairwaves"), - QString("https://github.com/xtrx-sdr/sdrangel"), + QString("(c) Edouard Griffiths, F4EXB"), + QString("https://github.com/f4exb/sdrangel"), true, - QString("https://github.com/xtrx-sdr/sdrangel") + QString("https://github.com/f4exb/sdrangel") }; const QString XTRXInputPlugin::m_hardwareID = "XTRX"; @@ -113,24 +113,6 @@ PluginInstanceGUI* XTRXInputPlugin::createSampleSourcePluginInstanceGUI( } #endif -bool XTRXInputPlugin::findSerial(const char *lmsInfoStr, std::string& serial) -{ - std::regex serial_reg("serial=([0-9,A-F]+)"); - std::string input(lmsInfoStr); - std::smatch result; - std::regex_search(input, result, serial_reg); - - if (result[1].str().length()>0) - { - serial = result[1].str(); - return true; - } - else - { - return false; - } -} - DeviceSampleSource *XTRXInputPlugin::createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI) { if (sourceId == m_deviceTypeID) diff --git a/plugins/samplesource/xtrxinput/xtrxinputplugin.h b/plugins/samplesource/xtrxinput/xtrxinputplugin.h index 493e7ae16..60ae1e6d7 100644 --- a/plugins/samplesource/xtrxinput/xtrxinputplugin.h +++ b/plugins/samplesource/xtrxinput/xtrxinputplugin.h @@ -48,7 +48,6 @@ public: private: static const PluginDescriptor m_pluginDescriptor; - static bool findSerial(const char *lmsInfoStr, std::string& serial); }; diff --git a/plugins/samplesource/xtrxinput/xtrxinputthread.cpp b/plugins/samplesource/xtrxinput/xtrxinputthread.cpp index c5cc6b35d..2404d3750 100644 --- a/plugins/samplesource/xtrxinput/xtrxinputthread.cpp +++ b/plugins/samplesource/xtrxinput/xtrxinputthread.cpp @@ -19,8 +19,6 @@ #include #include -#include "xtrx_api.h" - #include "xtrx/devicextrx.h" #include "xtrxinputsettings.h" #include "xtrxinputthread.h" diff --git a/plugins/samplesource/xtrxinput/xtrxinputthread.h b/plugins/samplesource/xtrxinput/xtrxinputthread.h index 122511996..d6c039e4c 100644 --- a/plugins/samplesource/xtrxinput/xtrxinputthread.h +++ b/plugins/samplesource/xtrxinput/xtrxinputthread.h @@ -30,7 +30,7 @@ struct xtrx_dev; -class XTRXInputThread : public QThread +class XTRXInputThread : public QThread, public DeviceXTRXShared::ThreadInterface { Q_OBJECT diff --git a/pluginssrv/samplesink/CMakeLists.txt b/pluginssrv/samplesink/CMakeLists.txt index 3fa769ebc..7e6873203 100644 --- a/pluginssrv/samplesink/CMakeLists.txt +++ b/pluginssrv/samplesink/CMakeLists.txt @@ -33,6 +33,11 @@ if(LIBUSB_FOUND AND SOAPYSDR_FOUND) add_subdirectory(soapysdroutput) endif() +find_package(LibXTRX) +if(LIBXTRX_FOUND) + add_subdirectory(xtrxoutput) +endif(LIBXTRX_FOUND) + if (BUILD_DEBIAN) add_subdirectory(bladerf1output) add_subdirectory(bladerf2output) diff --git a/pluginssrv/samplesink/xtrxoutput/CMakeLists.txt b/pluginssrv/samplesink/xtrxoutput/CMakeLists.txt new file mode 100644 index 000000000..7f9cfd568 --- /dev/null +++ b/pluginssrv/samplesink/xtrxoutput/CMakeLists.txt @@ -0,0 +1,47 @@ +project(xtrxoutput) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +set(PLUGIN_PREFIX "../../../plugins/samplesink/xtrxoutput") + +set(xtrxoutput_SOURCES + ${PLUGIN_PREFIX}/xtrxoutput.cpp + ${PLUGIN_PREFIX}/xtrxoutputplugin.cpp + ${PLUGIN_PREFIX}/xtrxoutputsettings.cpp + ${PLUGIN_PREFIX}/xtrxoutputthread.cpp +) + +set(xtrxoutput_HEADERS + ${PLUGIN_PREFIX}/xtrxoutput.h + ${PLUGIN_PREFIX}/xtrxoutputplugin.h + ${PLUGIN_PREFIX}/xtrxoutputsettings.h + ${PLUGIN_PREFIX}/xtrxoutputthread.h +) + +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${CMAKE_SOURCE_DIR}/devices + ${LIBXTRX_INCLUDE_DIRS} +) + +add_definitions(${QT_DEFINITIONS}) +add_definitions(-DQT_PLUGIN) +add_definitions(-DQT_SHARED) + +add_library(outputxtrxsrv SHARED + ${xtrxoutput_SOURCES} + ${xtrxoutput_HEADERS_MOC} +) + +target_link_libraries(outputxtrxsrv + ${QT_LIBRARIES} + ${LIBXTRX_LIBRARIES} + sdrbase + swagger + xtrxdevice +) + +target_link_libraries(outputxtrxsrv Qt5::Core) + +install(TARGETS outputxtrxsrv DESTINATION lib/pluginssrv/samplesink) diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 158712913..6a66de5a0 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -2182,6 +2182,9 @@ margin-bottom: 20px; }, "xtrxInputReport" : { "$ref" : "#/definitions/XtrxInputReport" + }, + "xtrxOutputReport" : { + "$ref" : "#/definitions/XtrxOutputReport" } }, "description" : "Base device report. Only the device report corresponding to the device specified in the deviceHwType is or should be present." @@ -2309,6 +2312,9 @@ margin-bottom: 20px; }, "xtrxInputSettings" : { "$ref" : "#/definitions/XtrxInputSettings" + }, + "xtrxOutputSettings" : { + "$ref" : "#/definitions/XtrxOutputSettings" } }, "description" : "Base device settings. Only the device settings corresponding to the device specified in the deviceHwType field is or should be present." @@ -4858,10 +4864,6 @@ margin-bottom: 20px; "type" : "integer", "description" : "1 if info was successfully retrieved else 0" }, - "streamActive" : { - "type" : "integer", - "description" : "1 if active else 0" - }, "fifoSize" : { "type" : "integer" }, @@ -4968,6 +4970,92 @@ margin-bottom: 20px; } }, "description" : "XTRX" +}; + defs.XtrxOutputReport = { + "properties" : { + "success" : { + "type" : "integer", + "description" : "1 if info was successfully retrieved else 0" + }, + "fifoSize" : { + "type" : "integer" + }, + "fifoFill" : { + "type" : "integer" + }, + "temperature" : { + "type" : "number", + "format" : "float" + }, + "gpsLock" : { + "type" : "integer", + "description" : "1 if GPSDO is locked else 0" + } + }, + "description" : "XTRX" +}; + defs.XtrxOutputSettings = { + "properties" : { + "centerFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "devSampleRate" : { + "type" : "integer" + }, + "log2HardInterp" : { + "type" : "integer" + }, + "log2SoftInterp" : { + "type" : "integer" + }, + "lpfBW" : { + "type" : "integer", + "description" : "LMS analog lowpass filter bandwidth (Hz)" + }, + "gain" : { + "type" : "integer", + "description" : "Optimally distributed gain (dB)" + }, + "ncoEnable" : { + "type" : "integer", + "description" : "Enable TSP NCO and mixing (1 for yes, 0 for no)" + }, + "ncoFrequency" : { + "type" : "integer", + "description" : "Frequency shift from LO" + }, + "antennaPath" : { + "type" : "integer", + "description" : "Antenna selected (enum value from xtrx_antenna_t)" + }, + "extClock" : { + "type" : "integer", + "description" : "Use external clock source (1 for yes, 0 for no)" + }, + "extClockFreq" : { + "type" : "integer", + "description" : "Frequency (Hz) of external clock source" + }, + "pwrmode" : { + "type" : "integer", + "description" : "LMS power mode (0 save max to 7 perf max)" + }, + "useReverseAPI" : { + "type" : "integer", + "description" : "Synchronize with reverse API (1 for yes, 0 for no)" + }, + "reverseAPIAddress" : { + "type" : "string" + }, + "reverseAPIPort" : { + "type" : "integer" + }, + "reverseAPIDeviceIndex" : { + "type" : "integer" + } + }, + "description" : "XTRX" }; @@ -24000,7 +24088,7 @@ except ApiException as e:
- Generated 2019-01-01T11:45:52.860+01:00 + Generated 2019-01-02T09:02:53.799+01:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/Xtrx.yaml b/sdrbase/resources/webapi/doc/swagger/include/Xtrx.yaml index a2739fea8..b1d6e0b24 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/Xtrx.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/Xtrx.yaml @@ -70,8 +70,68 @@ XtrxInputReport: success: description: 1 if info was successfully retrieved else 0 type: integer - streamActive: - description: 1 if active else 0 + fifoSize: + type: integer + fifoFill: + type: integer + temperature: + type: number + format: float + gpsLock: + description: 1 if GPSDO is locked else 0 + type: integer + +XtrxOutputSettings: + description: XTRX + properties: + centerFrequency: + type: integer + format: int64 + devSampleRate: + type: integer + log2HardInterp: + type: integer + log2SoftInterp: + type: integer + lpfBW: + description: LMS analog lowpass filter bandwidth (Hz) + type: integer + gain: + description: Optimally distributed gain (dB) + type: integer + ncoEnable: + description: Enable TSP NCO and mixing (1 for yes, 0 for no) + type: integer + ncoFrequency: + description: Frequency shift from LO + type: integer + antennaPath: + description: Antenna selected (enum value from xtrx_antenna_t) + type: integer + extClock: + description: Use external clock source (1 for yes, 0 for no) + type: integer + extClockFreq: + description: Frequency (Hz) of external clock source + type: integer + pwrmode: + description: LMS power mode (0 save max to 7 perf max) + type: integer + useReverseAPI: + description: Synchronize with reverse API (1 for yes, 0 for no) + type: integer + reverseAPIAddress: + type: string + reverseAPIPort: + type: integer + reverseAPIDeviceIndex: + type: integer + +XtrxOutputReport: + description: XTRX + properties: + success: + description: 1 if info was successfully retrieved else 0 type: integer fifoSize: type: integer @@ -82,4 +142,4 @@ XtrxInputReport: format: float gpsLock: description: 1 if GPSDO is locked else 0 - type: integer \ No newline at end of file + type: integer \ No newline at end of file diff --git a/sdrbase/resources/webapi/doc/swagger/swagger.yaml b/sdrbase/resources/webapi/doc/swagger/swagger.yaml index 1e744fc8b..05059b9b4 100644 --- a/sdrbase/resources/webapi/doc/swagger/swagger.yaml +++ b/sdrbase/resources/webapi/doc/swagger/swagger.yaml @@ -1807,6 +1807,8 @@ definitions: $ref: "/doc/swagger/include/TestSource.yaml#/TestSourceSettings" xtrxInputSettings: $ref: "/doc/swagger/include/Xtrx.yaml#/XtrxInputSettings" + xtrxOutputSettings: + $ref: "/doc/swagger/include/Xtrx.yaml#/XtrxOutputSettings" DeviceReport: @@ -1856,6 +1858,8 @@ definitions: $ref: "/doc/swagger/include/SoapySDR.yaml#/SoapySDRReport" xtrxInputReport: $ref: "/doc/swagger/include/Xtrx.yaml#/XtrxInputReport" + xtrxOutputReport: + $ref: "/doc/swagger/include/Xtrx.yaml#/XtrxOutputReport" ChannelSettings: description: Base channel settings. Only the channel settings corresponding to the channel specified in the channelType field is or should be present. diff --git a/swagger/sdrangel/api/swagger/include/Xtrx.yaml b/swagger/sdrangel/api/swagger/include/Xtrx.yaml index 87840cad6..b1d6e0b24 100644 --- a/swagger/sdrangel/api/swagger/include/Xtrx.yaml +++ b/swagger/sdrangel/api/swagger/include/Xtrx.yaml @@ -79,4 +79,67 @@ XtrxInputReport: format: float gpsLock: description: 1 if GPSDO is locked else 0 - type: integer \ No newline at end of file + type: integer + +XtrxOutputSettings: + description: XTRX + properties: + centerFrequency: + type: integer + format: int64 + devSampleRate: + type: integer + log2HardInterp: + type: integer + log2SoftInterp: + type: integer + lpfBW: + description: LMS analog lowpass filter bandwidth (Hz) + type: integer + gain: + description: Optimally distributed gain (dB) + type: integer + ncoEnable: + description: Enable TSP NCO and mixing (1 for yes, 0 for no) + type: integer + ncoFrequency: + description: Frequency shift from LO + type: integer + antennaPath: + description: Antenna selected (enum value from xtrx_antenna_t) + type: integer + extClock: + description: Use external clock source (1 for yes, 0 for no) + type: integer + extClockFreq: + description: Frequency (Hz) of external clock source + type: integer + pwrmode: + description: LMS power mode (0 save max to 7 perf max) + type: integer + useReverseAPI: + description: Synchronize with reverse API (1 for yes, 0 for no) + type: integer + reverseAPIAddress: + type: string + reverseAPIPort: + type: integer + reverseAPIDeviceIndex: + type: integer + +XtrxOutputReport: + description: XTRX + properties: + success: + description: 1 if info was successfully retrieved else 0 + type: integer + fifoSize: + type: integer + fifoFill: + type: integer + temperature: + type: number + format: float + gpsLock: + description: 1 if GPSDO is locked else 0 + type: integer \ No newline at end of file diff --git a/swagger/sdrangel/api/swagger/swagger.yaml b/swagger/sdrangel/api/swagger/swagger.yaml index b6f26b1c8..be0b02495 100644 --- a/swagger/sdrangel/api/swagger/swagger.yaml +++ b/swagger/sdrangel/api/swagger/swagger.yaml @@ -1807,6 +1807,8 @@ definitions: $ref: "http://localhost:8081/api/swagger/include/TestSource.yaml#/TestSourceSettings" xtrxInputSettings: $ref: "http://localhost:8081/api/swagger/include/Xtrx.yaml#/XtrxInputSettings" + xtrxOutputSettings: + $ref: "http://localhost:8081/api/swagger/include/Xtrx.yaml#/XtrxOutputSettings" DeviceReport: @@ -1856,6 +1858,8 @@ definitions: $ref: "http://localhost:8081/api/swagger/include/SoapySDR.yaml#/SoapySDRReport" xtrxInputReport: $ref: "http://localhost:8081/api/swagger/include/Xtrx.yaml#/XtrxInputReport" + xtrxOutputReport: + $ref: "http://localhost:8081/api/swagger/include/Xtrx.yaml#/XtrxOutputReport" ChannelSettings: description: Base channel settings. Only the channel settings corresponding to the channel specified in the channelType field is or should be present. diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 158712913..6a66de5a0 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -2182,6 +2182,9 @@ margin-bottom: 20px; }, "xtrxInputReport" : { "$ref" : "#/definitions/XtrxInputReport" + }, + "xtrxOutputReport" : { + "$ref" : "#/definitions/XtrxOutputReport" } }, "description" : "Base device report. Only the device report corresponding to the device specified in the deviceHwType is or should be present." @@ -2309,6 +2312,9 @@ margin-bottom: 20px; }, "xtrxInputSettings" : { "$ref" : "#/definitions/XtrxInputSettings" + }, + "xtrxOutputSettings" : { + "$ref" : "#/definitions/XtrxOutputSettings" } }, "description" : "Base device settings. Only the device settings corresponding to the device specified in the deviceHwType field is or should be present." @@ -4858,10 +4864,6 @@ margin-bottom: 20px; "type" : "integer", "description" : "1 if info was successfully retrieved else 0" }, - "streamActive" : { - "type" : "integer", - "description" : "1 if active else 0" - }, "fifoSize" : { "type" : "integer" }, @@ -4968,6 +4970,92 @@ margin-bottom: 20px; } }, "description" : "XTRX" +}; + defs.XtrxOutputReport = { + "properties" : { + "success" : { + "type" : "integer", + "description" : "1 if info was successfully retrieved else 0" + }, + "fifoSize" : { + "type" : "integer" + }, + "fifoFill" : { + "type" : "integer" + }, + "temperature" : { + "type" : "number", + "format" : "float" + }, + "gpsLock" : { + "type" : "integer", + "description" : "1 if GPSDO is locked else 0" + } + }, + "description" : "XTRX" +}; + defs.XtrxOutputSettings = { + "properties" : { + "centerFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "devSampleRate" : { + "type" : "integer" + }, + "log2HardInterp" : { + "type" : "integer" + }, + "log2SoftInterp" : { + "type" : "integer" + }, + "lpfBW" : { + "type" : "integer", + "description" : "LMS analog lowpass filter bandwidth (Hz)" + }, + "gain" : { + "type" : "integer", + "description" : "Optimally distributed gain (dB)" + }, + "ncoEnable" : { + "type" : "integer", + "description" : "Enable TSP NCO and mixing (1 for yes, 0 for no)" + }, + "ncoFrequency" : { + "type" : "integer", + "description" : "Frequency shift from LO" + }, + "antennaPath" : { + "type" : "integer", + "description" : "Antenna selected (enum value from xtrx_antenna_t)" + }, + "extClock" : { + "type" : "integer", + "description" : "Use external clock source (1 for yes, 0 for no)" + }, + "extClockFreq" : { + "type" : "integer", + "description" : "Frequency (Hz) of external clock source" + }, + "pwrmode" : { + "type" : "integer", + "description" : "LMS power mode (0 save max to 7 perf max)" + }, + "useReverseAPI" : { + "type" : "integer", + "description" : "Synchronize with reverse API (1 for yes, 0 for no)" + }, + "reverseAPIAddress" : { + "type" : "string" + }, + "reverseAPIPort" : { + "type" : "integer" + }, + "reverseAPIDeviceIndex" : { + "type" : "integer" + } + }, + "description" : "XTRX" }; @@ -24000,7 +24088,7 @@ except ApiException as e:
- Generated 2019-01-01T11:45:52.860+01:00 + Generated 2019-01-02T09:02:53.799+01:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp index 2b2751fb8..c234b6b3f 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp @@ -66,6 +66,8 @@ SWGDeviceReport::SWGDeviceReport() { m_soapy_sdr_output_report_isSet = false; xtrx_input_report = nullptr; m_xtrx_input_report_isSet = false; + xtrx_output_report = nullptr; + m_xtrx_output_report_isSet = false; } SWGDeviceReport::~SWGDeviceReport() { @@ -112,6 +114,8 @@ SWGDeviceReport::init() { m_soapy_sdr_output_report_isSet = false; xtrx_input_report = new SWGXtrxInputReport(); m_xtrx_input_report_isSet = false; + xtrx_output_report = new SWGXtrxOutputReport(); + m_xtrx_output_report_isSet = false; } void @@ -171,6 +175,9 @@ SWGDeviceReport::cleanup() { if(xtrx_input_report != nullptr) { delete xtrx_input_report; } + if(xtrx_output_report != nullptr) { + delete xtrx_output_report; + } } SWGDeviceReport* @@ -222,6 +229,8 @@ SWGDeviceReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&xtrx_input_report, pJson["xtrxInputReport"], "SWGXtrxInputReport", "SWGXtrxInputReport"); + ::SWGSDRangel::setValue(&xtrx_output_report, pJson["xtrxOutputReport"], "SWGXtrxOutputReport", "SWGXtrxOutputReport"); + } QString @@ -295,6 +304,9 @@ SWGDeviceReport::asJsonObject() { if((xtrx_input_report != nullptr) && (xtrx_input_report->isSet())){ toJsonValue(QString("xtrxInputReport"), xtrx_input_report, obj, QString("SWGXtrxInputReport")); } + if((xtrx_output_report != nullptr) && (xtrx_output_report->isSet())){ + toJsonValue(QString("xtrxOutputReport"), xtrx_output_report, obj, QString("SWGXtrxOutputReport")); + } return obj; } @@ -489,6 +501,16 @@ SWGDeviceReport::setXtrxInputReport(SWGXtrxInputReport* xtrx_input_report) { this->m_xtrx_input_report_isSet = true; } +SWGXtrxOutputReport* +SWGDeviceReport::getXtrxOutputReport() { + return xtrx_output_report; +} +void +SWGDeviceReport::setXtrxOutputReport(SWGXtrxOutputReport* xtrx_output_report) { + this->xtrx_output_report = xtrx_output_report; + this->m_xtrx_output_report_isSet = true; +} + bool SWGDeviceReport::isSet(){ @@ -513,6 +535,7 @@ SWGDeviceReport::isSet(){ if(soapy_sdr_input_report != nullptr && soapy_sdr_input_report->isSet()){ isObjectUpdated = true; break;} if(soapy_sdr_output_report != nullptr && soapy_sdr_output_report->isSet()){ isObjectUpdated = true; break;} if(xtrx_input_report != nullptr && xtrx_input_report->isSet()){ isObjectUpdated = true; break;} + if(xtrx_output_report != nullptr && xtrx_output_report->isSet()){ isObjectUpdated = true; break;} }while(false); return isObjectUpdated; } diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h index d30dbe4e4..d092842b2 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h @@ -38,6 +38,7 @@ #include "SWGSDRdaemonSourceReport.h" #include "SWGSoapySDRReport.h" #include "SWGXtrxInputReport.h" +#include "SWGXtrxOutputReport.h" #include #include "SWGObject.h" @@ -115,6 +116,9 @@ public: SWGXtrxInputReport* getXtrxInputReport(); void setXtrxInputReport(SWGXtrxInputReport* xtrx_input_report); + SWGXtrxOutputReport* getXtrxOutputReport(); + void setXtrxOutputReport(SWGXtrxOutputReport* xtrx_output_report); + virtual bool isSet() override; @@ -176,6 +180,9 @@ private: SWGXtrxInputReport* xtrx_input_report; bool m_xtrx_input_report_isSet; + SWGXtrxOutputReport* xtrx_output_report; + bool m_xtrx_output_report_isSet; + }; } diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp index 5da19fa4e..7f3cb3d6d 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp @@ -80,6 +80,8 @@ SWGDeviceSettings::SWGDeviceSettings() { m_test_source_settings_isSet = false; xtrx_input_settings = nullptr; m_xtrx_input_settings_isSet = false; + xtrx_output_settings = nullptr; + m_xtrx_output_settings_isSet = false; } SWGDeviceSettings::~SWGDeviceSettings() { @@ -140,6 +142,8 @@ SWGDeviceSettings::init() { m_test_source_settings_isSet = false; xtrx_input_settings = new SWGXtrxInputSettings(); m_xtrx_input_settings_isSet = false; + xtrx_output_settings = new SWGXtrxOutputSettings(); + m_xtrx_output_settings_isSet = false; } void @@ -220,6 +224,9 @@ SWGDeviceSettings::cleanup() { if(xtrx_input_settings != nullptr) { delete xtrx_input_settings; } + if(xtrx_output_settings != nullptr) { + delete xtrx_output_settings; + } } SWGDeviceSettings* @@ -285,6 +292,8 @@ SWGDeviceSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&xtrx_input_settings, pJson["xtrxInputSettings"], "SWGXtrxInputSettings", "SWGXtrxInputSettings"); + ::SWGSDRangel::setValue(&xtrx_output_settings, pJson["xtrxOutputSettings"], "SWGXtrxOutputSettings", "SWGXtrxOutputSettings"); + } QString @@ -379,6 +388,9 @@ SWGDeviceSettings::asJsonObject() { if((xtrx_input_settings != nullptr) && (xtrx_input_settings->isSet())){ toJsonValue(QString("xtrxInputSettings"), xtrx_input_settings, obj, QString("SWGXtrxInputSettings")); } + if((xtrx_output_settings != nullptr) && (xtrx_output_settings->isSet())){ + toJsonValue(QString("xtrxOutputSettings"), xtrx_output_settings, obj, QString("SWGXtrxOutputSettings")); + } return obj; } @@ -643,6 +655,16 @@ SWGDeviceSettings::setXtrxInputSettings(SWGXtrxInputSettings* xtrx_input_setting this->m_xtrx_input_settings_isSet = true; } +SWGXtrxOutputSettings* +SWGDeviceSettings::getXtrxOutputSettings() { + return xtrx_output_settings; +} +void +SWGDeviceSettings::setXtrxOutputSettings(SWGXtrxOutputSettings* xtrx_output_settings) { + this->xtrx_output_settings = xtrx_output_settings; + this->m_xtrx_output_settings_isSet = true; +} + bool SWGDeviceSettings::isSet(){ @@ -674,6 +696,7 @@ SWGDeviceSettings::isSet(){ if(soapy_sdr_output_settings != nullptr && soapy_sdr_output_settings->isSet()){ isObjectUpdated = true; break;} if(test_source_settings != nullptr && test_source_settings->isSet()){ isObjectUpdated = true; break;} if(xtrx_input_settings != nullptr && xtrx_input_settings->isSet()){ isObjectUpdated = true; break;} + if(xtrx_output_settings != nullptr && xtrx_output_settings->isSet()){ isObjectUpdated = true; break;} }while(false); return isObjectUpdated; } diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h index 91cbbb1a4..4f5db49db 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h @@ -46,6 +46,7 @@ #include "SWGSoapySDROutputSettings.h" #include "SWGTestSourceSettings.h" #include "SWGXtrxInputSettings.h" +#include "SWGXtrxOutputSettings.h" #include #include "SWGObject.h" @@ -144,6 +145,9 @@ public: SWGXtrxInputSettings* getXtrxInputSettings(); void setXtrxInputSettings(SWGXtrxInputSettings* xtrx_input_settings); + SWGXtrxOutputSettings* getXtrxOutputSettings(); + void setXtrxOutputSettings(SWGXtrxOutputSettings* xtrx_output_settings); + virtual bool isSet() override; @@ -226,6 +230,9 @@ private: SWGXtrxInputSettings* xtrx_input_settings; bool m_xtrx_input_settings_isSet; + SWGXtrxOutputSettings* xtrx_output_settings; + bool m_xtrx_output_settings_isSet; + }; } diff --git a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h index 647a1f73a..c7ed9aeb6 100644 --- a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h +++ b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h @@ -131,6 +131,8 @@ #include "SWGWFMModSettings.h" #include "SWGXtrxInputReport.h" #include "SWGXtrxInputSettings.h" +#include "SWGXtrxOutputReport.h" +#include "SWGXtrxOutputSettings.h" namespace SWGSDRangel { @@ -486,6 +488,12 @@ namespace SWGSDRangel { if(QString("SWGXtrxInputSettings").compare(type) == 0) { return new SWGXtrxInputSettings(); } + if(QString("SWGXtrxOutputReport").compare(type) == 0) { + return new SWGXtrxOutputReport(); + } + if(QString("SWGXtrxOutputSettings").compare(type) == 0) { + return new SWGXtrxOutputSettings(); + } return nullptr; } diff --git a/swagger/sdrangel/code/qt5/client/SWGXtrxInputReport.cpp b/swagger/sdrangel/code/qt5/client/SWGXtrxInputReport.cpp index d32d791bc..95cbd36d6 100644 --- a/swagger/sdrangel/code/qt5/client/SWGXtrxInputReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGXtrxInputReport.cpp @@ -30,8 +30,6 @@ SWGXtrxInputReport::SWGXtrxInputReport(QString* json) { SWGXtrxInputReport::SWGXtrxInputReport() { success = 0; m_success_isSet = false; - stream_active = 0; - m_stream_active_isSet = false; fifo_size = 0; m_fifo_size_isSet = false; fifo_fill = 0; @@ -50,8 +48,6 @@ void SWGXtrxInputReport::init() { success = 0; m_success_isSet = false; - stream_active = 0; - m_stream_active_isSet = false; fifo_size = 0; m_fifo_size_isSet = false; fifo_fill = 0; @@ -69,7 +65,6 @@ SWGXtrxInputReport::cleanup() { - } SWGXtrxInputReport* @@ -85,8 +80,6 @@ void SWGXtrxInputReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&success, pJson["success"], "qint32", ""); - ::SWGSDRangel::setValue(&stream_active, pJson["streamActive"], "qint32", ""); - ::SWGSDRangel::setValue(&fifo_size, pJson["fifoSize"], "qint32", ""); ::SWGSDRangel::setValue(&fifo_fill, pJson["fifoFill"], "qint32", ""); @@ -114,9 +107,6 @@ SWGXtrxInputReport::asJsonObject() { if(m_success_isSet){ obj->insert("success", QJsonValue(success)); } - if(m_stream_active_isSet){ - obj->insert("streamActive", QJsonValue(stream_active)); - } if(m_fifo_size_isSet){ obj->insert("fifoSize", QJsonValue(fifo_size)); } @@ -143,16 +133,6 @@ SWGXtrxInputReport::setSuccess(qint32 success) { this->m_success_isSet = true; } -qint32 -SWGXtrxInputReport::getStreamActive() { - return stream_active; -} -void -SWGXtrxInputReport::setStreamActive(qint32 stream_active) { - this->stream_active = stream_active; - this->m_stream_active_isSet = true; -} - qint32 SWGXtrxInputReport::getFifoSize() { return fifo_size; @@ -199,7 +179,6 @@ SWGXtrxInputReport::isSet(){ bool isObjectUpdated = false; do{ if(m_success_isSet){ isObjectUpdated = true; break;} - if(m_stream_active_isSet){ isObjectUpdated = true; break;} if(m_fifo_size_isSet){ isObjectUpdated = true; break;} if(m_fifo_fill_isSet){ isObjectUpdated = true; break;} if(m_temperature_isSet){ isObjectUpdated = true; break;} diff --git a/swagger/sdrangel/code/qt5/client/SWGXtrxInputReport.h b/swagger/sdrangel/code/qt5/client/SWGXtrxInputReport.h index 1228534d6..4865824af 100644 --- a/swagger/sdrangel/code/qt5/client/SWGXtrxInputReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGXtrxInputReport.h @@ -44,9 +44,6 @@ public: qint32 getSuccess(); void setSuccess(qint32 success); - qint32 getStreamActive(); - void setStreamActive(qint32 stream_active); - qint32 getFifoSize(); void setFifoSize(qint32 fifo_size); @@ -66,9 +63,6 @@ private: qint32 success; bool m_success_isSet; - qint32 stream_active; - bool m_stream_active_isSet; - qint32 fifo_size; bool m_fifo_size_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGXtrxOutputReport.cpp b/swagger/sdrangel/code/qt5/client/SWGXtrxOutputReport.cpp new file mode 100644 index 000000000..fdb8a5c2b --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGXtrxOutputReport.cpp @@ -0,0 +1,190 @@ +/** + * 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.4.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 "SWGXtrxOutputReport.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGXtrxOutputReport::SWGXtrxOutputReport(QString* json) { + init(); + this->fromJson(*json); +} + +SWGXtrxOutputReport::SWGXtrxOutputReport() { + success = 0; + m_success_isSet = false; + fifo_size = 0; + m_fifo_size_isSet = false; + fifo_fill = 0; + m_fifo_fill_isSet = false; + temperature = 0.0f; + m_temperature_isSet = false; + gps_lock = 0; + m_gps_lock_isSet = false; +} + +SWGXtrxOutputReport::~SWGXtrxOutputReport() { + this->cleanup(); +} + +void +SWGXtrxOutputReport::init() { + success = 0; + m_success_isSet = false; + fifo_size = 0; + m_fifo_size_isSet = false; + fifo_fill = 0; + m_fifo_fill_isSet = false; + temperature = 0.0f; + m_temperature_isSet = false; + gps_lock = 0; + m_gps_lock_isSet = false; +} + +void +SWGXtrxOutputReport::cleanup() { + + + + + +} + +SWGXtrxOutputReport* +SWGXtrxOutputReport::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGXtrxOutputReport::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&success, pJson["success"], "qint32", ""); + + ::SWGSDRangel::setValue(&fifo_size, pJson["fifoSize"], "qint32", ""); + + ::SWGSDRangel::setValue(&fifo_fill, pJson["fifoFill"], "qint32", ""); + + ::SWGSDRangel::setValue(&temperature, pJson["temperature"], "float", ""); + + ::SWGSDRangel::setValue(&gps_lock, pJson["gpsLock"], "qint32", ""); + +} + +QString +SWGXtrxOutputReport::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGXtrxOutputReport::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_success_isSet){ + obj->insert("success", QJsonValue(success)); + } + if(m_fifo_size_isSet){ + obj->insert("fifoSize", QJsonValue(fifo_size)); + } + if(m_fifo_fill_isSet){ + obj->insert("fifoFill", QJsonValue(fifo_fill)); + } + if(m_temperature_isSet){ + obj->insert("temperature", QJsonValue(temperature)); + } + if(m_gps_lock_isSet){ + obj->insert("gpsLock", QJsonValue(gps_lock)); + } + + return obj; +} + +qint32 +SWGXtrxOutputReport::getSuccess() { + return success; +} +void +SWGXtrxOutputReport::setSuccess(qint32 success) { + this->success = success; + this->m_success_isSet = true; +} + +qint32 +SWGXtrxOutputReport::getFifoSize() { + return fifo_size; +} +void +SWGXtrxOutputReport::setFifoSize(qint32 fifo_size) { + this->fifo_size = fifo_size; + this->m_fifo_size_isSet = true; +} + +qint32 +SWGXtrxOutputReport::getFifoFill() { + return fifo_fill; +} +void +SWGXtrxOutputReport::setFifoFill(qint32 fifo_fill) { + this->fifo_fill = fifo_fill; + this->m_fifo_fill_isSet = true; +} + +float +SWGXtrxOutputReport::getTemperature() { + return temperature; +} +void +SWGXtrxOutputReport::setTemperature(float temperature) { + this->temperature = temperature; + this->m_temperature_isSet = true; +} + +qint32 +SWGXtrxOutputReport::getGpsLock() { + return gps_lock; +} +void +SWGXtrxOutputReport::setGpsLock(qint32 gps_lock) { + this->gps_lock = gps_lock; + this->m_gps_lock_isSet = true; +} + + +bool +SWGXtrxOutputReport::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_success_isSet){ isObjectUpdated = true; break;} + if(m_fifo_size_isSet){ isObjectUpdated = true; break;} + if(m_fifo_fill_isSet){ isObjectUpdated = true; break;} + if(m_temperature_isSet){ isObjectUpdated = true; break;} + if(m_gps_lock_isSet){ isObjectUpdated = true; break;} + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGXtrxOutputReport.h b/swagger/sdrangel/code/qt5/client/SWGXtrxOutputReport.h new file mode 100644 index 000000000..0dcc20a70 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGXtrxOutputReport.h @@ -0,0 +1,82 @@ +/** + * 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.4.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. + */ + +/* + * SWGXtrxOutputReport.h + * + * XTRX + */ + +#ifndef SWGXtrxOutputReport_H_ +#define SWGXtrxOutputReport_H_ + +#include + + + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGXtrxOutputReport: public SWGObject { +public: + SWGXtrxOutputReport(); + SWGXtrxOutputReport(QString* json); + virtual ~SWGXtrxOutputReport(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGXtrxOutputReport* fromJson(QString &jsonString) override; + + qint32 getSuccess(); + void setSuccess(qint32 success); + + qint32 getFifoSize(); + void setFifoSize(qint32 fifo_size); + + qint32 getFifoFill(); + void setFifoFill(qint32 fifo_fill); + + float getTemperature(); + void setTemperature(float temperature); + + qint32 getGpsLock(); + void setGpsLock(qint32 gps_lock); + + + virtual bool isSet() override; + +private: + qint32 success; + bool m_success_isSet; + + qint32 fifo_size; + bool m_fifo_size_isSet; + + qint32 fifo_fill; + bool m_fifo_fill_isSet; + + float temperature; + bool m_temperature_isSet; + + qint32 gps_lock; + bool m_gps_lock_isSet; + +}; + +} + +#endif /* SWGXtrxOutputReport_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGXtrxOutputSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGXtrxOutputSettings.cpp new file mode 100644 index 000000000..157cd9f85 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGXtrxOutputSettings.cpp @@ -0,0 +1,423 @@ +/** + * 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.4.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 "SWGXtrxOutputSettings.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGXtrxOutputSettings::SWGXtrxOutputSettings(QString* json) { + init(); + this->fromJson(*json); +} + +SWGXtrxOutputSettings::SWGXtrxOutputSettings() { + center_frequency = 0L; + m_center_frequency_isSet = false; + dev_sample_rate = 0; + m_dev_sample_rate_isSet = false; + log2_hard_interp = 0; + m_log2_hard_interp_isSet = false; + log2_soft_interp = 0; + m_log2_soft_interp_isSet = false; + lpf_bw = 0; + m_lpf_bw_isSet = false; + gain = 0; + m_gain_isSet = false; + nco_enable = 0; + m_nco_enable_isSet = false; + nco_frequency = 0; + m_nco_frequency_isSet = false; + antenna_path = 0; + m_antenna_path_isSet = false; + ext_clock = 0; + m_ext_clock_isSet = false; + ext_clock_freq = 0; + m_ext_clock_freq_isSet = false; + pwrmode = 0; + m_pwrmode_isSet = false; + use_reverse_api = 0; + m_use_reverse_api_isSet = false; + reverse_api_address = nullptr; + m_reverse_api_address_isSet = false; + reverse_api_port = 0; + m_reverse_api_port_isSet = false; + reverse_api_device_index = 0; + m_reverse_api_device_index_isSet = false; +} + +SWGXtrxOutputSettings::~SWGXtrxOutputSettings() { + this->cleanup(); +} + +void +SWGXtrxOutputSettings::init() { + center_frequency = 0L; + m_center_frequency_isSet = false; + dev_sample_rate = 0; + m_dev_sample_rate_isSet = false; + log2_hard_interp = 0; + m_log2_hard_interp_isSet = false; + log2_soft_interp = 0; + m_log2_soft_interp_isSet = false; + lpf_bw = 0; + m_lpf_bw_isSet = false; + gain = 0; + m_gain_isSet = false; + nco_enable = 0; + m_nco_enable_isSet = false; + nco_frequency = 0; + m_nco_frequency_isSet = false; + antenna_path = 0; + m_antenna_path_isSet = false; + ext_clock = 0; + m_ext_clock_isSet = false; + ext_clock_freq = 0; + m_ext_clock_freq_isSet = false; + pwrmode = 0; + m_pwrmode_isSet = false; + use_reverse_api = 0; + m_use_reverse_api_isSet = false; + reverse_api_address = new QString(""); + m_reverse_api_address_isSet = false; + reverse_api_port = 0; + m_reverse_api_port_isSet = false; + reverse_api_device_index = 0; + m_reverse_api_device_index_isSet = false; +} + +void +SWGXtrxOutputSettings::cleanup() { + + + + + + + + + + + + + + if(reverse_api_address != nullptr) { + delete reverse_api_address; + } + + +} + +SWGXtrxOutputSettings* +SWGXtrxOutputSettings::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGXtrxOutputSettings::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(¢er_frequency, pJson["centerFrequency"], "qint64", ""); + + ::SWGSDRangel::setValue(&dev_sample_rate, pJson["devSampleRate"], "qint32", ""); + + ::SWGSDRangel::setValue(&log2_hard_interp, pJson["log2HardInterp"], "qint32", ""); + + ::SWGSDRangel::setValue(&log2_soft_interp, pJson["log2SoftInterp"], "qint32", ""); + + ::SWGSDRangel::setValue(&lpf_bw, pJson["lpfBW"], "qint32", ""); + + ::SWGSDRangel::setValue(&gain, pJson["gain"], "qint32", ""); + + ::SWGSDRangel::setValue(&nco_enable, pJson["ncoEnable"], "qint32", ""); + + ::SWGSDRangel::setValue(&nco_frequency, pJson["ncoFrequency"], "qint32", ""); + + ::SWGSDRangel::setValue(&antenna_path, pJson["antennaPath"], "qint32", ""); + + ::SWGSDRangel::setValue(&ext_clock, pJson["extClock"], "qint32", ""); + + ::SWGSDRangel::setValue(&ext_clock_freq, pJson["extClockFreq"], "qint32", ""); + + ::SWGSDRangel::setValue(&pwrmode, pJson["pwrmode"], "qint32", ""); + + ::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString"); + + ::SWGSDRangel::setValue(&reverse_api_port, pJson["reverseAPIPort"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_device_index, pJson["reverseAPIDeviceIndex"], "qint32", ""); + +} + +QString +SWGXtrxOutputSettings::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGXtrxOutputSettings::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_log2_hard_interp_isSet){ + obj->insert("log2HardInterp", QJsonValue(log2_hard_interp)); + } + if(m_log2_soft_interp_isSet){ + obj->insert("log2SoftInterp", QJsonValue(log2_soft_interp)); + } + if(m_lpf_bw_isSet){ + obj->insert("lpfBW", QJsonValue(lpf_bw)); + } + if(m_gain_isSet){ + obj->insert("gain", QJsonValue(gain)); + } + if(m_nco_enable_isSet){ + obj->insert("ncoEnable", QJsonValue(nco_enable)); + } + if(m_nco_frequency_isSet){ + obj->insert("ncoFrequency", QJsonValue(nco_frequency)); + } + if(m_antenna_path_isSet){ + obj->insert("antennaPath", QJsonValue(antenna_path)); + } + if(m_ext_clock_isSet){ + obj->insert("extClock", QJsonValue(ext_clock)); + } + if(m_ext_clock_freq_isSet){ + obj->insert("extClockFreq", QJsonValue(ext_clock_freq)); + } + if(m_pwrmode_isSet){ + obj->insert("pwrmode", QJsonValue(pwrmode)); + } + if(m_use_reverse_api_isSet){ + obj->insert("useReverseAPI", QJsonValue(use_reverse_api)); + } + if(reverse_api_address != nullptr && *reverse_api_address != QString("")){ + toJsonValue(QString("reverseAPIAddress"), reverse_api_address, obj, QString("QString")); + } + if(m_reverse_api_port_isSet){ + obj->insert("reverseAPIPort", QJsonValue(reverse_api_port)); + } + if(m_reverse_api_device_index_isSet){ + obj->insert("reverseAPIDeviceIndex", QJsonValue(reverse_api_device_index)); + } + + return obj; +} + +qint64 +SWGXtrxOutputSettings::getCenterFrequency() { + return center_frequency; +} +void +SWGXtrxOutputSettings::setCenterFrequency(qint64 center_frequency) { + this->center_frequency = center_frequency; + this->m_center_frequency_isSet = true; +} + +qint32 +SWGXtrxOutputSettings::getDevSampleRate() { + return dev_sample_rate; +} +void +SWGXtrxOutputSettings::setDevSampleRate(qint32 dev_sample_rate) { + this->dev_sample_rate = dev_sample_rate; + this->m_dev_sample_rate_isSet = true; +} + +qint32 +SWGXtrxOutputSettings::getLog2HardInterp() { + return log2_hard_interp; +} +void +SWGXtrxOutputSettings::setLog2HardInterp(qint32 log2_hard_interp) { + this->log2_hard_interp = log2_hard_interp; + this->m_log2_hard_interp_isSet = true; +} + +qint32 +SWGXtrxOutputSettings::getLog2SoftInterp() { + return log2_soft_interp; +} +void +SWGXtrxOutputSettings::setLog2SoftInterp(qint32 log2_soft_interp) { + this->log2_soft_interp = log2_soft_interp; + this->m_log2_soft_interp_isSet = true; +} + +qint32 +SWGXtrxOutputSettings::getLpfBw() { + return lpf_bw; +} +void +SWGXtrxOutputSettings::setLpfBw(qint32 lpf_bw) { + this->lpf_bw = lpf_bw; + this->m_lpf_bw_isSet = true; +} + +qint32 +SWGXtrxOutputSettings::getGain() { + return gain; +} +void +SWGXtrxOutputSettings::setGain(qint32 gain) { + this->gain = gain; + this->m_gain_isSet = true; +} + +qint32 +SWGXtrxOutputSettings::getNcoEnable() { + return nco_enable; +} +void +SWGXtrxOutputSettings::setNcoEnable(qint32 nco_enable) { + this->nco_enable = nco_enable; + this->m_nco_enable_isSet = true; +} + +qint32 +SWGXtrxOutputSettings::getNcoFrequency() { + return nco_frequency; +} +void +SWGXtrxOutputSettings::setNcoFrequency(qint32 nco_frequency) { + this->nco_frequency = nco_frequency; + this->m_nco_frequency_isSet = true; +} + +qint32 +SWGXtrxOutputSettings::getAntennaPath() { + return antenna_path; +} +void +SWGXtrxOutputSettings::setAntennaPath(qint32 antenna_path) { + this->antenna_path = antenna_path; + this->m_antenna_path_isSet = true; +} + +qint32 +SWGXtrxOutputSettings::getExtClock() { + return ext_clock; +} +void +SWGXtrxOutputSettings::setExtClock(qint32 ext_clock) { + this->ext_clock = ext_clock; + this->m_ext_clock_isSet = true; +} + +qint32 +SWGXtrxOutputSettings::getExtClockFreq() { + return ext_clock_freq; +} +void +SWGXtrxOutputSettings::setExtClockFreq(qint32 ext_clock_freq) { + this->ext_clock_freq = ext_clock_freq; + this->m_ext_clock_freq_isSet = true; +} + +qint32 +SWGXtrxOutputSettings::getPwrmode() { + return pwrmode; +} +void +SWGXtrxOutputSettings::setPwrmode(qint32 pwrmode) { + this->pwrmode = pwrmode; + this->m_pwrmode_isSet = true; +} + +qint32 +SWGXtrxOutputSettings::getUseReverseApi() { + return use_reverse_api; +} +void +SWGXtrxOutputSettings::setUseReverseApi(qint32 use_reverse_api) { + this->use_reverse_api = use_reverse_api; + this->m_use_reverse_api_isSet = true; +} + +QString* +SWGXtrxOutputSettings::getReverseApiAddress() { + return reverse_api_address; +} +void +SWGXtrxOutputSettings::setReverseApiAddress(QString* reverse_api_address) { + this->reverse_api_address = reverse_api_address; + this->m_reverse_api_address_isSet = true; +} + +qint32 +SWGXtrxOutputSettings::getReverseApiPort() { + return reverse_api_port; +} +void +SWGXtrxOutputSettings::setReverseApiPort(qint32 reverse_api_port) { + this->reverse_api_port = reverse_api_port; + this->m_reverse_api_port_isSet = true; +} + +qint32 +SWGXtrxOutputSettings::getReverseApiDeviceIndex() { + return reverse_api_device_index; +} +void +SWGXtrxOutputSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) { + this->reverse_api_device_index = reverse_api_device_index; + this->m_reverse_api_device_index_isSet = true; +} + + +bool +SWGXtrxOutputSettings::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_center_frequency_isSet){ isObjectUpdated = true; break;} + if(m_dev_sample_rate_isSet){ isObjectUpdated = true; break;} + if(m_log2_hard_interp_isSet){ isObjectUpdated = true; break;} + if(m_log2_soft_interp_isSet){ isObjectUpdated = true; break;} + if(m_lpf_bw_isSet){ isObjectUpdated = true; break;} + if(m_gain_isSet){ isObjectUpdated = true; break;} + if(m_nco_enable_isSet){ isObjectUpdated = true; break;} + if(m_nco_frequency_isSet){ isObjectUpdated = true; break;} + if(m_antenna_path_isSet){ isObjectUpdated = true; break;} + if(m_ext_clock_isSet){ isObjectUpdated = true; break;} + if(m_ext_clock_freq_isSet){ isObjectUpdated = true; break;} + if(m_pwrmode_isSet){ isObjectUpdated = true; break;} + if(m_use_reverse_api_isSet){ isObjectUpdated = true; break;} + if(reverse_api_address != nullptr && *reverse_api_address != QString("")){ isObjectUpdated = true; break;} + if(m_reverse_api_port_isSet){ isObjectUpdated = true; break;} + if(m_reverse_api_device_index_isSet){ isObjectUpdated = true; break;} + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGXtrxOutputSettings.h b/swagger/sdrangel/code/qt5/client/SWGXtrxOutputSettings.h new file mode 100644 index 000000000..78087158a --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGXtrxOutputSettings.h @@ -0,0 +1,149 @@ +/** + * 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.4.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. + */ + +/* + * SWGXtrxOutputSettings.h + * + * XTRX + */ + +#ifndef SWGXtrxOutputSettings_H_ +#define SWGXtrxOutputSettings_H_ + +#include + + +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGXtrxOutputSettings: public SWGObject { +public: + SWGXtrxOutputSettings(); + SWGXtrxOutputSettings(QString* json); + virtual ~SWGXtrxOutputSettings(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGXtrxOutputSettings* fromJson(QString &jsonString) override; + + qint64 getCenterFrequency(); + void setCenterFrequency(qint64 center_frequency); + + qint32 getDevSampleRate(); + void setDevSampleRate(qint32 dev_sample_rate); + + qint32 getLog2HardInterp(); + void setLog2HardInterp(qint32 log2_hard_interp); + + qint32 getLog2SoftInterp(); + void setLog2SoftInterp(qint32 log2_soft_interp); + + qint32 getLpfBw(); + void setLpfBw(qint32 lpf_bw); + + qint32 getGain(); + void setGain(qint32 gain); + + qint32 getNcoEnable(); + void setNcoEnable(qint32 nco_enable); + + qint32 getNcoFrequency(); + void setNcoFrequency(qint32 nco_frequency); + + qint32 getAntennaPath(); + void setAntennaPath(qint32 antenna_path); + + qint32 getExtClock(); + void setExtClock(qint32 ext_clock); + + qint32 getExtClockFreq(); + void setExtClockFreq(qint32 ext_clock_freq); + + qint32 getPwrmode(); + void setPwrmode(qint32 pwrmode); + + qint32 getUseReverseApi(); + void setUseReverseApi(qint32 use_reverse_api); + + QString* getReverseApiAddress(); + void setReverseApiAddress(QString* reverse_api_address); + + qint32 getReverseApiPort(); + void setReverseApiPort(qint32 reverse_api_port); + + qint32 getReverseApiDeviceIndex(); + void setReverseApiDeviceIndex(qint32 reverse_api_device_index); + + + virtual bool isSet() override; + +private: + qint64 center_frequency; + bool m_center_frequency_isSet; + + qint32 dev_sample_rate; + bool m_dev_sample_rate_isSet; + + qint32 log2_hard_interp; + bool m_log2_hard_interp_isSet; + + qint32 log2_soft_interp; + bool m_log2_soft_interp_isSet; + + qint32 lpf_bw; + bool m_lpf_bw_isSet; + + qint32 gain; + bool m_gain_isSet; + + qint32 nco_enable; + bool m_nco_enable_isSet; + + qint32 nco_frequency; + bool m_nco_frequency_isSet; + + qint32 antenna_path; + bool m_antenna_path_isSet; + + qint32 ext_clock; + bool m_ext_clock_isSet; + + qint32 ext_clock_freq; + bool m_ext_clock_freq_isSet; + + qint32 pwrmode; + bool m_pwrmode_isSet; + + qint32 use_reverse_api; + bool m_use_reverse_api_isSet; + + QString* reverse_api_address; + bool m_reverse_api_address_isSet; + + qint32 reverse_api_port; + bool m_reverse_api_port_isSet; + + qint32 reverse_api_device_index; + bool m_reverse_api_device_index_isSet; + +}; + +} + +#endif /* SWGXtrxOutputSettings_H_ */