From 7aebff108231ba1bdac438e12bcbb25f58488df6 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Sun, 11 Apr 2021 21:21:36 +0100 Subject: [PATCH] Add SDRplay V3 API sample source. --- CMakeLists.txt | 11 +- cmake/Modules/FindSDRplay.cmake | 27 + cmake/cpack/CMakeLists.txt | 13 + doc/img/SDRPlayV3_plugin.png | Bin 0 -> 12128 bytes external/CMakeLists.txt | 19 + plugins/samplesource/CMakeLists.txt | 4 + plugins/samplesource/sdrplayv3/CMakeLists.txt | 59 + plugins/samplesource/sdrplayv3/readme.md | 118 ++ .../samplesource/sdrplayv3/sdrplayv3gui.cpp | 491 ++++++ plugins/samplesource/sdrplayv3/sdrplayv3gui.h | 99 ++ .../samplesource/sdrplayv3/sdrplayv3gui.ui | 799 ++++++++++ .../samplesource/sdrplayv3/sdrplayv3input.cpp | 1312 +++++++++++++++++ .../samplesource/sdrplayv3/sdrplayv3input.h | 200 +++ .../sdrplayv3/sdrplayv3plugin.cpp | 185 +++ .../samplesource/sdrplayv3/sdrplayv3plugin.h | 54 + .../sdrplayv3/sdrplayv3settings.cpp | 139 ++ .../sdrplayv3/sdrplayv3settings.h | 88 ++ .../sdrplayv3/sdrplayv3thread.cpp | 220 +++ .../samplesource/sdrplayv3/sdrplayv3thread.h | 66 + .../sdrplayv3/sdrplayv3webapiadapter.cpp | 53 + .../sdrplayv3/sdrplayv3webapiadapter.h | 45 + sdrbase/webapi/webapirequestmapper.cpp | 7 + sdrbase/webapi/webapiutils.cpp | 3 + .../api/swagger/include/DeviceReports.yaml | 2 + .../api/swagger/include/DeviceSettings.yaml | 2 + .../api/swagger/include/SDRPlayV3.yaml | 61 + swagger/sdrangel/code/html2/index.html | 158 +- .../code/qt5/client/SWGDeviceReport.cpp | 25 + .../code/qt5/client/SWGDeviceReport.h | 7 + .../code/qt5/client/SWGDeviceSettings.cpp | 25 + .../code/qt5/client/SWGDeviceSettings.h | 7 + .../code/qt5/client/SWGModelFactory.h | 8 + .../code/qt5/client/SWGSDRPlayV3Report.cpp | 143 ++ .../code/qt5/client/SWGSDRPlayV3Report.h | 67 + .../code/qt5/client/SWGSDRPlayV3Settings.cpp | 593 ++++++++ .../code/qt5/client/SWGSDRPlayV3Settings.h | 185 +++ 36 files changed, 5282 insertions(+), 13 deletions(-) create mode 100644 cmake/Modules/FindSDRplay.cmake create mode 100644 doc/img/SDRPlayV3_plugin.png create mode 100644 plugins/samplesource/sdrplayv3/CMakeLists.txt create mode 100644 plugins/samplesource/sdrplayv3/readme.md create mode 100644 plugins/samplesource/sdrplayv3/sdrplayv3gui.cpp create mode 100644 plugins/samplesource/sdrplayv3/sdrplayv3gui.h create mode 100644 plugins/samplesource/sdrplayv3/sdrplayv3gui.ui create mode 100644 plugins/samplesource/sdrplayv3/sdrplayv3input.cpp create mode 100644 plugins/samplesource/sdrplayv3/sdrplayv3input.h create mode 100644 plugins/samplesource/sdrplayv3/sdrplayv3plugin.cpp create mode 100644 plugins/samplesource/sdrplayv3/sdrplayv3plugin.h create mode 100644 plugins/samplesource/sdrplayv3/sdrplayv3settings.cpp create mode 100644 plugins/samplesource/sdrplayv3/sdrplayv3settings.h create mode 100644 plugins/samplesource/sdrplayv3/sdrplayv3thread.cpp create mode 100644 plugins/samplesource/sdrplayv3/sdrplayv3thread.h create mode 100644 plugins/samplesource/sdrplayv3/sdrplayv3webapiadapter.cpp create mode 100644 plugins/samplesource/sdrplayv3/sdrplayv3webapiadapter.h create mode 100644 swagger/sdrangel/api/swagger/include/SDRPlayV3.yaml create mode 100644 swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Report.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Report.h create mode 100644 swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Settings.cpp create mode 100644 swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Settings.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 67cb2c7f5..d2a59ed20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ option(ENABLE_LIMESUITE "Enable limesuite support" ON) option(ENABLE_MIRISDR "Enable LibMiri for old SDRPlay" ON) option(ENABLE_PERSEUS "Enable perseus support" ON) option(ENABLE_RTLSDR "Enable rtl-sdr support" ON) +option(ENABLE_SDRPLAY "Enable SDRplay support" ON) option(ENABLE_SOAPYSDR "Enable SoapySDR support" ON) option(ENABLE_XTRX "Enable XTRX support" ON) option(ENABLE_PACK_MIRSDRAPI "Enable inclusion of the mirsdr-api library - for personal use only" OFF) @@ -82,7 +83,7 @@ add_definitions("-DSDRANGEL_VERSION=\"${sdrangel_VERSION}\"") # configure CPACK information set(CPACK_PACKAGE_NAME "${CMAKE_PROJECT_NAME}") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "SDR Rx/Tx software for Airspy, Airspy HF+, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "SDR Rx/Tx software for Airspy, Airspy HF+, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay, USRP and FunCube") set(CPACK_PACKAGE_VENDOR "${COMPANY}") set(CPACK_PACKAGE_CONTACT "https://github.com/f4exb/sdrangel") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/Readme.md") @@ -249,6 +250,11 @@ elseif (WIN32) # LimeSuite FX3 support set(FX3SDK_DIR "${EXTERNAL_LIBRARY_FOLDER}/FX3SDK" CACHE INTERNAL "") + set(SDRPLAY_FOUND ON CACHE INTERNAL "") + set(SDRPLAY_INCLUDE_DIR "${EXTERNAL_LIBRARY_FOLDER}/sdrplay/inc" CACHE INTERNAL "") + set(SDRPLAY_LIBRARIES "${EXTERNAL_LIBRARY_FOLDER}/sdrplay/x64/sdrplay_api.lib" CACHE INTERNAL "") + set(SDRPLAY_DLL_DIR "${EXTERNAL_LIBRARY_FOLDER}/sdrplay/x64/" CACHE INTERNAL "") + # used on fixup_bundle phase set(WINDOWS_FIXUP_BUNDLE_LIB_DIRS "${EXTERNAL_LIBRARY_FOLDER}/fftw-3" @@ -403,6 +409,9 @@ endif() if(ENABLE_RTLSDR) find_package(LibRTLSDR) endif() +if(ENABLE_SDRPLAY) + find_package(SDRplay) +endif() if(ENABLE_SOAPYSDR) find_package(SoapySDR) endif() diff --git a/cmake/Modules/FindSDRplay.cmake b/cmake/Modules/FindSDRplay.cmake new file mode 100644 index 000000000..226d8977a --- /dev/null +++ b/cmake/Modules/FindSDRplay.cmake @@ -0,0 +1,27 @@ +IF(NOT SDRPLAY_FOUND) + + FIND_PATH( + SDRPLAY_INCLUDE_DIR + NAMES sdrplay_api.h + HINTS ${SDRPLAY_DIR}/inc + PATHS /usr/local/include + /usr/include + ) + + FIND_LIBRARY( + SDRPLAY_LIBRARIES + NAMES sdrplay_api + HINTS ${SDRPLAY_DIR}/x86_64 + PATHS /usr/local/lib + /usr/lib + /usr/lib64 + ) + + message(STATUS "SDRPLAY LIBRARIES " ${SDRPLAY_LIBRARIES}) + message(STATUS "SDRPLAY INCLUDE DIRS " ${SDRPLAY_INCLUDE_DIR}) + + INCLUDE(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDRPLAY DEFAULT_MSG SDRPLAY_LIBRARIES SDRPLAY_INCLUDE_DIR) + MARK_AS_ADVANCED(SDRPLAY_LIBRARIES SDRPLAY_INCLUDE_DIR) + +ENDIF(NOT SDRPLAY_FOUND) diff --git a/cmake/cpack/CMakeLists.txt b/cmake/cpack/CMakeLists.txt index 259853eeb..986d25b91 100644 --- a/cmake/cpack/CMakeLists.txt +++ b/cmake/cpack/CMakeLists.txt @@ -225,6 +225,16 @@ elseif(WIN32 OR MINGW) endforeach(uhd_dll) endif() + if(ENABLE_SDRPLAY AND SDRPLAY_FOUND) + file(GLOB SDRPLAY_DLLS "${SDRPLAY_DLL_DIR}/*${CMAKE_SHARED_LIBRARY_SUFFIX}") + foreach(sdrplay_dll ${SDRPLAY_DLLS}) + get_filename_component(sdrplay_dll_name "${sdrplay_dll}" NAME) + add_custom_target(copy_sdrplay_${sdrplay_dll_name} ALL + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${sdrplay_dll}" "${SDRANGEL_BINARY_BIN_DIR}/" + ) + endforeach(sdrplay_dll) + endif() + file(GLOB OPENSSL_DLLS "${OPENSSL_DLL_DIR}/*${CMAKE_SHARED_LIBRARY_SUFFIX}") foreach(openssl_dll ${OPENSSL_DLLS}) get_filename_component(openssl_dll_name "${openssl_dll}" NAME) @@ -277,6 +287,9 @@ elseif(WIN32 OR MINGW) # uhd install(DIRECTORY "${UHD_DLL_DIR}/" DESTINATION "${INSTALL_LIB_DIR}" FILES_MATCHING PATTERN "*${CMAKE_SHARED_LIBRARY_SUFFIX}") + # sdrplay + install(DIRECTORY "${SDRPLAY_DLL_DIR}/" DESTINATION "${INSTALL_LIB_DIR}" + FILES_MATCHING PATTERN "*${CMAKE_SHARED_LIBRARY_SUFFIX}") # OpenSSL install(DIRECTORY "${OPENSSL_DLL_DIR}/" DESTINATION "${INSTALL_LIB_DIR}" FILES_MATCHING PATTERN "*${CMAKE_SHARED_LIBRARY_SUFFIX}") diff --git a/doc/img/SDRPlayV3_plugin.png b/doc/img/SDRPlayV3_plugin.png new file mode 100644 index 0000000000000000000000000000000000000000..42558d3a0789d5118a93004d9137c35bc655edbd GIT binary patch literal 12128 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 D_G2At literal 0 HcmV?d00001 diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 7dd516463..7dfb0d26d 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -19,6 +19,7 @@ set(LIBIIO_TAG 826563e41b5ce9890b75506f672017de8d76d52d) set(AIRSPYHF_TAG "1.1.5") set(PERSEUS_TAG afefa23e3140ac79d845acb68cf0beeb86d09028) set(MIRISDR_TAG "v1.1.2") +set(SDRPLAY_TAG "3.07") set(PTHREADS4W_TAG "Version-2-11-0-release") set(RTLSDR_TAG be1d1206bfb6e6c41f7d91b20b77e20f929fa6a7) @@ -590,6 +591,24 @@ if (LINUX) ) endif (NOT LIBMIRISDR_FOUND OR LIBMIRISDR_EXTERNAL) + if (NOT SDRPLAY_FOUND OR SDRPLAY_EXTERNAL) + set(SDRPLAY_FOUND ON CACHE INTERNAL "") + set(SDRPLAY_EXTERNAL ON CACHE INTERNAL "") + set(SDRPLAY_INCLUDE_DIR "${EXTERNAL_BUILD_LIBRARIES}/sdrplayapi/inc" CACHE INTERNAL "") + set(SDRPLAY_LIBRARIES "${EXTERNAL_BUILD_LIBRARIES}/sdrplayapi/x86_64/libsdrplay_api.so.3.07" CACHE INTERNAL "") + ExternalProject_Add(sdrplayapi + GIT_REPOSITORY https://github.com/srcejon/sdrplayapi.git + GIT_TAG ${SDRPLAY_TAG} + PREFIX "${EXTERNAL_BUILD_LIBRARIES}/sdrplayapi" + CMAKE_ARGS ${COMMON_CMAKE_ARGS} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + BUILD_BYPRODUCTS "" + INSTALL_COMMAND "" + TEST_COMMAND "" + ) + endif (NOT SDRPLAY_FOUND OR SDRPLAY_EXTERNAL) + endif (LINUX) if (WIN32 OR APPLE) diff --git a/plugins/samplesource/CMakeLists.txt b/plugins/samplesource/CMakeLists.txt index dbaecd365..a903dd4ee 100644 --- a/plugins/samplesource/CMakeLists.txt +++ b/plugins/samplesource/CMakeLists.txt @@ -38,6 +38,10 @@ if(ENABLE_MIRISDR AND LIBMIRISDR_FOUND) add_subdirectory(sdrplay) endif() +if(ENABLE_SDRPLAY AND SDRPLAY_FOUND) + add_subdirectory(sdrplayv3) +endif() + if(ENABLE_PERSEUS AND LIBPERSEUS_FOUND AND RX_SAMPLE_24BIT) add_subdirectory(perseus) endif() diff --git a/plugins/samplesource/sdrplayv3/CMakeLists.txt b/plugins/samplesource/sdrplayv3/CMakeLists.txt new file mode 100644 index 000000000..a6923c3bb --- /dev/null +++ b/plugins/samplesource/sdrplayv3/CMakeLists.txt @@ -0,0 +1,59 @@ +project(sdrplay) + +set(sdrplayv3_SOURCES + sdrplayv3input.cpp + sdrplayv3plugin.cpp + sdrplayv3settings.cpp + sdrplayv3webapiadapter.cpp + sdrplayv3thread.cpp +) + +set(sdrplayv3_HEADERS + sdrplayv3input.h + sdrplayv3plugin.h + sdrplayv3settings.h + sdrplayv3webapiadapter.h + sdrplayv3thread.h +) + +include_directories( + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${SDRPLAY_INCLUDE_DIR} +) + +if(NOT SERVER_MODE) + set(sdrplayv3_SOURCES + ${sdrplayv3_SOURCES} + sdrplayv3gui.cpp + sdrplayv3gui.ui + ) + set(sdrplayv3_HEADERS + ${sdrplayv3_HEADERS} + sdrplayv3gui.h + ) + + set(TARGET_NAME inputsdrplayv3) + set(TARGET_LIB "Qt5::Widgets") + set(TARGET_LIB_GUI "sdrgui") + set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) +else() + set(TARGET_NAME inputsdrplayv3srv) + set(TARGET_LIB "") + set(TARGET_LIB_GUI "") + set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR}) +endif() + +add_library(${TARGET_NAME} SHARED + ${sdrplayv3_SOURCES} +) + +target_link_libraries(${TARGET_NAME} + Qt5::Core + ${TARGET_LIB} + sdrbase + ${TARGET_LIB_GUI} + swagger + ${SDRPLAY_LIBRARIES} +) + +install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER}) diff --git a/plugins/samplesource/sdrplayv3/readme.md b/plugins/samplesource/sdrplayv3/readme.md new file mode 100644 index 000000000..10dcc43cc --- /dev/null +++ b/plugins/samplesource/sdrplayv3/readme.md @@ -0,0 +1,118 @@ +

SDRplay plugin

+ +

Introduction

+ +This plugin supports input from SDRplay RSP devices using V3 of SDRplay's API, including RSP1, RSP1A, RSP2, RSPduo and RSPdx. + +

Interface

+ +![SDRplay v3 plugin GUI](../../../doc/img/SDRPlayV3_plugin.png) + +

1: Start/Stop

+ +Device start / stop button. + + - Blue triangle icon: device is ready and can be started + - Green square icon: device is running and can be stopped + - Magenta (or pink) square icon: an error occurred. In the case the device was accidentally disconnected you may click on the icon to stop, plug back in, check the source on the sampling devices control panel and start again. + +

2: Sample rate

+ +This is the sample rate at which IQ samples are transfered from the device to SDRangel, in kS/s (k). + +

3: Center frequency

+ +This is the center frequency of reception in kHz. + +

4: Local oscillator frequency correction

+ +This is the correction in tenths of ppm steps. + +

5: Tuner selection

+ +Selects which tuner is used for input. For RSPduo this can be 1 or 2. Other RSP devices only have a single tuner. + +

6: Antenna port

+ +Selects which antenna port is used. The antenna ports available depend upon the RSP device and tuner selected. + +

7: DC offset correction

+ +Check this button to enable DC offset correction. + +

8: IQ imbalance correction

+ +Check this button to enable IQ imbalance correction. + +

9: External reference clock output

+ +Enable reference clock output. This is only available for RSP2 and DSPduo. + +

10: Bias tee

+ +Enable bias tee. This is only available for RSP1A, RSP2, RSPduo tuner 2 and RSPdx. + +

11: AM notch filter

+ +Enable AM notch filter. This is only available for RSPduo tuner 1. + +

12: MW/FM notch filter

+ +Enable MW/FM notch filter. This is only available for RSP1A, RSP2, RSPduo and RSPdx. + +

13: DAB notch filter

+ +Enable DAB notch filter. This is only available for RSP1A, RSPduo and RSPdx. + +

14: IF bandwidth

+ +This selects the IF filter bandwidth. The following bandwidths are available: + + - 200 kHz + - 300 kHz + - 600 kHz + - 1536 kHz + - 5000 kHz + - 6000 kHz + - 7000 kHz + - 8000 kHz + +

15: IF frequency

+ +This selects the IF frequency between these values: + + - 0 for zero IF + - 450 kHz: you have to set sample rate to 1792 kHz (16) and use decimation (17) with an infradyne position (18) + - 1620 kHz: you have to set sample rate to 6400 kHz (16) and use decimation (17) with an infradyne position (18) + - 2048 kHz: you have to set sample rate to 8192 kHz (16) and use decimation (17) with an infradyne position (18) + +

16: Sample rate

+ +Sets the ADC IQ sample rats from 2M to 10.66M Hz. + +

17: Decimation

+ +Decimation in powers of two from 1 (no decimation) to 64. + +

18: Decimated bandpass center frequency position relative the SDRplay center frequency

+ + - **Cen**: the decimation operation takes place around the SDRplay center frequency Fs. + - **Inf**: the decimation operation takes place around Fs - Fc. + - **Sup**: the decimation operation takes place around Fs + Fc. + +With SR as the sample rate before decimation Fc is calculated as: + + - if decimation n is 4 or lower: Fc = SR/2^(log2(n)-1). The device center frequency is on the side of the baseband. You need a RF filter bandwidth at least twice the baseband. + - if decimation n is 8 or higher: Fc = SR/n. The device center frequency is half the baseband away from the side of the baseband. You need a RF filter bandwidth at least 3 times the baseband. + +

19. RF gain setting

+ +Sets the LNA and mixer gain dB. The settings available depended upon the RSP device and frequency band. + +

20. IF AGC

+ +Check this button to enable IF automatic gain control, + +

21. IF gain

+ +Manual IF gain from 0 to -59 dB. Only enabled when IF AGC is disabled. diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3gui.cpp b/plugins/samplesource/sdrplayv3/sdrplayv3gui.cpp new file mode 100644 index 000000000..5e28a1e9a --- /dev/null +++ b/plugins/samplesource/sdrplayv3/sdrplayv3gui.cpp @@ -0,0 +1,491 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "sdrplayv3gui.h" +#include "sdrplayv3input.h" + +#include "device/deviceapi.h" +#include "device/deviceuiset.h" + +#include "ui_sdrplayv3gui.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" + +SDRPlayV3Gui::SDRPlayV3Gui(DeviceUISet *deviceUISet, QWidget* parent) : + DeviceGUI(parent), + ui(new Ui::SDRPlayV3Gui), + m_deviceUISet(deviceUISet), + m_doApplySettings(true), + m_forceSettings(true) +{ + m_sdrPlayV3Input = (SDRPlayV3Input*) m_deviceUISet->m_deviceAPI->getSampleSource(); + + ui->setupUi(this); + ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); + ui->centerFrequency->setValueRange(7, 1U, 2000000U); + + ui->ifFrequency->clear(); + for (unsigned int i = 0; i < SDRPlayV3IF::getNbIFs(); i++) + { + ui->ifFrequency->addItem(QString::number(SDRPlayV3IF::getIF(i)/1000)); + } + + ui->samplerate->setColorMapper(ColorMapper(ColorMapper::GrayGold)); + ui->samplerate->setValueRange(8, 2000000U, 10660000U); + + ui->bandwidth->clear(); + for (unsigned int i = 0; i < SDRPlayV3Bandwidths::getNbBandwidths(); i++) + { + ui->bandwidth->addItem(QString::number(SDRPlayV3Bandwidths::getBandwidth(i)/1000)); + } + + 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 &))); + + ui->tuner->blockSignals(true); + ui->antenna->blockSignals(true); + ui->tuner->clear(); + ui->antenna->clear(); + switch (m_sdrPlayV3Input->getDeviceId()) + { + case SDRPLAY_RSP1_ID: + ui->tuner->addItem("1"); + ui->antenna->addItem("50Ohm"); + ui->amNotch->setVisible(false); + ui->biasTee->setVisible(false); + ui->extRef->setVisible(false); + break; + case SDRPLAY_RSP1A_ID: + ui->tuner->addItem("1"); + ui->antenna->addItem("50Ohm"); + ui->amNotch->setVisible(false); + ui->extRef->setVisible(false); + break; + case SDRPLAY_RSP2_ID: + ui->tuner->addItem("1"); + ui->antenna->addItem("A"); + ui->antenna->addItem("B"); + ui->antenna->addItem("Hi-Z"); + ui->amNotch->setVisible(false); + break; + case SDRPLAY_RSPduo_ID: + ui->tuner->addItem("1"); + ui->tuner->addItem("2"); + ui->antenna->addItem("50Ohm"); + ui->antenna->addItem("Hi-Z"); + ui->biasTee->setVisible(false); + break; + case SDRPLAY_RSPdx_ID: + ui->tuner->addItem("1"); + ui->antenna->addItem("A"); + ui->antenna->addItem("B"); + ui->antenna->addItem("C"); + ui->amNotch->setVisible(false); + ui->extRef->setVisible(false); + break; + } + ui->tuner->blockSignals(false); + ui->antenna->blockSignals(false); + + displaySettings(); + + connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection); + m_sdrPlayV3Input->setMessageQueueToGUI(&m_inputMessageQueue); +} + +SDRPlayV3Gui::~SDRPlayV3Gui() +{ + delete ui; +} + +void SDRPlayV3Gui::destroy() +{ + delete this; +} + +void SDRPlayV3Gui::resetToDefaults() +{ + m_settings.resetToDefaults(); + displaySettings(); + sendSettings(); +} + +QByteArray SDRPlayV3Gui::serialize() const +{ + return m_settings.serialize(); +} + +bool SDRPlayV3Gui::deserialize(const QByteArray& data) +{ + if(m_settings.deserialize(data)) + { + displaySettings(); + m_forceSettings = true; + sendSettings(); + return true; + } + else + { + resetToDefaults(); + return false; + } +} + +bool SDRPlayV3Gui::handleMessage(const Message& message) +{ + if (SDRPlayV3Input::MsgConfigureSDRPlayV3::match(message)) + { + const SDRPlayV3Input::MsgConfigureSDRPlayV3& cfg = (SDRPlayV3Input::MsgConfigureSDRPlayV3&) message; + m_settings = cfg.getSettings(); + blockApplySettings(true); + displaySettings(); + blockApplySettings(false); + return true; + } + else if (SDRPlayV3Input::MsgStartStop::match(message)) + { + SDRPlayV3Input::MsgStartStop& notif = (SDRPlayV3Input::MsgStartStop&) message; + blockApplySettings(true); + ui->startStop->setChecked(notif.getStartStop()); + blockApplySettings(false); + + return true; + } + else + { + return false; + } +} + +void SDRPlayV3Gui::handleInputMessages() +{ + Message* message; + + while ((message = m_inputMessageQueue.pop()) != 0) + { + qDebug("SDRPlayV3Gui::handleInputMessages: message: %s", message->getIdentifier()); + + if (DSPSignalNotification::match(*message)) + { + DSPSignalNotification* notif = (DSPSignalNotification*) message; + m_sampleRate = notif->getSampleRate(); + m_deviceCenterFrequency = notif->getCenterFrequency(); + qDebug("SDRPlayV3Gui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency()); + updateSampleRateAndFrequency(); + + delete message; + } + else + { + if (handleMessage(*message)) + { + delete message; + } + } + } +} + +void SDRPlayV3Gui::updateSampleRateAndFrequency() +{ + m_deviceUISet->getSpectrum()->setSampleRate(m_sampleRate); + m_deviceUISet->getSpectrum()->setCenterFrequency(m_deviceCenterFrequency); + ui->deviceRateText->setText(tr("%1k").arg((float)m_sampleRate / 1000)); +} + +void SDRPlayV3Gui::displaySettings() +{ + ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); + + ui->ppm->setValue(m_settings.m_LOppmTenths); + ui->ppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1))); + + ui->tuner->setCurrentIndex(m_settings.m_tuner); + ui->antenna->setCurrentIndex(m_settings.m_antenna); + + ui->samplerate->setValue(m_settings.m_devSampleRate); + + ui->dcOffset->setChecked(m_settings.m_dcBlock); + ui->iqImbalance->setChecked(m_settings.m_iqCorrection); + + ui->extRef->setChecked(m_settings.m_extRef); + ui->biasTee->setChecked(m_settings.m_biasTee); + ui->amNotch->setChecked(m_settings.m_amNotch); + ui->fmNotch->setChecked(m_settings.m_fmNotch); + ui->dabNotch->setChecked(m_settings.m_dabNotch); + + ui->bandwidth->setCurrentIndex(m_settings.m_bandwidthIndex); + ui->ifFrequency->setCurrentIndex(m_settings.m_ifFrequencyIndex); + ui->samplerate->setValue(m_settings.m_devSampleRate); + + ui->decim->setCurrentIndex(m_settings.m_log2Decim); + ui->fcPos->setCurrentIndex((int) m_settings.m_fcPos); + + updateLNAValues(); + ui->gainLNA->setCurrentIndex(m_settings.m_lnaIndex); + if (m_settings.m_ifAGC) + { + ui->gainIFAGC->setChecked(true); + ui->gainIF->setEnabled(false); + } + else + { + ui->gainIFAGC->setChecked(false); + ui->gainIF->setEnabled(true); + } + int gain = m_settings.m_ifGain; + ui->gainIF->setValue(gain); + QString gainText = QStringLiteral("%1").arg(gain, 2, 10, QLatin1Char('0')); + ui->gainIFText->setText(gainText); +} + +void SDRPlayV3Gui::updateLNAValues() +{ + int currentValue = ui->gainLNA->currentText().toInt(); + bool found = false; + + const int *attenuations = SDRPlayV3LNA::getAttenuations(m_sdrPlayV3Input->getDeviceId(), m_settings.m_centerFrequency); + int len = attenuations[0]; + ui->gainLNA->clear(); + for (int i = 1; i <= len; i++) + { + if (attenuations[i] == 0) + ui->gainLNA->addItem("0"); + else + ui->gainLNA->addItem(QString("-%1").arg(attenuations[i])); + + // Find closest match + if ((attenuations[i] == -currentValue) || (!found && (attenuations[i] > -currentValue))) + { + ui->gainLNA->setCurrentIndex(i - 1); + found = true; + } + } +} + +void SDRPlayV3Gui::sendSettings() +{ + if(!m_updateTimer.isActive()) + m_updateTimer.start(100); +} + +void SDRPlayV3Gui::updateHardware() +{ + qDebug() << "SDRPlayV3Gui::updateHardware"; + SDRPlayV3Input::MsgConfigureSDRPlayV3* message = SDRPlayV3Input::MsgConfigureSDRPlayV3::create(m_settings, m_forceSettings); + m_sdrPlayV3Input->getInputMessageQueue()->push(message); + m_forceSettings = false; + m_updateTimer.stop(); +} + +void SDRPlayV3Gui::updateStatus() +{ + int state = m_deviceUISet->m_deviceAPI->state(); + + if(m_lastEngineState != state) + { + switch(state) + { + case DeviceAPI::StNotStarted: + ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); + break; + case DeviceAPI::StIdle: + ui->startStop->setStyleSheet("QToolButton { background-color : blue; }"); + break; + case DeviceAPI::StRunning: + ui->startStop->setStyleSheet("QToolButton { background-color : green; }"); + break; + case DeviceAPI::StError: + ui->startStop->setStyleSheet("QToolButton { background-color : red; }"); + QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage()); + break; + default: + break; + } + + m_lastEngineState = state; + } +} + +void SDRPlayV3Gui::on_centerFrequency_changed(quint64 value) +{ + m_settings.m_centerFrequency = value * 1000; + updateLNAValues(); + sendSettings(); +} + +void SDRPlayV3Gui::on_ppm_valueChanged(int value) +{ + m_settings.m_LOppmTenths = value; + ui->ppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1))); + sendSettings(); +} + +void SDRPlayV3Gui::on_tuner_currentIndexChanged(int index) +{ + m_settings.m_tuner = index; + if (m_sdrPlayV3Input->getDeviceId() == SDRPLAY_RSPduo_ID) + { + ui->antenna->clear(); + ui->antenna->addItem("50Ohm"); + if (m_settings.m_tuner == 0) + ui->antenna->addItem("Hi-Z"); + ui->amNotch->setVisible(index == 0); + ui->biasTee->setVisible(index == 1); + } + sendSettings(); +} + +void SDRPlayV3Gui::on_antenna_currentIndexChanged(int index) +{ + m_settings.m_antenna = index; + sendSettings(); +} + +void SDRPlayV3Gui::on_dcOffset_toggled(bool checked) +{ + m_settings.m_dcBlock = checked; + sendSettings(); +} + +void SDRPlayV3Gui::on_iqImbalance_toggled(bool checked) +{ + m_settings.m_iqCorrection = checked; + sendSettings(); +} + +void SDRPlayV3Gui::on_extRef_toggled(bool checked) +{ + m_settings.m_extRef = checked; + sendSettings(); +} + +void SDRPlayV3Gui::on_biasTee_toggled(bool checked) +{ + m_settings.m_biasTee = checked; + sendSettings(); +} + +void SDRPlayV3Gui::on_amNotch_toggled(bool checked) +{ + m_settings.m_amNotch = checked; + sendSettings(); +} + +void SDRPlayV3Gui::on_fmNotch_toggled(bool checked) +{ + m_settings.m_fmNotch = checked; + sendSettings(); +} + +void SDRPlayV3Gui::on_dabNotch_toggled(bool checked) +{ + m_settings.m_dabNotch = checked; + sendSettings(); +} + +void SDRPlayV3Gui::on_bandwidth_currentIndexChanged(int index) +{ + m_settings.m_bandwidthIndex = index; + sendSettings(); +} + +void SDRPlayV3Gui::on_samplerate_changed(quint64 value) +{ + m_settings.m_devSampleRate = (uint32_t)value; + sendSettings(); +} + +void SDRPlayV3Gui::on_ifFrequency_currentIndexChanged(int index) +{ + m_settings.m_ifFrequencyIndex = index; + sendSettings(); +} + +void SDRPlayV3Gui::on_decim_currentIndexChanged(int index) +{ + m_settings.m_log2Decim = index; + sendSettings(); +} + +void SDRPlayV3Gui::on_fcPos_currentIndexChanged(int index) +{ + m_settings.m_fcPos = (SDRPlayV3Settings::fcPos_t) index; + sendSettings(); +} + +void SDRPlayV3Gui::on_gainLNA_currentIndexChanged(int index) +{ + m_settings.m_lnaIndex = index; + sendSettings(); +} + +void SDRPlayV3Gui::on_gainIFAGC_toggled(bool checked) +{ + m_settings.m_ifAGC = checked; + ui->gainIF->setEnabled(!checked); + sendSettings(); +} + +void SDRPlayV3Gui::on_gainIF_valueChanged(int value) +{ + m_settings.m_ifGain = value; + + QString gainText = QStringLiteral("%1").arg(value, 2, 10, QLatin1Char('0')); + ui->gainIFText->setText(gainText); + + sendSettings(); +} + +void SDRPlayV3Gui::on_startStop_toggled(bool checked) +{ + if (m_doApplySettings) + { + SDRPlayV3Input::MsgStartStop *message = SDRPlayV3Input::MsgStartStop::create(checked); + m_sdrPlayV3Input->getInputMessageQueue()->push(message); + } +} + +void SDRPlayV3Gui::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/samplesource/sdrplayv3/sdrplayv3gui.h b/plugins/samplesource/sdrplayv3/sdrplayv3gui.h new file mode 100644 index 000000000..e91e79af9 --- /dev/null +++ b/plugins/samplesource/sdrplayv3/sdrplayv3gui.h @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3GUI_H_ +#define PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3GUI_H_ + +#include +#include +#include + +#include "util/messagequeue.h" + +#include "sdrplayv3input.h" +#include "sdrplayv3settings.h" + +class DeviceUISet; + +namespace Ui { + class SDRPlayV3Gui; +} + +class SDRPlayV3Gui : public DeviceGUI { + Q_OBJECT + +public: + explicit SDRPlayV3Gui(DeviceUISet *deviceUISet, QWidget* parent = 0); + virtual ~SDRPlayV3Gui(); + virtual void destroy(); + + virtual void resetToDefaults(); + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); + virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + +private: + Ui::SDRPlayV3Gui* ui; + + DeviceUISet* m_deviceUISet; + bool m_doApplySettings; + bool m_forceSettings; + SDRPlayV3Settings m_settings; + QTimer m_updateTimer; + QTimer m_statusTimer; + SDRPlayV3Input* m_sdrPlayV3Input; + int m_sampleRate; + quint64 m_deviceCenterFrequency; + int m_lastEngineState; + MessageQueue m_inputMessageQueue; + + void blockApplySettings(bool block) { m_doApplySettings = !block; } + void displaySettings(); + void updateLNAValues(); + void sendSettings(); + void updateSampleRateAndFrequency(); + bool handleMessage(const Message& message); + +private slots: + void updateHardware(); + void updateStatus(); + void handleInputMessages(); + void on_centerFrequency_changed(quint64 value); + void on_ppm_valueChanged(int value); + void on_tuner_currentIndexChanged(int index); + void on_antenna_currentIndexChanged(int index); + void on_dcOffset_toggled(bool checked); + void on_iqImbalance_toggled(bool checked); + void on_extRef_toggled(bool checked); + void on_biasTee_toggled(bool checked); + void on_amNotch_toggled(bool checked); + void on_fmNotch_toggled(bool checked); + void on_dabNotch_toggled(bool checked); + void on_bandwidth_currentIndexChanged(int index); + void on_samplerate_changed(quint64 value); + void on_ifFrequency_currentIndexChanged(int index); + void on_decim_currentIndexChanged(int index); + void on_fcPos_currentIndexChanged(int index); + void on_gainLNA_currentIndexChanged(int index); + void on_gainIFAGC_toggled(bool checked); + void on_gainIF_valueChanged(int value); + void on_startStop_toggled(bool checked); + void openDeviceSettingsDialog(const QPoint& p); +}; + +#endif /* PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3GUI_H_ */ diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3gui.ui b/plugins/samplesource/sdrplayv3/sdrplayv3gui.ui new file mode 100644 index 000000000..a7f57a614 --- /dev/null +++ b/plugins/samplesource/sdrplayv3/sdrplayv3gui.ui @@ -0,0 +1,799 @@ + + + SDRPlayV3Gui + + + + 0 + 0 + 317 + 260 + + + + + 0 + 0 + + + + + 0 + 260 + + + + + Liberation Sans + 9 + + + + SDRPlayV3 + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + 4 + + + + + + + + + start/stop acquisition + + + + + + + :/play.png + :/stop.png:/play.png + + + + + + + + + + + I/Q sample rate kS/s + + + 00000k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 20 + + + + PointingHandCursor + + + Qt::StrongFocus + + + Tuner center frequency in kHz + + + + + + + kHz + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + + Qt::Horizontal + + + + + + + 3 + + + + + + 40 + 0 + + + + 0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + LO ppm + + + + + + + Local Oscillator ppm correction + + + -200 + + + 200 + + + 1 + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + + + Qt::Horizontal + + + + + + + + + Tuner + + + + + + + Tuner + + + + + + + Qt::Vertical + + + + + + + Ant + + + + + + + Antenna port + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + + + Auto + + + + + + + Enable DAB notch filter + + + DAB + + + + + + + Enable bias tee + + + T + + + + + + + Automatic IQ imbalance correction + + + IQ + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Automatic DC offset removal + + + DC + + + + + + + Enable MW/FM notch filter + + + MW/FM + + + + + + + Enable external reference clock output + + + REF + + + + + + + Enable AM notch filter + + + AM + + + + + + + + + Qt::Horizontal + + + + + + + 3 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 70 + 16777215 + + + + IF bandwidth in kHz + + + + + + + + 0 + 0 + + + + BW + + + + + + + kHz + + + + + + + IF frequency in kHz + + + + + + + IF + + + + + + + kHz + + + + + + + + + 3 + + + + + + 50 + 16777215 + + + + Decimation factor + + + 0 + + + + 1 + + + + + 2 + + + + + 4 + + + + + 8 + + + + + 16 + + + + + 32 + + + + + 64 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Fp + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Relative position of device center frequency + + + + Inf + + + + + Sup + + + + + Cen + + + + + + + + + 0 + 0 + + + + SR + + + + + + + Dec + + + + + + + S/s + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 12 + 50 + false + + + + PointingHandCursor + + + Sample rate + + + + + + + + + Qt::Horizontal + + + + + + + 3 + + + + + true + + + Enable IF AGC + + + IF AGC + + + + + + + IF + + + + + + + Qt::Vertical + + + + + + + + 24 + 24 + + + + IF gain (dB) + + + -59 + + + 0 + + + 1 + + + + + + + Gain + + + + + + + Qt::Vertical + + + + + + + RF (LNA and mixer) gain in dB + + + + + + + RF + + + + + + + Baseband amplifier gain in dB + + + 00 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + + + + + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
+ + ValueDial + QWidget +
gui/valuedial.h
+ 1 +
+
+ + + + +
diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3input.cpp b/plugins/samplesource/sdrplayv3/sdrplayv3input.cpp new file mode 100644 index 000000000..c41a8d3d3 --- /dev/null +++ b/plugins/samplesource/sdrplayv3/sdrplayv3input.cpp @@ -0,0 +1,1312 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include +#include +#include + +#include "SWGDeviceSettings.h" +#include "SWGDeviceState.h" +#include "SWGDeviceReport.h" +#include "SWGSDRPlayV3Report.h" + +#include "util/simpleserializer.h" +#include "dsp/dspcommands.h" +#include "dsp/dspengine.h" +#include "sdrplayv3input.h" + +#include + +#include "sdrplayv3thread.h" + +MESSAGE_CLASS_DEFINITION(SDRPlayV3Input::MsgConfigureSDRPlayV3, Message) +MESSAGE_CLASS_DEFINITION(SDRPlayV3Input::MsgStartStop, Message) + +SDRPlayV3Input::SDRPlayV3Input(DeviceAPI *deviceAPI) : + m_deviceAPI(deviceAPI), + m_settings(), + m_dev(nullptr), + m_devParams(nullptr), + m_sdrPlayThread(nullptr), + m_deviceDescription("SDRPlayV3"), + m_devNumber(0), + m_running(false) +{ + openDevice(); + m_deviceAPI->setNbSourceStreams(1); + + m_networkManager = new QNetworkAccessManager(); + connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); +} + +SDRPlayV3Input::~SDRPlayV3Input() +{ + disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); + delete m_networkManager; + + if (m_running) { + stop(); + } + + closeDevice(); +} + +void SDRPlayV3Input::destroy() +{ + delete this; +} + +bool SDRPlayV3Input::openDevice() +{ + qDebug() << "SDRPlayV3Input::openDevice"; + m_devNumber = m_deviceAPI->getSamplingDeviceSequence(); + + if (m_dev != 0) + { + closeDevice(); + } + + if (!m_sampleFifo.setSize(96000 * 4)) + { + qCritical("SDRPlayV3Input::openDevice: could not allocate SampleFifo"); + return false; + } + + sdrplay_api_LockDeviceApi(); + + sdrplay_api_ErrT err; + unsigned int count; + if ((err = sdrplay_api_GetDevices(m_devs, &count, sizeof(m_devs) / sizeof(sdrplay_api_DeviceT))) == sdrplay_api_Success) + { + m_dev = &m_devs[m_devNumber]; + m_dev->tuner = sdrplay_api_Tuner_A; + m_dev->rspDuoMode = sdrplay_api_RspDuoMode_Single_Tuner; + if ((err = sdrplay_api_SelectDevice(m_dev)) == sdrplay_api_Success) + { + sdrplay_api_UnlockDeviceApi(); + if ((err = sdrplay_api_GetDeviceParams(m_dev->dev, &m_devParams)) == sdrplay_api_Success) + { + qDebug() << "SDRPlayV3Input::openDevice: opened sucessfully"; + } + else + { + qCritical() << "SDRPlayV3Input::openDevice: could not get device parameters: " << sdrplay_api_GetErrorString(err); + return false; + } + } + else + { + qCritical() << "SDRPlayV3Input::openDevice: could not select device: " << sdrplay_api_GetErrorString(err); + sdrplay_api_UnlockDeviceApi(); + return false; + } + } + else + { + qCritical() << "SDRPlayV3Input::openDevice: could not get devices: " << sdrplay_api_GetErrorString(err); + sdrplay_api_UnlockDeviceApi(); + return false; + } + + sdrplay_api_UnlockDeviceApi(); + + return true; +} + +bool SDRPlayV3Input::start() +{ + qDebug() << "SDRPlayV3Input::start"; + + if (!m_dev) { + return false; + } + + if (m_running) stop(); + + m_sdrPlayThread = new SDRPlayV3Thread(m_dev, &m_sampleFifo); + m_sdrPlayThread->setLog2Decimation(m_settings.m_log2Decim); + m_sdrPlayThread->setFcPos((int) m_settings.m_fcPos); + m_sdrPlayThread->startWork(); + + applySettings(m_settings, true, true); + m_running = true; + + return true; +} + +void SDRPlayV3Input::closeDevice() +{ + qDebug() << "SDRPlayV3Input::closeDevice"; + if (m_dev != 0) + { + sdrplay_api_ReleaseDevice(m_dev); + m_dev = 0; + } + m_deviceDescription.clear(); +} + +void SDRPlayV3Input::init() +{ + applySettings(m_settings, true, true); +} + +void SDRPlayV3Input::stop() +{ + qDebug() << "SDRPlayV3Input::stop"; + + if(m_sdrPlayThread) + { + m_sdrPlayThread->stopWork(); + delete m_sdrPlayThread; + m_sdrPlayThread = nullptr; + } + + m_running = false; +} + +QByteArray SDRPlayV3Input::serialize() const +{ + return m_settings.serialize(); +} + +bool SDRPlayV3Input::deserialize(const QByteArray& data) +{ + bool success = true; + + if (!m_settings.deserialize(data)) + { + m_settings.resetToDefaults(); + success = false; + } + + MsgConfigureSDRPlayV3* message = MsgConfigureSDRPlayV3::create(m_settings, true); + m_inputMessageQueue.push(message); + + if (m_guiMessageQueue) + { + MsgConfigureSDRPlayV3* messageToGUI = MsgConfigureSDRPlayV3::create(m_settings, true); + m_guiMessageQueue->push(messageToGUI); + } + + return success; +} + +const QString& SDRPlayV3Input::getDeviceDescription() const +{ + return m_deviceDescription; +} + +int SDRPlayV3Input::getSampleRate() const +{ + int rate = m_settings.m_devSampleRate; + return rate / (1 << m_settings.m_log2Decim); +} + +quint64 SDRPlayV3Input::getCenterFrequency() const +{ + return m_settings.m_centerFrequency; +} + +void SDRPlayV3Input::setCenterFrequency(qint64 centerFrequency) +{ + SDRPlayV3Settings settings = m_settings; + settings.m_centerFrequency = centerFrequency; + + MsgConfigureSDRPlayV3* message = MsgConfigureSDRPlayV3::create(settings, false); + m_inputMessageQueue.push(message); + + if (m_guiMessageQueue) + { + MsgConfigureSDRPlayV3* messageToGUI = MsgConfigureSDRPlayV3::create(settings, false); + m_guiMessageQueue->push(messageToGUI); + } +} + +bool SDRPlayV3Input::handleMessage(const Message& message) +{ + if (MsgConfigureSDRPlayV3::match(message)) + { + MsgConfigureSDRPlayV3& conf = (MsgConfigureSDRPlayV3&) message; + qDebug() << "SDRPlayV3Input::handleMessage: MsgConfigureSDRPlayV3"; + const SDRPlayV3Settings& settings = conf.getSettings(); + + if (!applySettings(settings, false, conf.getForce())) + qDebug("SDRPlayV3Input::handleMessage: config error"); + + return true; + } + else if (MsgStartStop::match(message)) + { + MsgStartStop& cmd = (MsgStartStop&) message; + qDebug() << "SDRPlayV3Input::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop"); + + if (cmd.getStartStop()) + { + if (m_deviceAPI->initDeviceEngine()) + { + m_deviceAPI->startDeviceEngine(); + } + } + else + { + m_deviceAPI->stopDeviceEngine(); + } + + if (m_settings.m_useReverseAPI) { + webapiReverseSendStartStop(cmd.getStartStop()); + } + + return true; + } + else + { + return false; + } +} + +bool SDRPlayV3Input::applySettings(const SDRPlayV3Settings& settings, bool forwardChange, bool force) +{ + qDebug() << "SDRPlayV3Input::applySettings"; + QList reverseAPIKeys; + QMutexLocker mutexLocker(&m_mutex); + sdrplay_api_ErrT err; + + if ((m_settings.m_tuner != settings.m_tuner) || force) + { + if (m_dev != nullptr) + { + if (getDeviceId() == SDRPLAY_RSPduo_ID) + { + if (((m_dev->tuner == sdrplay_api_Tuner_A) && (settings.m_tuner == 1)) + || ((m_dev->tuner == sdrplay_api_Tuner_B) && (settings.m_tuner == 0))) + { + if ((err = sdrplay_api_SwapRspDuoActiveTuner (m_dev->dev, &m_dev->tuner, settings.m_antenna == 1 ? sdrplay_api_RspDuo_AMPORT_1 : sdrplay_api_RspDuo_AMPORT_2)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Input::applySettings: could not swap tuners: " << sdrplay_api_GetErrorString(err); + } + } + } + } + + if ((m_settings.m_dcBlock != settings.m_dcBlock) || force) + { + reverseAPIKeys.append("dcBlock"); + + if (m_dev != nullptr) + { + if (m_dev->tuner == sdrplay_api_Tuner_A) + m_devParams->rxChannelA->ctrlParams.dcOffset.DCenable = settings.m_dcBlock ? 1 : 0; + else + m_devParams->rxChannelB->ctrlParams.dcOffset.DCenable = settings.m_dcBlock ? 1 : 0; + if ((err = sdrplay_api_Update(m_dev->dev, m_dev->tuner, sdrplay_api_Update_Ctrl_DCoffsetIQimbalance, sdrplay_api_Update_Ext1_None)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Input::applySettings: could not set DC offset enable: " << sdrplay_api_GetErrorString(err); + } + } + + if ((m_settings.m_iqCorrection != settings.m_iqCorrection) || force) + { + reverseAPIKeys.append("iqCorrection"); + + if (m_dev != nullptr) + { + if (m_dev->tuner == sdrplay_api_Tuner_A) + m_devParams->rxChannelA->ctrlParams.dcOffset.IQenable = settings.m_iqCorrection ? 1 : 0; + else + m_devParams->rxChannelB->ctrlParams.dcOffset.IQenable = settings.m_iqCorrection ? 1 : 0; + if ((err = sdrplay_api_Update(m_dev->dev, m_dev->tuner, sdrplay_api_Update_Ctrl_DCoffsetIQimbalance, sdrplay_api_Update_Ext1_None)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Input::applySettings: could not set IQ offset enable: " << sdrplay_api_GetErrorString(err); + } + } + + if (m_settings.m_lnaIndex != settings.m_lnaIndex) + { + reverseAPIKeys.append("lnaIndex"); + } + + if (m_settings.m_ifGain != settings.m_ifGain) + { + reverseAPIKeys.append("ifGain"); + } + + if ((m_settings.m_ifAGC != settings.m_ifAGC) || force) + { + reverseAPIKeys.append("ifAGC"); + + if (m_dev != nullptr) + { + if (m_dev->tuner == sdrplay_api_Tuner_A) + m_devParams->rxChannelA->ctrlParams.agc.enable = settings.m_ifAGC ? sdrplay_api_AGC_CTRL_EN : sdrplay_api_AGC_DISABLE; + else + m_devParams->rxChannelB->ctrlParams.agc.enable = settings.m_ifAGC ? sdrplay_api_AGC_CTRL_EN : sdrplay_api_AGC_DISABLE; + if ((err = sdrplay_api_Update(m_dev->dev, m_dev->tuner, sdrplay_api_Update_Ctrl_Agc, sdrplay_api_Update_Ext1_None)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Input::applySettings: could not set AGC enable: " << sdrplay_api_GetErrorString(err); + } + } + + // Need to reset IF gain manual setting after AGC is disabled + if ((m_settings.m_lnaIndex != settings.m_lnaIndex) + || (m_settings.m_ifGain != settings.m_ifGain) + || (m_settings.m_ifAGC != settings.m_ifAGC) || force) + { + if (m_dev != nullptr) + { + if (m_dev->tuner == sdrplay_api_Tuner_A) + { + m_devParams->rxChannelA->tunerParams.gain.gRdB = -settings.m_ifGain; + m_devParams->rxChannelA->tunerParams.gain.LNAstate = settings.m_lnaIndex; + m_devParams->rxChannelA->tunerParams.gain.minGr = sdrplay_api_EXTENDED_MIN_GR; + } + else + { + m_devParams->rxChannelB->tunerParams.gain.gRdB = -settings.m_ifGain; + m_devParams->rxChannelB->tunerParams.gain.LNAstate = settings.m_lnaIndex; + m_devParams->rxChannelB->tunerParams.gain.minGr = sdrplay_api_EXTENDED_MIN_GR; + } + if ((err = sdrplay_api_Update(m_dev->dev, m_dev->tuner, sdrplay_api_Update_Tuner_Gr, sdrplay_api_Update_Ext1_None)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Input::applySettings: could not set gain: " << sdrplay_api_GetErrorString(err); + } + } + + if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force) + { + reverseAPIKeys.append("devSampleRate"); + + if (m_dev != nullptr) + { + int sampleRate = settings.m_devSampleRate; + m_devParams->devParams->fsFreq.fsHz = (double)sampleRate; + if ((err = sdrplay_api_Update(m_dev->dev, m_dev->tuner, sdrplay_api_Update_Dev_Fs, sdrplay_api_Update_Ext1_None)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Input::applySettings: could not set sample rate to " << sampleRate << " : " << sdrplay_api_GetErrorString(err); + else + qDebug() << "SDRPlayV3Input::applySettings: sample rate set to " << sampleRate; + forwardChange = true; + } + } + + if ((m_settings.m_log2Decim != settings.m_log2Decim) || force) + { + reverseAPIKeys.append("log2Decim"); + + if (m_sdrPlayThread) + { + m_sdrPlayThread->setLog2Decimation(settings.m_log2Decim); + qDebug() << "SDRPlayV3Input::applySettings: set decimation to " << (1<setFcPos((int) settings.m_fcPos); + qDebug() << "SDRPlayV3Input:applySettings: set fc pos (enum) to " << (int) settings.m_fcPos; + } + } + + if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) { + reverseAPIKeys.append("centerFrequency"); + } + if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) { + reverseAPIKeys.append("LOppmTenths"); + } + + if ((m_settings.m_centerFrequency != settings.m_centerFrequency) + || (m_settings.m_LOppmTenths != settings.m_LOppmTenths) + || (m_settings.m_fcPos != settings.m_fcPos) + || (m_settings.m_log2Decim != settings.m_log2Decim) || force) + { + qint64 deviceCenterFrequency = DeviceSampleSource::calculateDeviceCenterFrequency( + settings.m_centerFrequency, + 0, + settings.m_log2Decim, + (DeviceSampleSource::fcPos_t) settings.m_fcPos, + settings.m_devSampleRate, + DeviceSampleSource::FrequencyShiftScheme::FSHIFT_STD, + false); + + forwardChange = true; + + if (m_dev != nullptr) + { + if (setDeviceCenterFrequency(deviceCenterFrequency)) { + qDebug() << "SDRPlayV3Input::applySettings: center freq: " << settings.m_centerFrequency << " Hz"; + } + } + } + + if ((m_settings.m_bandwidthIndex != settings.m_bandwidthIndex) || force) + { + reverseAPIKeys.append("bandwidthIndex"); + + if (m_dev != nullptr) + { + if (m_dev->tuner == sdrplay_api_Tuner_A) + m_devParams->rxChannelA->tunerParams.bwType = SDRPlayV3Bandwidths::getBandwidthEnum(settings.m_bandwidthIndex); + else + m_devParams->rxChannelB->tunerParams.bwType = SDRPlayV3Bandwidths::getBandwidthEnum(settings.m_bandwidthIndex); + if ((err = sdrplay_api_Update(m_dev->dev, m_dev->tuner, sdrplay_api_Update_Tuner_BwType, sdrplay_api_Update_Ext1_None)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Input::applySettings: could not set bandwidth: " << sdrplay_api_GetErrorString(err); + } + } + + if ((m_settings.m_ifFrequencyIndex != settings.m_ifFrequencyIndex) || force) + { + reverseAPIKeys.append("ifFrequencyIndex"); + + if (m_dev != nullptr) + { + if (m_dev->tuner == sdrplay_api_Tuner_A) + m_devParams->rxChannelA->tunerParams.ifType = SDRPlayV3IF::getIFEnum(settings.m_ifFrequencyIndex); + else + m_devParams->rxChannelB->tunerParams.ifType = SDRPlayV3IF::getIFEnum(settings.m_ifFrequencyIndex); + if ((err = sdrplay_api_Update(m_dev->dev, m_dev->tuner, sdrplay_api_Update_Tuner_IfType, sdrplay_api_Update_Ext1_None)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Input::applySettings: could not set IF frequency: " << sdrplay_api_GetErrorString(err); + } + } + + if ((m_settings.m_biasTee != settings.m_biasTee) || force) + { + reverseAPIKeys.append("biasTee"); + + if (m_dev != nullptr) + { + sdrplay_api_ReasonForUpdateT update = sdrplay_api_Update_None; + sdrplay_api_ReasonForUpdateExtension1T updateExt = sdrplay_api_Update_Ext1_None; + switch (getDeviceId()) + { + case SDRPLAY_RSP1A_ID: + m_devParams->rxChannelA->rsp1aTunerParams.biasTEnable = settings.m_biasTee; + update = sdrplay_api_Update_Rsp1a_BiasTControl; + break; + case SDRPLAY_RSP2_ID: + m_devParams->rxChannelA->rsp2TunerParams.biasTEnable = settings.m_biasTee; + update = sdrplay_api_Update_Rsp2_BiasTControl; + break; + case SDRPLAY_RSPduo_ID: + // Only channel B has bias tee + if (m_dev->tuner == sdrplay_api_Tuner_B) + { + m_devParams->rxChannelB->rspDuoTunerParams.biasTEnable = settings.m_biasTee; + update = sdrplay_api_Update_RspDuo_BiasTControl; + } + break; + case SDRPLAY_RSPdx_ID: + m_devParams->devParams->rspDxParams.biasTEnable = settings.m_biasTee; + updateExt = sdrplay_api_Update_RspDx_BiasTControl; + break; + default: + // SDRPLAY_RSP1_ID doesn't have a bias tee + break; + } + if ((err = sdrplay_api_Update(m_dev->dev, m_dev->tuner, update, updateExt)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Input::applySettings: could not set state of bias tee: " << sdrplay_api_GetErrorString(err); + } + } + + if ((m_settings.m_amNotch != settings.m_amNotch) || force) + { + reverseAPIKeys.append("amNotch"); + + if (m_dev != nullptr) + { + sdrplay_api_ReasonForUpdateT update = sdrplay_api_Update_None; + sdrplay_api_ReasonForUpdateExtension1T updateExt = sdrplay_api_Update_Ext1_None; + switch (getDeviceId()) + { + case SDRPLAY_RSPduo_ID: + if (m_dev->tuner == sdrplay_api_Tuner_A) + { + m_devParams->rxChannelA->rspDuoTunerParams.tuner1AmNotchEnable = settings.m_amNotch; + update = sdrplay_api_Update_RspDuo_Tuner1AmNotchControl; + } + break; + default: + // Other devices don't have AM notch filter + break; + } + if ((err = sdrplay_api_Update(m_dev->dev, m_dev->tuner, update, updateExt)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Input::applySettings: could not set state of AM notch filter: " << sdrplay_api_GetErrorString(err); + } + } + + if ((m_settings.m_fmNotch != settings.m_fmNotch) || force) + { + reverseAPIKeys.append("fmNotch"); + + if (m_dev != nullptr) + { + sdrplay_api_ReasonForUpdateT update = sdrplay_api_Update_None; + sdrplay_api_ReasonForUpdateExtension1T updateExt = sdrplay_api_Update_Ext1_None; + switch (getDeviceId()) + { + case SDRPLAY_RSP1A_ID: + m_devParams->devParams->rsp1aParams.rfNotchEnable = settings.m_fmNotch; + update = sdrplay_api_Update_Rsp1a_RfNotchControl; + break; + case SDRPLAY_RSP2_ID: + m_devParams->rxChannelA->rsp2TunerParams.rfNotchEnable = settings.m_fmNotch; + update = sdrplay_api_Update_Rsp2_RfNotchControl; + break; + case SDRPLAY_RSPduo_ID: + if (m_dev->tuner == sdrplay_api_Tuner_A) + m_devParams->rxChannelA->rspDuoTunerParams.rfNotchEnable = settings.m_fmNotch; + else + m_devParams->rxChannelB->rspDuoTunerParams.rfNotchEnable = settings.m_fmNotch; + update = sdrplay_api_Update_RspDuo_RfNotchControl; + break; + case SDRPLAY_RSPdx_ID: + m_devParams->devParams->rspDxParams.rfNotchEnable = settings.m_fmNotch; + updateExt = sdrplay_api_Update_RspDx_RfNotchControl; + break; + default: + // SDRPLAY_RSP1_ID doesn't have notch filter + break; + } + if ((err = sdrplay_api_Update(m_dev->dev, m_dev->tuner, update, updateExt)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Input::applySettings: could not set state of MW/FM notch filter: " << sdrplay_api_GetErrorString(err); + } + } + + if ((m_settings.m_dabNotch != settings.m_dabNotch) || force) + { + reverseAPIKeys.append("dabNotch"); + + if (m_dev != nullptr) + { + sdrplay_api_ReasonForUpdateT update = sdrplay_api_Update_None; + sdrplay_api_ReasonForUpdateExtension1T updateExt = sdrplay_api_Update_Ext1_None; + switch (getDeviceId()) + { + case SDRPLAY_RSP1A_ID: + m_devParams->devParams->rsp1aParams.rfDabNotchEnable = settings.m_dabNotch; + update = sdrplay_api_Update_Rsp1a_RfDabNotchControl; + break; + case SDRPLAY_RSPduo_ID: + if (m_dev->tuner == sdrplay_api_Tuner_A) + m_devParams->rxChannelA->rspDuoTunerParams.rfDabNotchEnable = settings.m_dabNotch; + else + m_devParams->rxChannelB->rspDuoTunerParams.rfDabNotchEnable = settings.m_dabNotch; + update = sdrplay_api_Update_RspDuo_RfDabNotchControl; + break; + case SDRPLAY_RSPdx_ID: + m_devParams->devParams->rspDxParams.rfDabNotchEnable = settings.m_dabNotch; + updateExt = sdrplay_api_Update_RspDx_RfDabNotchControl; + break; + default: + // SDRPLAY_RSP1_ID and SDRPLAY_RSP2_ID don't have DAB filter + break; + } + if ((err = sdrplay_api_Update(m_dev->dev, m_dev->tuner, update, updateExt)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Input::applySettings: could not set state of DAB notch filter: " << sdrplay_api_GetErrorString(err); + } + } + + if ((m_settings.m_antenna != settings.m_antenna) || force) + { + reverseAPIKeys.append("antenna"); + + if (m_dev != nullptr) + { + sdrplay_api_ReasonForUpdateT update = sdrplay_api_Update_None; + sdrplay_api_ReasonForUpdateExtension1T updateExt = sdrplay_api_Update_Ext1_None; + switch (getDeviceId()) + { + case SDRPLAY_RSP2_ID: + m_devParams->rxChannelA->rsp2TunerParams.amPortSel = settings.m_antenna == 2 ? sdrplay_api_Rsp2_AMPORT_1 : sdrplay_api_Rsp2_AMPORT_2; + m_devParams->rxChannelA->rsp2TunerParams.antennaSel = settings.m_antenna == 1 ? sdrplay_api_Rsp2_ANTENNA_B : sdrplay_api_Rsp2_ANTENNA_A; + update = (sdrplay_api_ReasonForUpdateT) (sdrplay_api_Update_Rsp2_AntennaControl | sdrplay_api_Update_Rsp2_AmPortSelect); + break; + case SDRPLAY_RSPduo_ID: + if (m_dev->tuner == sdrplay_api_Tuner_A) + { + m_devParams->rxChannelA->rspDuoTunerParams.tuner1AmPortSel = settings.m_antenna == 1 ? sdrplay_api_RspDuo_AMPORT_1 : sdrplay_api_RspDuo_AMPORT_2; + update = sdrplay_api_Update_RspDuo_AmPortSelect; + } + break; + case SDRPLAY_RSPdx_ID: + m_devParams->devParams->rspDxParams.antennaSel = (sdrplay_api_RspDx_AntennaSelectT)settings.m_antenna; + updateExt = sdrplay_api_Update_RspDx_AntennaControl; + break; + default: + // SDRPLAY_RSP1_ID and SDRPLAY_RSP1A_ID only have one antenna + break; + } + if ((err = sdrplay_api_Update(m_dev->dev, m_dev->tuner, update, updateExt)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Input::applySettings: could not set antenna: " << sdrplay_api_GetErrorString(err); + } + } + + if ((m_settings.m_extRef != settings.m_extRef) || force) + { + reverseAPIKeys.append("extRef"); + + if (m_dev != nullptr) + { + sdrplay_api_ReasonForUpdateT update = sdrplay_api_Update_None; + sdrplay_api_ReasonForUpdateExtension1T updateExt = sdrplay_api_Update_Ext1_None; + switch (getDeviceId()) + { + case SDRPLAY_RSP2_ID: + m_devParams->devParams->rsp2Params.extRefOutputEn = settings.m_extRef; + update = sdrplay_api_Update_Rsp2_ExtRefControl; + break; + case SDRPLAY_RSPduo_ID: + m_devParams->devParams->rspDuoParams.extRefOutputEn = settings.m_extRef; + update = sdrplay_api_Update_RspDuo_ExtRefControl; + break; + default: + // Other devices do not have external reference output + break; + } + if ((err = sdrplay_api_Update(m_dev->dev, m_dev->tuner, update, updateExt)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Input::applySettings: could not set state of external reference output: " << sdrplay_api_GetErrorString(err); + } + } + + 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 (forwardChange) + { + int sampleRate = getSampleRate(); + DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, m_settings.m_centerFrequency); + m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif); + } + + return true; +} + +bool SDRPlayV3Input::setDeviceCenterFrequency(quint64 freq_hz) +{ + qint64 df = ((qint64)freq_hz * m_settings.m_LOppmTenths) / 10000000LL; + freq_hz += df; + + sdrplay_api_ErrT err; + if (m_dev->tuner == sdrplay_api_Tuner_A) + m_devParams->rxChannelA->tunerParams.rfFreq.rfHz = (double)freq_hz; + else + m_devParams->rxChannelB->tunerParams.rfFreq.rfHz = (double)freq_hz; + if ((err = sdrplay_api_Update(m_dev->dev, m_dev->tuner, sdrplay_api_Update_Tuner_Frf, sdrplay_api_Update_Ext1_None)) != sdrplay_api_Success) + { + qWarning("SDRPlayV3Input::setDeviceCenterFrequency: could not frequency to %llu Hz", freq_hz); + return false; + } + else + { + qDebug("SDRPlayV3Input::setDeviceCenterFrequency: frequency set to %llu Hz", freq_hz); + return true; + } +} + +int SDRPlayV3Input::webapiRunGet( + SWGSDRangel::SWGDeviceState& response, + QString& errorMessage) +{ + (void) errorMessage; + m_deviceAPI->getDeviceEngineStateStr(*response.getState()); + return 200; +} + +int SDRPlayV3Input::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; +} + +int SDRPlayV3Input::webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setSdrPlayV3Settings(new SWGSDRangel::SWGSDRPlayV3Settings()); + response.getSdrPlayV3Settings()->init(); + webapiFormatDeviceSettings(response, m_settings); + return 200; +} + +int SDRPlayV3Input::webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage) +{ + (void) errorMessage; + SDRPlayV3Settings settings = m_settings; + webapiUpdateDeviceSettings(settings, deviceSettingsKeys, response); + + MsgConfigureSDRPlayV3 *msg = MsgConfigureSDRPlayV3::create(settings, force); + m_inputMessageQueue.push(msg); + + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigureSDRPlayV3 *msgToGUI = MsgConfigureSDRPlayV3::create(settings, force); + m_guiMessageQueue->push(msgToGUI); + } + + webapiFormatDeviceSettings(response, settings); + return 200; +} + +void SDRPlayV3Input::webapiUpdateDeviceSettings( + SDRPlayV3Settings& settings, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response) +{ + if (deviceSettingsKeys.contains("centerFrequency")) { + settings.m_centerFrequency = response.getSdrPlayV3Settings()->getCenterFrequency(); + } + if (deviceSettingsKeys.contains("LOppmTenths")) { + settings.m_LOppmTenths = response.getSdrPlayV3Settings()->getLOppmTenths(); + } + if (deviceSettingsKeys.contains("ifFrequencyIndex")) { + settings.m_ifFrequencyIndex = response.getSdrPlayV3Settings()->getIfFrequencyIndex(); + } + if (deviceSettingsKeys.contains("bandwidthIndex")) { + settings.m_bandwidthIndex = response.getSdrPlayV3Settings()->getBandwidthIndex(); + } + if (deviceSettingsKeys.contains("devSampleRate")) { + settings.m_devSampleRate = response.getSdrPlayV3Settings()->getDevSampleRate(); + } + if (deviceSettingsKeys.contains("log2Decim")) { + settings.m_log2Decim = response.getSdrPlayV3Settings()->getLog2Decim(); + } + if (deviceSettingsKeys.contains("fcPos")) + { + int fcPos = response.getSdrPlayV3Settings()->getFcPos(); + fcPos = fcPos < 0 ? 0 : fcPos > 2 ? 2 : fcPos; + settings.m_fcPos = (SDRPlayV3Settings::fcPos_t) fcPos; + } + if (deviceSettingsKeys.contains("dcBlock")) { + settings.m_dcBlock = response.getSdrPlayV3Settings()->getDcBlock() != 0; + } + if (deviceSettingsKeys.contains("iqCorrection")) { + settings.m_iqCorrection = response.getSdrPlayV3Settings()->getIqCorrection() != 0; + } + if (deviceSettingsKeys.contains("lnaIndex")) { + settings.m_lnaIndex = response.getSdrPlayV3Settings()->getLnaIndex(); + } + if (deviceSettingsKeys.contains("ifAGC")) { + settings.m_ifAGC = response.getSdrPlayV3Settings()->getIfAgc() != 0; + } + if (deviceSettingsKeys.contains("ifGain")) { + settings.m_ifGain = response.getSdrPlayV3Settings()->getIfGain(); + } + if (deviceSettingsKeys.contains("amNotch")) { + settings.m_amNotch = response.getSdrPlayV3Settings()->getAmNotch(); + } + if (deviceSettingsKeys.contains("fmNotch")) { + settings.m_fmNotch = response.getSdrPlayV3Settings()->getFmNotch(); + } + if (deviceSettingsKeys.contains("dabNotch")) { + settings.m_dabNotch = response.getSdrPlayV3Settings()->getDabNotch(); + } + if (deviceSettingsKeys.contains("extRef")) { + settings.m_extRef = response.getSdrPlayV3Settings()->getExtRef(); + } + if (deviceSettingsKeys.contains("tuner")) { + settings.m_tuner = response.getSdrPlayV3Settings()->getTuner(); + } + if (deviceSettingsKeys.contains("antenna")) { + settings.m_antenna = response.getSdrPlayV3Settings()->getAntenna(); + } + if (deviceSettingsKeys.contains("useReverseAPI")) { + settings.m_useReverseAPI = response.getSdrPlayV3Settings()->getUseReverseApi() != 0; + } + if (deviceSettingsKeys.contains("reverseAPIAddress")) { + settings.m_reverseAPIAddress = *response.getSdrPlayV3Settings()->getReverseApiAddress(); + } + if (deviceSettingsKeys.contains("reverseAPIPort")) { + settings.m_reverseAPIPort = response.getSdrPlayV3Settings()->getReverseApiPort(); + } + if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) { + settings.m_reverseAPIDeviceIndex = response.getSdrPlayV3Settings()->getReverseApiDeviceIndex(); + } +} + +void SDRPlayV3Input::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const SDRPlayV3Settings& settings) +{ + response.getSdrPlayV3Settings()->setCenterFrequency(settings.m_centerFrequency); + response.getSdrPlayV3Settings()->setLOppmTenths(settings.m_LOppmTenths); + response.getSdrPlayV3Settings()->setIfFrequencyIndex(settings.m_ifFrequencyIndex); + response.getSdrPlayV3Settings()->setBandwidthIndex(settings.m_bandwidthIndex); + response.getSdrPlayV3Settings()->setDevSampleRate(settings.m_devSampleRate); + response.getSdrPlayV3Settings()->setLog2Decim(settings.m_log2Decim); + response.getSdrPlayV3Settings()->setFcPos((int) settings.m_fcPos); + response.getSdrPlayV3Settings()->setDcBlock(settings.m_dcBlock ? 1 : 0); + response.getSdrPlayV3Settings()->setIqCorrection(settings.m_iqCorrection ? 1 : 0); + response.getSdrPlayV3Settings()->setLnaIndex(settings.m_lnaIndex); + response.getSdrPlayV3Settings()->setIfAgc(settings.m_ifAGC ? 1 : 0); + response.getSdrPlayV3Settings()->setIfGain(settings.m_ifGain); + response.getSdrPlayV3Settings()->setAmNotch(settings.m_amNotch); + response.getSdrPlayV3Settings()->setFmNotch(settings.m_fmNotch); + response.getSdrPlayV3Settings()->setDabNotch(settings.m_dabNotch); + response.getSdrPlayV3Settings()->setExtRef(settings.m_extRef); + response.getSdrPlayV3Settings()->setTuner(settings.m_tuner); + response.getSdrPlayV3Settings()->setAntenna(settings.m_antenna); + + response.getSdrPlayV3Settings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); + + if (response.getSdrPlayV3Settings()->getReverseApiAddress()) { + *response.getSdrPlayV3Settings()->getReverseApiAddress() = settings.m_reverseAPIAddress; + } else { + response.getSdrPlayV3Settings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress)); + } + + response.getSdrPlayV3Settings()->setReverseApiPort(settings.m_reverseAPIPort); + response.getSdrPlayV3Settings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex); +} + +int SDRPlayV3Input::webapiReportGet( + SWGSDRangel::SWGDeviceReport& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setSdrPlayV3Report(new SWGSDRangel::SWGSDRPlayV3Report()); + response.getSdrPlayV3Report()->init(); + webapiFormatDeviceReport(response); + return 200; +} + +void SDRPlayV3Input::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response) +{ + response.getSdrPlayV3Report()->setIntermediateFrequencies(new QList); + + for (unsigned int i = 0; i < SDRPlayV3IF::getNbIFs(); i++) + { + response.getSdrPlayV3Report()->getIntermediateFrequencies()->append(new SWGSDRangel::SWGFrequency); + response.getSdrPlayV3Report()->getIntermediateFrequencies()->back()->setFrequency(SDRPlayV3IF::getIF(i)); + } + + response.getSdrPlayV3Report()->setBandwidths(new QList); + + for (unsigned int i = 0; i < SDRPlayV3Bandwidths::getNbBandwidths(); i++) + { + response.getSdrPlayV3Report()->getBandwidths()->append(new SWGSDRangel::SWGBandwidth); + response.getSdrPlayV3Report()->getBandwidths()->back()->setBandwidth(SDRPlayV3Bandwidths::getBandwidth(i)); + } +} + +void SDRPlayV3Input::webapiReverseSendSettings(QList& deviceSettingsKeys, const SDRPlayV3Settings& settings, bool force) +{ + SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings(); + swgDeviceSettings->setDirection(0); // single Rx + swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex()); + swgDeviceSettings->setDeviceHwType(new QString("SDRplay")); + swgDeviceSettings->setSdrPlayV3Settings(new SWGSDRangel::SWGSDRPlayV3Settings()); + SWGSDRangel::SWGSDRPlayV3Settings *swgSDRPlayV3Settings = swgDeviceSettings->getSdrPlayV3Settings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (deviceSettingsKeys.contains("centerFrequency") || force) { + swgSDRPlayV3Settings->setCenterFrequency(settings.m_centerFrequency); + } + if (deviceSettingsKeys.contains("LOppmTenths") || force) { + swgSDRPlayV3Settings->setLOppmTenths(settings.m_LOppmTenths); + } + if (deviceSettingsKeys.contains("ifFrequencyIndex") || force) { + swgSDRPlayV3Settings->setIfFrequencyIndex(settings.m_ifFrequencyIndex); + } + if (deviceSettingsKeys.contains("bandwidthIndex") || force) { + swgSDRPlayV3Settings->setBandwidthIndex(settings.m_bandwidthIndex); + } + if (deviceSettingsKeys.contains("devSampleRate") || force) { + swgSDRPlayV3Settings->setDevSampleRate(settings.m_devSampleRate); + } + if (deviceSettingsKeys.contains("log2Decim") || force) { + swgSDRPlayV3Settings->setLog2Decim(settings.m_log2Decim); + } + if (deviceSettingsKeys.contains("fcPos") || force) { + swgSDRPlayV3Settings->setFcPos((int) settings.m_fcPos); + } + if (deviceSettingsKeys.contains("dcBlock") || force) { + swgSDRPlayV3Settings->setDcBlock(settings.m_dcBlock ? 1 : 0); + } + if (deviceSettingsKeys.contains("iqCorrection") || force) { + swgSDRPlayV3Settings->setIqCorrection(settings.m_iqCorrection ? 1 : 0); + } + if (deviceSettingsKeys.contains("lnaIndex") || force) { + swgSDRPlayV3Settings->setLnaIndex(settings.m_lnaIndex); + } + if (deviceSettingsKeys.contains("ifAGC") || force) { + swgSDRPlayV3Settings->setIfAgc(settings.m_ifAGC ? 1 : 0); + } + if (deviceSettingsKeys.contains("ifGain") || force) { + swgSDRPlayV3Settings->setIfGain(settings.m_ifGain); + } + if (deviceSettingsKeys.contains("amNotch") || force) { + swgSDRPlayV3Settings->setAmNotch(settings.m_amNotch); + } + if (deviceSettingsKeys.contains("fmNotch") || force) { + swgSDRPlayV3Settings->setFmNotch(settings.m_fmNotch); + } + if (deviceSettingsKeys.contains("dabNotch") || force) { + swgSDRPlayV3Settings->setDabNotch(settings.m_dabNotch); + } + if (deviceSettingsKeys.contains("extRef") || force) { + swgSDRPlayV3Settings->setExtRef(settings.m_extRef); + } + if (deviceSettingsKeys.contains("tuner") || force) { + swgSDRPlayV3Settings->setTuner(settings.m_tuner); + } + if (deviceSettingsKeys.contains("antenna") || force) { + swgSDRPlayV3Settings->setAntenna(settings.m_antenna); + } + + QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex); + m_networkRequest.setUrl(QUrl(deviceSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgDeviceSettings->asJson().toUtf8()); + buffer->seek(0); + + // Always use PATCH to avoid passing reverse API settings + QNetworkReply *reply = m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + buffer->setParent(reply); + + delete swgDeviceSettings; +} + +void SDRPlayV3Input::webapiReverseSendStartStop(bool start) +{ + SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings(); + swgDeviceSettings->setDirection(0); // single Rx + swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex()); + swgDeviceSettings->setDeviceHwType(new QString("SDRplay")); + + QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run") + .arg(m_settings.m_reverseAPIAddress) + .arg(m_settings.m_reverseAPIPort) + .arg(m_settings.m_reverseAPIDeviceIndex); + m_networkRequest.setUrl(QUrl(deviceSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer = new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgDeviceSettings->asJson().toUtf8()); + buffer->seek(0); + QNetworkReply *reply; + + if (start) { + reply = m_networkManager->sendCustomRequest(m_networkRequest, "POST", buffer); + } else { + reply = m_networkManager->sendCustomRequest(m_networkRequest, "DELETE", buffer); + } + + buffer->setParent(reply); + delete swgDeviceSettings; +} + +void SDRPlayV3Input::networkManagerFinished(QNetworkReply *reply) +{ + QNetworkReply::NetworkError replyError = reply->error(); + + if (replyError) + { + qWarning() << "SDRPlayV3Input::networkManagerFinished:" + << " error(" << (int) replyError + << "): " << replyError + << ": " << reply->errorString(); + } + else + { + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("SDRPlayV3Input::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); + } + + reply->deleteLater(); +} + +int SDRPlayV3Input::getDeviceId() +{ + if (m_dev != nullptr) + return m_dev->hwVer; // E.g. SDRPLAY_RSPduo_ID + else + return -1; +} + +// ==================================================================== + +sdrplay_api_Bw_MHzT SDRPlayV3Bandwidths::m_bwEnums[m_nb_bw] = { + sdrplay_api_BW_0_200, + sdrplay_api_BW_0_300, + sdrplay_api_BW_0_600, + sdrplay_api_BW_1_536, + sdrplay_api_BW_5_000, + sdrplay_api_BW_6_000, + sdrplay_api_BW_7_000, + sdrplay_api_BW_8_000 +}; + +unsigned int SDRPlayV3Bandwidths::m_bw[m_nb_bw] = { + 200000, // 0 + 300000, // 1 + 600000, // 2 + 1536000, // 3 + 5000000, // 4 + 6000000, // 5 + 7000000, // 6 + 8000000, // 7 +}; + +sdrplay_api_Bw_MHzT SDRPlayV3Bandwidths::getBandwidthEnum(unsigned int bandwidth_index) +{ + if (bandwidth_index < m_nb_bw) + { + return m_bwEnums[bandwidth_index]; + } + else + { + return m_bwEnums[0]; + } +} + +unsigned int SDRPlayV3Bandwidths::getBandwidth(unsigned int bandwidth_index) +{ + if (bandwidth_index < m_nb_bw) + { + return m_bw[bandwidth_index]; + } + else + { + return m_bw[0]; + } +} + +unsigned int SDRPlayV3Bandwidths::getBandwidthIndex(unsigned int bandwidth) +{ + for (unsigned int i=0; i < m_nb_bw; i++) + { + if (bandwidth == m_bw[i]) + { + return i; + } + } + + return 0; +} + +unsigned int SDRPlayV3Bandwidths::getNbBandwidths() +{ + return SDRPlayV3Bandwidths::m_nb_bw; +} + +// ==================================================================== + +sdrplay_api_If_kHzT SDRPlayV3IF::m_ifEnums[m_nb_if] = { + sdrplay_api_IF_Zero, + sdrplay_api_IF_0_450, + sdrplay_api_IF_1_620, + sdrplay_api_IF_2_048 +}; + +unsigned int SDRPlayV3IF::m_if[m_nb_if] = { + 0, // 0 + 450000, // 1 + 1620000, // 2 + 2048000, // 3 +}; + +sdrplay_api_If_kHzT SDRPlayV3IF::getIFEnum(unsigned int if_index) +{ + if (if_index < m_nb_if) + { + return m_ifEnums[if_index]; + } + else + { + return m_ifEnums[0]; + } +} + +unsigned int SDRPlayV3IF::getIF(unsigned int if_index) +{ + if (if_index < m_nb_if) + { + return m_if[if_index]; + } + else + { + return m_if[0]; + } +} + +unsigned int SDRPlayV3IF::getIFIndex(unsigned int iff) +{ + for (unsigned int i=0; i < m_nb_if; i++) + { + if (iff == m_if[i]) + { + return i; + } + } + + return 0; +} + +unsigned int SDRPlayV3IF::getNbIFs() +{ + return SDRPlayV3IF::m_nb_if; +} + +// ==================================================================== + +// LNA state attenuation values - for some devices, such as rsp1, this is combination of LNA and mixer attenuation + +const int SDRPlayV3LNA::rsp1Attenuation[3][5] = +{ + {4, 0, 24, 19, 43}, + {4, 0, 7, 19, 26}, + {4, 0, 5, 19, 24} +}; + +const int SDRPlayV3LNA::rsp1AAttenuation[4][11] = +{ + {7, 0, 6, 12, 18, 37, 42, 61}, + {10, 0, 6, 12, 18, 20, 26, 32, 38, 57, 62}, + {10, 0, 7, 13, 19, 20, 27, 33, 39, 45, 64}, + { 9, 0, 6, 12, 20, 26, 32, 38, 43, 62} +}; + +const int SDRPlayV3LNA::rsp2Attenuation[3][10] = +{ + {9, 0, 10, 15, 21, 24, 34, 39, 45, 64}, + {6, 0, 7, 10, 17, 22, 41}, + {6, 0, 5, 21, 15, 15, 32} +}; + +const int SDRPlayV3LNA::rspDuoAttenuation[5][11] = +{ + { 7, 0, 6, 12, 18, 37, 42, 61}, + {10, 0, 6, 12, 18, 20, 26, 32, 38, 57, 62}, + {10, 0, 7, 13, 19, 20, 27, 33, 39, 45, 64}, + { 9, 0, 6, 12, 20, 26, 32, 38, 43, 62}, + { 5, 0, 6, 12, 18, 37} +}; + +const int SDRPlayV3LNA::rspDxAttenuation[6][28] = +{ + {22, 0, 3, 6, 9, 12, 15, 18, 21, 24, 25, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60}, + {19, 0, 3, 6, 9, 12, 15, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60}, + {20, 0, 3, 6, 9, 12, 15, 18, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60}, + {27, 0, 3, 6, 9, 12, 15, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84}, + {21, 0, 7, 10, 13, 16, 19, 22, 25, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58, 61, 64, 67}, + {19, 0, 5, 8, 11, 14, 17, 20, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65} +}; + +const int *SDRPlayV3LNA::getAttenuations(int deviceId, qint64 frequency) +{ + int row; + const int *lnaAttenuation; + + switch (deviceId) + { + case SDRPLAY_RSP1_ID: + if (frequency < 420000000) + row = 0; + else if (frequency < 10000000000) + row = 1; + else + row = 2; + lnaAttenuation = &rsp1Attenuation[row][0]; + break; + case SDRPLAY_RSP1A_ID: + if (frequency < 60000000) + row = 0; + else if (frequency < 420000000) + row = 1; + else if (frequency < 1000000000) + row = 2; + else + row = 3; + lnaAttenuation = &rsp1AAttenuation[row][0]; + break; + case SDRPLAY_RSP2_ID: + if (frequency < 420000000) + row = 0; + else if (frequency < 1000000000) + row = 1; + else + row = 2; + lnaAttenuation = &rsp2Attenuation[row][0]; + break; + case SDRPLAY_RSPduo_ID: + if (frequency < 60000000) + row = 0; + else if (frequency < 420000000) + row = 1; + else if (frequency < 1000000000) + row = 2; + else + row = 3; + lnaAttenuation = &rspDuoAttenuation[row][0]; + break; + case SDRPLAY_RSPdx_ID: + if (frequency < 2) + row = 0; + else if (frequency < 12000000) + row = 1; + else if (frequency < 60000000) + row = 2; + else if (frequency < 250000000) + row = 3; + else if (frequency < 420000000) + row = 4; + else if (frequency < 1000000000) + row = 5; + else + row = 6; + lnaAttenuation = &rspDxAttenuation[row][0]; + break; + default: + lnaAttenuation = nullptr; + break; + } + return lnaAttenuation; +} + diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3input.h b/plugins/samplesource/sdrplayv3/sdrplayv3input.h new file mode 100644 index 000000000..3d588b1e7 --- /dev/null +++ b/plugins/samplesource/sdrplayv3/sdrplayv3input.h @@ -0,0 +1,200 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3INPUT_H_ +#define PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3INPUT_H_ + +#include + +#include +#include +#include + +#include +#include "dsp/devicesamplesource.h" +#include "sdrplayv3settings.h" + +class QNetworkAccessManager; +class QNetworkReply; +class DeviceAPI; +class SDRPlayV3Thread; + +class SDRPlayV3Input : public DeviceSampleSource { + Q_OBJECT +public: + + class MsgConfigureSDRPlayV3 : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const SDRPlayV3Settings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureSDRPlayV3* create(const SDRPlayV3Settings& settings, bool force) + { + return new MsgConfigureSDRPlayV3(settings, force); + } + + private: + SDRPlayV3Settings m_settings; + bool m_force; + + MsgConfigureSDRPlayV3(const SDRPlayV3Settings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + class MsgStartStop : public Message { + MESSAGE_CLASS_DECLARATION + + public: + bool getStartStop() const { return m_startStop; } + + static MsgStartStop* create(bool startStop) { + return new MsgStartStop(startStop); + } + + protected: + bool m_startStop; + + MsgStartStop(bool startStop) : + Message(), + m_startStop(startStop) + { } + }; + + SDRPlayV3Input(DeviceAPI *deviceAPI); + virtual ~SDRPlayV3Input(); + virtual void destroy(); + + virtual void init(); + virtual bool start(); + virtual void stop(); + + 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 void setSampleRate(int sampleRate) { (void) sampleRate; } + 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); + + static void webapiFormatDeviceSettings( + SWGSDRangel::SWGDeviceSettings& response, + const SDRPlayV3Settings& settings); + + static void webapiUpdateDeviceSettings( + SDRPlayV3Settings& settings, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response); + + int getDeviceId(); + +private: + DeviceAPI *m_deviceAPI; + QMutex m_mutex; + SDRPlayV3Settings m_settings; + sdrplay_api_DeviceT m_devs[SDRPLAY_MAX_DEVICES]; + sdrplay_api_DeviceT* m_dev; + sdrplay_api_DeviceParamsT *m_devParams; + SDRPlayV3Thread* m_sdrPlayThread; + QString m_deviceDescription; + int m_devNumber; + bool m_running; + QNetworkAccessManager *m_networkManager; + QNetworkRequest m_networkRequest; + + bool openDevice(); + void closeDevice(); + bool applySettings(const SDRPlayV3Settings& settings, bool forwardChange, bool force); + bool setDeviceCenterFrequency(quint64 freq); + void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response); + void webapiReverseSendSettings(QList& deviceSettingsKeys, const SDRPlayV3Settings& settings, bool force); + void webapiReverseSendStartStop(bool start); + +private slots: + void networkManagerFinished(QNetworkReply *reply); +}; + +// ==================================================================== + +class SDRPlayV3Bandwidths { +public: + static sdrplay_api_Bw_MHzT getBandwidthEnum(unsigned int bandwidth_index); + static unsigned int getBandwidth(unsigned int bandwidth_index); + static unsigned int getBandwidthIndex(unsigned int bandwidth); + static unsigned int getNbBandwidths(); +private: + static const unsigned int m_nb_bw = 8; + static unsigned int m_bw[m_nb_bw]; + static sdrplay_api_Bw_MHzT m_bwEnums[m_nb_bw]; +}; + +class SDRPlayV3IF { +public: + static sdrplay_api_If_kHzT getIFEnum(unsigned int if_index); + static unsigned int getIF(unsigned int if_index); + static unsigned int getIFIndex(unsigned int iff); + static unsigned int getNbIFs(); +private: + static const unsigned int m_nb_if = 4; + static unsigned int m_if[m_nb_if]; + static sdrplay_api_If_kHzT m_ifEnums[m_nb_if]; +}; + +class SDRPlayV3LNA { +public: + static const int *getAttenuations(int deviceId, qint64 frequency); +private: + static const int rsp1Attenuation[3][5]; + static const int rsp1AAttenuation[4][11]; + static const int rsp2Attenuation[3][10]; + static const int rspDuoAttenuation[5][11]; + static const int rspDxAttenuation[6][28]; +}; + +#endif /* PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3INPUT_H_ */ diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3plugin.cpp b/plugins/samplesource/sdrplayv3/sdrplayv3plugin.cpp new file mode 100644 index 000000000..aab72c2f3 --- /dev/null +++ b/plugins/samplesource/sdrplayv3/sdrplayv3plugin.cpp @@ -0,0 +1,185 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "plugin/pluginapi.h" +#include "util/simpleserializer.h" + +#ifdef SERVER_MODE +#include "sdrplayv3input.h" +#else +#include "sdrplayv3gui.h" +#endif +#include "sdrplayv3plugin.h" +#include "sdrplayv3webapiadapter.h" + +const PluginDescriptor SDRPlayV3Plugin::m_pluginDescriptor = { + QStringLiteral("SDRPlayV3"), + QStringLiteral("SDRPlayV3 Input"), + QStringLiteral("6.7.1"), + QStringLiteral("(c) Jon Beniston, M7RCE and Edouard Griffiths, F4EXB"), + QStringLiteral("https://github.com/f4exb/sdrangel"), + true, + QStringLiteral("https://github.com/f4exb/sdrangel") +}; + +static constexpr const char* const m_hardwareID = "SDRplayV3"; +static constexpr const char* const m_deviceTypeID = SDRPLAYV3_DEVICE_TYPE_ID; + +SDRPlayV3Plugin::SDRPlayV3Plugin(QObject* parent) : + QObject(parent) +{ + sdrplay_api_ErrT err; + float ver = 0.0f; + + qDebug() << "SDRPlayV3Plugin: calling sdrplay_api_Open()"; + if ((err = sdrplay_api_Open()) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Plugin::SDRPlayV3Plugin: sdrplay_api_Open() was unsuccessful. " << sdrplay_api_GetErrorString(err); + + if ((err = sdrplay_api_ApiVersion(&ver)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Plugin::SDRPlayV3Plugin: failed to get SDRPlay API version."; + + if (ver != SDRPLAY_API_VERSION) + qCritical() << "SDRPlayV3Plugin::SDRPlayV3Plugin: SDRPlay API versions do not match " << ver << " " << SDRPLAY_API_VERSION; +} + +SDRPlayV3Plugin::~SDRPlayV3Plugin() +{ + sdrplay_api_Close(); +} + +const PluginDescriptor& SDRPlayV3Plugin::getPluginDescriptor() const +{ + return m_pluginDescriptor; +} + +void SDRPlayV3Plugin::initPlugin(PluginAPI* pluginAPI) +{ + pluginAPI->registerSampleSource(m_deviceTypeID, this); +} + +void SDRPlayV3Plugin::enumOriginDevices(QStringList& listedHwIds, OriginDevices& originDevices) +{ + if (listedHwIds.contains(m_hardwareID)) { // check if it was done + return; + } + + sdrplay_api_LockDeviceApi(); + + sdrplay_api_ErrT err; + sdrplay_api_DeviceT devs[6]; + unsigned int count; + if ((err = sdrplay_api_GetDevices(devs, &count, sizeof(devs) / sizeof(sdrplay_api_DeviceT))) == sdrplay_api_Success) + { + for(unsigned int i = 0; i < count; i++) + { + qDebug("SDRPlayV3Plugin::enumSampleSources: found %d - %s", devs[i].hwVer, devs[i].SerNo); + QString displayableName(QString("SDRPlayV3[%1] %2").arg(i).arg(devs[i].SerNo)); + + originDevices.append(OriginDevice( + displayableName, + m_hardwareID, + devs[i].SerNo, + i, // sequence + 1, // Nb Rx + 0 // Nb Tx + )); + } + + listedHwIds.append(m_hardwareID); + } + else + qCritical() << "SDRPlayV3Plugin::enumOriginDevices: Failed to get SDRPlay devices: " << sdrplay_api_GetErrorString(err); + + sdrplay_api_UnlockDeviceApi(); +} + +PluginInterface::SamplingDevices SDRPlayV3Plugin::enumSampleSources(const OriginDevices& originDevices) +{ + SamplingDevices result; + + for (OriginDevices::const_iterator it = originDevices.begin(); it != originDevices.end(); ++it) + { + if (it->hardwareId == m_hardwareID) + { + result.append(SamplingDevice( + it->displayableName, + it->hardwareId, + m_deviceTypeID, + it->serial, + it->sequence, + PluginInterface::SamplingDevice::PhysicalDevice, + PluginInterface::SamplingDevice::StreamSingleRx, + 1, + 0 + )); + qDebug("SDRPlayV3Plugin::enumSampleSources: enumerated SDRPlayV3 RSP1 device #%d", it->sequence); + } + } + + return result; +} + +#ifdef SERVER_MODE +DeviceGUI* SDRPlayV3Plugin::createSampleSourcePluginInstanceGUI( + const QString& sourceId, + QWidget **widget, + DeviceUISet *deviceUISet) +{ + (void) sourceId; + (void) widget; + (void) deviceUISet; + return 0; +} +#else +DeviceGUI* SDRPlayV3Plugin::createSampleSourcePluginInstanceGUI( + const QString& sourceId, + QWidget **widget, + DeviceUISet *deviceUISet) +{ + if(sourceId == m_deviceTypeID) + { + SDRPlayV3Gui* gui = new SDRPlayV3Gui(deviceUISet); + *widget = gui; + return gui; + } + else + { + return 0; + } +} +#endif + +DeviceSampleSource *SDRPlayV3Plugin::createSampleSourcePluginInstance(const QString& sourceId, DeviceAPI *deviceAPI) +{ + if (sourceId == m_deviceTypeID) + { + SDRPlayV3Input* input = new SDRPlayV3Input(deviceAPI); + return input; + } + else + { + return 0; + } +} + +DeviceWebAPIAdapter *SDRPlayV3Plugin::createDeviceWebAPIAdapter() const +{ + return new SDRPlayV3WebAPIAdapter(); +} diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3plugin.h b/plugins/samplesource/sdrplayv3/sdrplayv3plugin.h new file mode 100644 index 000000000..fc180c32f --- /dev/null +++ b/plugins/samplesource/sdrplayv3/sdrplayv3plugin.h @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3PLUGIN_H_ +#define PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3PLUGIN_H_ + +#include +#include "plugin/plugininterface.h" + +class PluginAPI; + +#define SDRPLAYV3_DEVICE_TYPE_ID "sdrangel.samplesource.sdrplayv3" + +class SDRPlayV3Plugin : public QObject, public PluginInterface { + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID SDRPLAYV3_DEVICE_TYPE_ID) + +public: + explicit SDRPlayV3Plugin(QObject* parent = NULL); + ~SDRPlayV3Plugin(); + + const PluginDescriptor& getPluginDescriptor() const; + void initPlugin(PluginAPI* pluginAPI); + + virtual void enumOriginDevices(QStringList& listedHwIds, OriginDevices& originDevices); + virtual SamplingDevices enumSampleSources(const OriginDevices& originDevices); + virtual DeviceGUI* createSampleSourcePluginInstanceGUI( + const QString& sourceId, + QWidget **widget, + DeviceUISet *deviceUISet); + virtual DeviceSampleSource* createSampleSourcePluginInstance(const QString& sourceId, DeviceAPI *deviceAPI); + virtual DeviceWebAPIAdapter* createDeviceWebAPIAdapter() const; + +private: + static const PluginDescriptor m_pluginDescriptor; +}; + +#endif /* PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3PLUGIN_H_ */ diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3settings.cpp b/plugins/samplesource/sdrplayv3/sdrplayv3settings.cpp new file mode 100644 index 000000000..668330c13 --- /dev/null +++ b/plugins/samplesource/sdrplayv3/sdrplayv3settings.cpp @@ -0,0 +1,139 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "sdrplayv3settings.h" + +#include +#include "util/simpleserializer.h" + +SDRPlayV3Settings::SDRPlayV3Settings() +{ + resetToDefaults(); +} + +void SDRPlayV3Settings::resetToDefaults() +{ + m_centerFrequency = 7040*1000; + m_LOppmTenths = 0; + m_ifFrequencyIndex = 0; + m_bandwidthIndex = 0; + m_devSampleRate = 2000000; + m_log2Decim = 0; + m_fcPos = FC_POS_CENTER; + m_dcBlock = false; + m_iqCorrection = false; + m_lnaIndex = 0; + m_ifAGC = true; + m_ifGain = 29; + m_amNotch = false; + m_fmNotch = false; + m_dabNotch = false; + m_biasTee = false; + m_tuner = 0; + m_antenna = 0; + m_extRef = false; + m_useReverseAPI = false; + m_reverseAPIAddress = "127.0.0.1"; + m_reverseAPIPort = 8888; + m_reverseAPIDeviceIndex = 0; +} + +QByteArray SDRPlayV3Settings::serialize() const +{ + SimpleSerializer s(1); + + s.writeS32(1, m_LOppmTenths); + s.writeU32(3, m_ifFrequencyIndex); + s.writeU32(5, m_bandwidthIndex); + s.writeU32(6, m_devSampleRate); + s.writeU32(7, m_log2Decim); + s.writeS32(8, (int) m_fcPos); + s.writeBool(9, m_dcBlock); + s.writeBool(10, m_iqCorrection); + s.writeS32(11, m_lnaIndex); + s.writeBool(13, m_ifAGC); + s.writeS32(14, m_ifGain); + s.writeBool(15, m_useReverseAPI); + s.writeString(16, m_reverseAPIAddress); + s.writeU32(17, m_reverseAPIPort); + s.writeU32(18, m_reverseAPIDeviceIndex); + s.writeBool(19, m_amNotch); + s.writeBool(20, m_fmNotch); + s.writeBool(21, m_dabNotch); + s.writeBool(22, m_biasTee); + s.writeS32(23, m_tuner); + s.writeS32(24, m_antenna); + s.writeBool(25, m_extRef); + return s.final(); +} + +bool SDRPlayV3Settings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if (!d.isValid()) + { + resetToDefaults(); + return false; + } + + if (d.getVersion() == 1) + { + int intval; + uint32_t uintval; + + d.readS32(1, &m_LOppmTenths, 0); + d.readU32(3, &m_ifFrequencyIndex, 0); + d.readU32(5, &m_bandwidthIndex, 0); + d.readU32(6, &m_devSampleRate, 2000000); + d.readU32(7, &m_log2Decim, 0); + d.readS32(8, &intval, 0); + m_fcPos = (fcPos_t) intval; + d.readBool(9, &m_dcBlock, false); + d.readBool(10, &m_iqCorrection, false); + d.readS32(11, &m_lnaIndex, 0); + d.readBool(13, &m_ifAGC, true); + d.readS32(14, &m_ifGain, 29); + d.readBool(15, &m_useReverseAPI, false); + d.readString(16, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(17, &uintval, 0); + + if ((uintval > 1023) && (uintval < 65535)) { + m_reverseAPIPort = uintval; + } else { + m_reverseAPIPort = 8888; + } + + d.readU32(18, &uintval, 0); + m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval; + d.readBool(19, &m_amNotch, false); + d.readBool(20, &m_fmNotch, false); + d.readBool(21, &m_dabNotch, false); + d.readBool(22, &m_biasTee, false); + d.readS32(23, &m_tuner, 0); + d.readS32(24, &m_antenna, 0); + d.readBool(25, &m_extRef, false); + + return true; + } + else + { + resetToDefaults(); + return false; + } +} diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3settings.h b/plugins/samplesource/sdrplayv3/sdrplayv3settings.h new file mode 100644 index 000000000..268d9326f --- /dev/null +++ b/plugins/samplesource/sdrplayv3/sdrplayv3settings.h @@ -0,0 +1,88 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef _SDRPLAYV3_SDRPLAYV3SETTINGS_H_ +#define _SDRPLAYV3_SDRPLAYV3SETTINGS_H_ + +#include +#include +#include +#include + +struct SDRPlayV3Settings { + typedef enum { + FC_POS_INFRA = 0, + FC_POS_SUPRA, + FC_POS_CENTER + } fcPos_t; + + uint64_t m_centerFrequency; + int32_t m_LOppmTenths; + uint32_t m_ifFrequencyIndex; + uint32_t m_bandwidthIndex; + uint32_t m_devSampleRate; + uint32_t m_log2Decim; + fcPos_t m_fcPos; + bool m_dcBlock; + bool m_iqCorrection; + int m_lnaIndex; + bool m_ifAGC; + int m_ifGain; + bool m_amNotch; + bool m_fmNotch; + bool m_dabNotch; + bool m_biasTee; + int m_tuner; + int m_antenna; + bool m_extRef; + bool m_useReverseAPI; + QString m_reverseAPIAddress; + uint16_t m_reverseAPIPort; + uint16_t m_reverseAPIDeviceIndex; + + SDRPlayV3Settings(); + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + + void debug(const char *title) const + { + qDebug() << QString(title) + << ": m_centerFrequency: " << m_centerFrequency + << " m_LOppmTenths: " << m_LOppmTenths + << " m_ifFrequencyIndex: " << m_ifFrequencyIndex + << " m_bandwidthIndex: " << m_bandwidthIndex + << " m_devSampleRate: " << m_devSampleRate + << " m_log2Decim: " << m_log2Decim + << " m_fcPos: " << m_fcPos + << " m_dcBlock: " << m_dcBlock + << " m_iqCorrection: " << m_iqCorrection + << " m_lnaIndex: " << m_lnaIndex + << " m_ifAGC: " << m_ifAGC + << " m_ifGain: " << m_ifGain + << " m_amNotch: " << m_amNotch + << " m_fmNotch: " << m_fmNotch + << " m_dabNotch: " << m_dabNotch + << " m_biasTee: " << m_biasTee + << " m_tuner: " << m_tuner + << " m_antenna: " << m_antenna + << " m_extRef: " << m_extRef; + } +}; + +#endif /* _SDRPLAYV3_SDRPLAYV3SETTINGS_H_ */ diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3thread.cpp b/plugins/samplesource/sdrplayv3/sdrplayv3thread.cpp new file mode 100644 index 000000000..cb6b7ce90 --- /dev/null +++ b/plugins/samplesource/sdrplayv3/sdrplayv3thread.cpp @@ -0,0 +1,220 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "sdrplayv3thread.h" +#include "dsp/samplesinkfifo.h" + +#include + +SDRPlayV3Thread::SDRPlayV3Thread(sdrplay_api_DeviceT* dev, SampleSinkFifo* sampleFifo, QObject* parent) : + QThread(parent), + m_running(false), + m_dev(dev), + m_convertBuffer(SDRPLAYV3_INIT_NBSAMPLES), + m_sampleFifo(sampleFifo), + m_samplerate(2000000), + m_log2Decim(0), + m_fcPos(0) +{ +} + +SDRPlayV3Thread::~SDRPlayV3Thread() +{ + stopWork(); +} + +void SDRPlayV3Thread::startWork() +{ + m_startWaitMutex.lock(); + start(); + while(!m_running) + m_startWaiter.wait(&m_startWaitMutex, 100); + m_startWaitMutex.unlock(); +} + +void SDRPlayV3Thread::stopWork() +{ + sdrplay_api_ErrT err; + + if (m_running) + { + m_running = false; + if ((err = sdrplay_api_Uninit(m_dev->dev)) != sdrplay_api_Success) + qWarning() << "SDRPlayV3Thread::callbackHelper: sdrplay_api_Uninit error: " << sdrplay_api_GetErrorString(err); + } + wait(); +} + +void SDRPlayV3Thread::setSamplerate(int samplerate) +{ + m_samplerate = samplerate; +} + +void SDRPlayV3Thread::setLog2Decimation(unsigned int log2_decim) +{ + m_log2Decim = log2_decim; +} + +void SDRPlayV3Thread::setFcPos(int fcPos) +{ + m_fcPos = fcPos; +} + +// Don't really need a thread here - just using same structure as other plugins +void SDRPlayV3Thread::run() +{ + sdrplay_api_ErrT err; + sdrplay_api_CallbackFnsT cbFns; + + cbFns.StreamACbFn = &SDRPlayV3Thread::callbackHelper; + cbFns.StreamBCbFn = &SDRPlayV3Thread::callbackHelper; + cbFns.EventCbFn = &SDRPlayV3Thread::eventCallback; + + if ((err = sdrplay_api_Init(m_dev->dev, &cbFns, this)) != sdrplay_api_Success) + qCritical() << "SDRPlayV3Thread::run: sdrplay_api_Init error: " << sdrplay_api_GetErrorString(err); + + m_running = true; + m_startWaiter.wakeAll(); +} + +void SDRPlayV3Thread::eventCallback(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext) +{ + // Could possibly report params->gainParams.currGain for eventId == sdrplay_api_GainChange + // or indicate ADC overload for eventId == sdrplay_api_PowerOverloadChange + (void) eventId; + (void) tuner; + (void) params; + (void) cbContext; +} + +void SDRPlayV3Thread::callbackHelper(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *ctx) +{ + (void) params; + (void) reset; + SDRPlayV3Thread* thread = (SDRPlayV3Thread*) ctx; + qint16 iq[8192]; + + if (thread->m_running) + { + if (numSamples > 8192) + qCritical() << "SDRPlayV3Thread::callbackHelper: IQ buffer too small: " << numSamples; + + for (int i = 0; i < numSamples; i++) + { + iq[i*2] = xi[i]; + iq[i*2+1] = xq[i]; + } + + thread->callbackIQ(iq, numSamples*2); + } +} + +void SDRPlayV3Thread::callbackIQ(const qint16* buf, qint32 len) +{ + SampleVector::iterator it = m_convertBuffer.begin(); + + if (m_log2Decim == 0) + { + m_decimatorsIQ.decimate1(&it, buf, len); + } + else + { + if (m_fcPos == 0) // Infradyne + { + switch (m_log2Decim) + { + case 1: + m_decimatorsIQ.decimate2_inf(&it, buf, len); + break; + case 2: + m_decimatorsIQ.decimate4_inf(&it, buf, len); + break; + case 3: + m_decimatorsIQ.decimate8_inf(&it, buf, len); + break; + case 4: + m_decimatorsIQ.decimate16_inf(&it, buf, len); + break; + case 5: + m_decimatorsIQ.decimate32_inf(&it, buf, len); + break; + case 6: + m_decimatorsIQ.decimate64_inf(&it, buf, len); + break; + default: + break; + } + } + else if (m_fcPos == 1) // Supradyne + { + switch (m_log2Decim) + { + case 1: + m_decimatorsIQ.decimate2_sup(&it, buf, len); + break; + case 2: + m_decimatorsIQ.decimate4_sup(&it, buf, len); + break; + case 3: + m_decimatorsIQ.decimate8_sup(&it, buf, len); + break; + case 4: + m_decimatorsIQ.decimate16_sup(&it, buf, len); + break; + case 5: + m_decimatorsIQ.decimate32_sup(&it, buf, len); + break; + case 6: + m_decimatorsIQ.decimate64_sup(&it, buf, len); + break; + default: + break; + } + } + else // Centered + { + switch (m_log2Decim) + { + case 1: + m_decimatorsIQ.decimate2_cen(&it, buf, len); + break; + case 2: + m_decimatorsIQ.decimate4_cen(&it, buf, len); + break; + case 3: + m_decimatorsIQ.decimate8_cen(&it, buf, len); + break; + case 4: + m_decimatorsIQ.decimate16_cen(&it, buf, len); + break; + case 5: + m_decimatorsIQ.decimate32_cen(&it, buf, len); + break; + case 6: + m_decimatorsIQ.decimate64_cen(&it, buf, len); + break; + default: + break; + } + } + } + + m_sampleFifo->write(m_convertBuffer.begin(), it); +} diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3thread.h b/plugins/samplesource/sdrplayv3/sdrplayv3thread.h new file mode 100644 index 000000000..a62becc25 --- /dev/null +++ b/plugins/samplesource/sdrplayv3/sdrplayv3thread.h @@ -0,0 +1,66 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3THREAD_H_ +#define PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3THREAD_H_ + +#include +#include +#include +#include +#include "dsp/samplesinkfifo.h" +#include "dsp/decimators.h" + +#define SDRPLAYV3_INIT_NBSAMPLES (1<<14) + +class SDRPlayV3Thread : public QThread { + Q_OBJECT + +public: + SDRPlayV3Thread(sdrplay_api_DeviceT* dev, SampleSinkFifo* sampleFifo, QObject* parent = NULL); + ~SDRPlayV3Thread(); + + void startWork(); + void stopWork(); + void setSamplerate(int samplerate); + void setLog2Decimation(unsigned int log2_decim); + void setFcPos(int fcPos); + +private: + QMutex m_startWaitMutex; + QWaitCondition m_startWaiter; + bool m_running; + + sdrplay_api_DeviceT *m_dev; + SampleVector m_convertBuffer; + SampleSinkFifo* m_sampleFifo; + + int m_samplerate; + unsigned int m_log2Decim; + int m_fcPos; + + Decimators m_decimatorsIQ; + + void run(); + void callbackIQ(const qint16* buf, qint32 len); + + static void callbackHelper(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *ctx); + static void eventCallback(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext); +}; + +#endif /* PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3THREAD_H_ */ diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3webapiadapter.cpp b/plugins/samplesource/sdrplayv3/sdrplayv3webapiadapter.cpp new file mode 100644 index 000000000..03e46e6e4 --- /dev/null +++ b/plugins/samplesource/sdrplayv3/sdrplayv3webapiadapter.cpp @@ -0,0 +1,53 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// Implementation of static web API adapters used for preset serialization and // +// deserialization // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "SWGDeviceSettings.h" +#include "sdrplayv3input.h" +#include "sdrplayv3webapiadapter.h" + +SDRPlayV3WebAPIAdapter::SDRPlayV3WebAPIAdapter() +{} + +SDRPlayV3WebAPIAdapter::~SDRPlayV3WebAPIAdapter() +{} + +int SDRPlayV3WebAPIAdapter::webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setSdrPlayV3Settings(new SWGSDRangel::SWGSDRPlayV3Settings()); + response.getSdrPlayV3Settings()->init(); + SDRPlayV3Input::webapiFormatDeviceSettings(response, m_settings); + return 200; +} + +int SDRPlayV3WebAPIAdapter::webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage) +{ + (void) force; // no action + (void) errorMessage; + SDRPlayV3Input::webapiUpdateDeviceSettings(m_settings, deviceSettingsKeys, response); + return 200; +} diff --git a/plugins/samplesource/sdrplayv3/sdrplayv3webapiadapter.h b/plugins/samplesource/sdrplayv3/sdrplayv3webapiadapter.h new file mode 100644 index 000000000..65227d6cc --- /dev/null +++ b/plugins/samplesource/sdrplayv3/sdrplayv3webapiadapter.h @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// Implementation of static web API adapters used for preset serialization and // +// deserialization // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "device/devicewebapiadapter.h" +#include "sdrplayv3settings.h" + +class SDRPlayV3WebAPIAdapter : public DeviceWebAPIAdapter +{ +public: + SDRPlayV3WebAPIAdapter(); + virtual ~SDRPlayV3WebAPIAdapter(); + virtual QByteArray serialize() { return m_settings.serialize(); } + virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); } + + virtual int webapiSettingsGet( + SWGSDRangel::SWGDeviceSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& deviceSettingsKeys, + SWGSDRangel::SWGDeviceSettings& response, // query + response + QString& errorMessage); + +private: + SDRPlayV3Settings m_settings; +}; diff --git a/sdrbase/webapi/webapirequestmapper.cpp b/sdrbase/webapi/webapirequestmapper.cpp index 0c16ec371..7ca1a9f38 100644 --- a/sdrbase/webapi/webapirequestmapper.cpp +++ b/sdrbase/webapi/webapirequestmapper.cpp @@ -4243,6 +4243,11 @@ bool WebAPIRequestMapper::getDeviceSettings( deviceSettings->setSdrPlaySettings(new SWGSDRangel::SWGSDRPlaySettings()); deviceSettings->getSdrPlaySettings()->fromJsonObject(settingsJsonObject); } + else if (deviceSettingsKey == "sdrPlayV3Settings") + { + deviceSettings->setSdrPlayV3Settings(new SWGSDRangel::SWGSDRPlayV3Settings()); + deviceSettings->getSdrPlayV3Settings()->fromJsonObject(settingsJsonObject); + } else if (deviceSettingsKey == "sigMFFileInputSettings") { deviceSettings->setSigMfFileInputSettings(new SWGSDRangel::SWGSigMFFileInputSettings()); @@ -4546,6 +4551,7 @@ void WebAPIRequestMapper::resetDeviceSettings(SWGSDRangel::SWGDeviceSettings& de deviceSettings.setRemoteOutputSettings(nullptr); deviceSettings.setRemoteInputSettings(nullptr); deviceSettings.setSdrPlaySettings(nullptr); + deviceSettings.setSdrPlayV3Settings(nullptr); deviceSettings.setTestSourceSettings(nullptr); deviceSettings.setUsrpInputSettings(nullptr); deviceSettings.setUsrpOutputSettings(nullptr); @@ -4567,6 +4573,7 @@ void WebAPIRequestMapper::resetDeviceReport(SWGSDRangel::SWGDeviceReport& device deviceReport.setRemoteOutputReport(nullptr); deviceReport.setRemoteInputReport(nullptr); deviceReport.setSdrPlayReport(nullptr); + deviceReport.setSdrPlayV3Report(nullptr); deviceReport.setUsrpOutputReport(nullptr); } diff --git a/sdrbase/webapi/webapiutils.cpp b/sdrbase/webapi/webapiutils.cpp index 4af9d71d8..134368b34 100644 --- a/sdrbase/webapi/webapiutils.cpp +++ b/sdrbase/webapi/webapiutils.cpp @@ -105,6 +105,7 @@ const QMap WebAPIUtils::m_deviceIdToSettingsKey = { {"sdrangel.samplesource.remoteinput", "remoteInputSettings"}, {"sdrangel.samplesink.remoteoutput", "remoteOutputSettings"}, {"sdrangel.samplesource.sdrplay", "sdrPlaySettings"}, + {"sdrangel.samplesource.sdrplayv3", "sdrPlayV3Settings"}, {"sdrangel.samplesource.sigmffileinput", "sigMFFileInputSettings"}, {"sdrangel.samplesource.soapysdrinput", "soapySDRInputSettings"}, {"sdrangel.samplesink.soapysdroutput", "soapySDROutputSettings"}, @@ -185,6 +186,7 @@ const QMap WebAPIUtils::m_sourceDeviceHwIdToSettingsKey = { {"RTLSDR", "rtlSdrSettings"}, {"RemoteInput", "remoteInputSettings"}, {"SDRplay1", "sdrPlaySettings"}, + {"SDRplay", "sdrPlayV3Settings"}, {"SigMFFileInput", "sigMFFileInputSettings"}, {"SoapySDR", "soapySDRInputSettings"}, {"TestSource", "testSourceSettings"}, @@ -208,6 +210,7 @@ const QMap WebAPIUtils::m_sourceDeviceHwIdToActionsKey = { {"RemoteInput", "remoteInputActions"}, {"RTLSDR", "rtlSdrActions"}, {"SDRplay1", "sdrPlayActions"}, + {"SDRplay", "sdrPlayV3Actions"}, {"SigMFFileInput", "sigMFFileActions"}, {"SoapySDR", "soapySDRInputActions"}, {"TestSource", "testSourceActions"}, diff --git a/swagger/sdrangel/api/swagger/include/DeviceReports.yaml b/swagger/sdrangel/api/swagger/include/DeviceReports.yaml index 1f6a4db49..9ca55ea3c 100644 --- a/swagger/sdrangel/api/swagger/include/DeviceReports.yaml +++ b/swagger/sdrangel/api/swagger/include/DeviceReports.yaml @@ -49,6 +49,8 @@ DeviceReport: $ref: "http://swgserver:8081/api/swagger/include/RemoteInput.yaml#/RemoteInputReport" sdrPlayReport: $ref: "http://swgserver:8081/api/swagger/include/SDRPlay.yaml#/SDRPlayReport" + sdrPlayV3Report: + $ref: "http://swgserver:8081/api/swagger/include/SDRPlayV3.yaml#/SDRPlayV3Report" sigMFFileInputReport: $ref: "http://swgserver:8081/api/swagger/include/SigMFFileInput.yaml#/SigMFFileInputReport" soapySDRInputReport: diff --git a/swagger/sdrangel/api/swagger/include/DeviceSettings.yaml b/swagger/sdrangel/api/swagger/include/DeviceSettings.yaml index 03a6922ee..c7babbde8 100644 --- a/swagger/sdrangel/api/swagger/include/DeviceSettings.yaml +++ b/swagger/sdrangel/api/swagger/include/DeviceSettings.yaml @@ -70,6 +70,8 @@ DeviceSettings: $ref: "http://swgserver:8081/api/swagger/include/RemoteInput.yaml#/RemoteInputSettings" sdrPlaySettings: $ref: "http://swgserver:8081/api/swagger/include/SDRPlay.yaml#/SDRPlaySettings" + sdrPlayV3Settings: + $ref: "http://swgserver:8081/api/swagger/include/SDRPlayV3.yaml#/SDRPlayV3Settings" sigMFFileInputSettings: $ref: "http://swgserver:8081/api/swagger/include/SigMFFileInput.yaml#/SigMFFileInputSettings" soapySDRInputSettings: diff --git a/swagger/sdrangel/api/swagger/include/SDRPlayV3.yaml b/swagger/sdrangel/api/swagger/include/SDRPlayV3.yaml new file mode 100644 index 000000000..3c6b958e5 --- /dev/null +++ b/swagger/sdrangel/api/swagger/include/SDRPlayV3.yaml @@ -0,0 +1,61 @@ +SDRPlayV3Settings: + description: SDRplayV3 + properties: + centerFrequency: + type: integer + format: int64 + LOppmTenths: + type: integer + ifFrequencyIndex: + type: integer + bandwidthIndex: + type: integer + devSampleRate: + type: integer + log2Decim: + type: integer + fcPos: + type: integer + dcBlock: + type: integer + iqCorrection: + type: integer + lnaIndex: + type: integer + ifAGC: + type: integer + ifGain: + type: integer + amNotch: + type: integer + fmNotch: + type: integer + dabNotch: + type: integer + extRef: + type: integer + tuner: + type: integer + antenna: + type: integer + useReverseAPI: + description: Synchronize with reverse API (1 for yes, 0 for no) + type: integer + reverseAPIAddress: + type: string + reverseAPIPort: + type: integer + reverseAPIDeviceIndex: + type: integer + +SDRPlayV3Report: + description: SDRplayV3 + properties: + bandwidths: + type: array + items: + $ref: "http://swgserver:8081/api/swagger/include/Structs.yaml#/Bandwidth" + intermediateFrequencies: + type: array + items: + $ref: "http://swgserver:8081/api/swagger/include/Structs.yaml#/Frequency" diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 635abc699..264d20a8e 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -3358,19 +3358,35 @@ margin-bottom: 20px; }, "standard" : { "type" : "integer", - "description" : "see DATVDemodSettings::dvb_version" + "description" : "DVB bersion (see DATVDemodSettings::dvb_version)\n * 0 - DVB-S\n * 1 - DVB-S2\n" }, "modulation" : { "type" : "integer", - "description" : "see DATVDemodSettings::DATVModulation" + "description" : "Modulation type (DATVDemodSettings::DATVModulation)\n * 0 - BPSK\n * 1 - QPSK\n * 2 - PSK8\n * 3 - APSK16\n * 4 - APSK32\n * 5 - APSK64E\n * 6 - QAM16\n * 7 - QAM64\n * 8 - QAM256\n" }, "fec" : { "type" : "integer", - "description" : "see DATVDemodSettings::DATVCodeRate" + "description" : "FEC rate (see DATVDemodSettings::DATVCodeRate)\n * 0 - 1/2\n * 1 - 2/3\n * 2 - 4/6\n * 3 - 3/4\n * 4 - 4/6\n * 5 - 7/8\n * 6 - 4/5\n * 7 - 8/9\n * 8 - 9/10\n * 9 - 1/4\n * 10 - 1/3\n * 11 - 2/5\n * 12 - 3/5\n" + }, + "softLDPC" : { + "type" : "integer", + "description" : "(boolean) engage sodt LDPC with LDPC tool sub processes (Linux only)" + }, + "softLDPCToolPath" : { + "type" : "string", + "description" : "O/S path to the LDPC tool binary" + }, + "softLDPCMaxTrials" : { + "type" : "integer", + "description" : "maximum number of trials in the soft LDPC algorithm (LDPC tool parameter)" + }, + "maxBitflips" : { + "type" : "integer", + "description" : "maximum number of bit flips allowed in hard LDPC algorithm" }, "audioMute" : { "type" : "integer", - "description" : "boolean" + "description" : "(boolean) mute audio output" }, "audioDeviceName" : { "type" : "string" @@ -3383,30 +3399,32 @@ margin-bottom: 20px; }, "allowDrift" : { "type" : "integer", - "description" : "boolean" + "description" : "(boolean) allow a larger frequency drift (DVB-S)" }, "fastLock" : { "type" : "integer", - "description" : "boolean" + "description" : "(boolean) faster locking algorithm (DVB-S)" }, "filter" : { "type" : "integer", - "description" : "see DATVDemodSettings::dvb_sampler" + "description" : "Type of sumbol filtering (see DATVDemodSettings::dvb_sampler)\n * 0 - Nearest\n * 1 - Linear\n * 2 - Root Raised Cosine\n" }, "hardMetric" : { "type" : "integer", - "description" : "boolean" + "description" : "(boolean) (DVB-S)" }, "rollOff" : { "type" : "number", - "format" : "float" + "format" : "float", + "description" : "RRC filter roll-off factor (0..1)" }, "viterbi" : { "type" : "integer", - "description" : "boolean" + "description" : "(boolean) (DVB-S)" }, "excursion" : { - "type" : "integer" + "type" : "integer", + "description" : "RRC filter envelope excursion (dB)" }, "audioVolume" : { "type" : "integer" @@ -3424,6 +3442,26 @@ margin-bottom: 20px; "udpTS" : { "type" : "integer", "description" : "boolean" + }, + "streamIndex" : { + "type" : "integer", + "description" : "MIMO channel. Not relevant when connected to SI (single Rx)." + }, + "useReverseAPI" : { + "type" : "integer", + "description" : "Synchronize with reverse API (1 for yes, 0 for no)" + }, + "reverseAPIAddress" : { + "type" : "string" + }, + "reverseAPIPort" : { + "type" : "integer" + }, + "reverseAPIDeviceIndex" : { + "type" : "integer" + }, + "reverseAPIChannelIndex" : { + "type" : "integer" } }, "description" : "DATVDemod" @@ -3892,6 +3930,9 @@ margin-bottom: 20px; "sdrPlayReport" : { "$ref" : "#/definitions/SDRPlayReport" }, + "sdrPlayV3Report" : { + "$ref" : "#/definitions/SDRPlayV3Report" + }, "sigMFFileInputReport" : { "$ref" : "#/definitions/SigMFFileInputReport" }, @@ -4059,6 +4100,9 @@ margin-bottom: 20px; "sdrPlaySettings" : { "$ref" : "#/definitions/SDRPlaySettings" }, + "sdrPlayV3Settings" : { + "$ref" : "#/definitions/SDRPlayV3Settings" + }, "sigMFFileInputSettings" : { "$ref" : "#/definitions/SigMFFileInputSettings" }, @@ -8542,6 +8586,96 @@ margin-bottom: 20px; } }, "description" : "SDRplay1" +}; + defs.SDRPlayV3Report = { + "properties" : { + "bandwidths" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/Bandwidth" + } + }, + "intermediateFrequencies" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/Frequency" + } + } + }, + "description" : "SDRplayV3" +}; + defs.SDRPlayV3Settings = { + "properties" : { + "centerFrequency" : { + "type" : "integer", + "format" : "int64" + }, + "LOppmTenths" : { + "type" : "integer" + }, + "ifFrequencyIndex" : { + "type" : "integer" + }, + "bandwidthIndex" : { + "type" : "integer" + }, + "devSampleRate" : { + "type" : "integer" + }, + "log2Decim" : { + "type" : "integer" + }, + "fcPos" : { + "type" : "integer" + }, + "dcBlock" : { + "type" : "integer" + }, + "iqCorrection" : { + "type" : "integer" + }, + "lnaIndex" : { + "type" : "integer" + }, + "ifAGC" : { + "type" : "integer" + }, + "ifGain" : { + "type" : "integer" + }, + "amNotch" : { + "type" : "integer" + }, + "fmNotch" : { + "type" : "integer" + }, + "dabNotch" : { + "type" : "integer" + }, + "extRef" : { + "type" : "integer" + }, + "tuner" : { + "type" : "integer" + }, + "antenna" : { + "type" : "integer" + }, + "useReverseAPI" : { + "type" : "integer", + "description" : "Synchronize with reverse API (1 for yes, 0 for no)" + }, + "reverseAPIAddress" : { + "type" : "string" + }, + "reverseAPIPort" : { + "type" : "integer" + }, + "reverseAPIDeviceIndex" : { + "type" : "integer" + } + }, + "description" : "SDRplayV3" }; defs.SSBDemodReport = { "properties" : { @@ -45892,7 +46026,7 @@ except ApiException as e:
- Generated 2021-04-02T23:43:06.310+02:00 + Generated 2021-04-11T22:11:18.598+02:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp index f77234449..56b2a23b0 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.cpp @@ -70,6 +70,8 @@ SWGDeviceReport::SWGDeviceReport() { m_remote_input_report_isSet = false; sdr_play_report = nullptr; m_sdr_play_report_isSet = false; + sdr_play_v3_report = nullptr; + m_sdr_play_v3_report_isSet = false; sig_mf_file_input_report = nullptr; m_sig_mf_file_input_report_isSet = false; soapy_sdr_input_report = nullptr; @@ -136,6 +138,8 @@ SWGDeviceReport::init() { m_remote_input_report_isSet = false; sdr_play_report = new SWGSDRPlayReport(); m_sdr_play_report_isSet = false; + sdr_play_v3_report = new SWGSDRPlayV3Report(); + m_sdr_play_v3_report_isSet = false; sig_mf_file_input_report = new SWGSigMFFileInputReport(); m_sig_mf_file_input_report_isSet = false; soapy_sdr_input_report = new SWGSoapySDRReport(); @@ -217,6 +221,9 @@ SWGDeviceReport::cleanup() { if(sdr_play_report != nullptr) { delete sdr_play_report; } + if(sdr_play_v3_report != nullptr) { + delete sdr_play_v3_report; + } if(sig_mf_file_input_report != nullptr) { delete sig_mf_file_input_report; } @@ -296,6 +303,8 @@ SWGDeviceReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&sdr_play_report, pJson["sdrPlayReport"], "SWGSDRPlayReport", "SWGSDRPlayReport"); + ::SWGSDRangel::setValue(&sdr_play_v3_report, pJson["sdrPlayV3Report"], "SWGSDRPlayV3Report", "SWGSDRPlayV3Report"); + ::SWGSDRangel::setValue(&sig_mf_file_input_report, pJson["sigMFFileInputReport"], "SWGSigMFFileInputReport", "SWGSigMFFileInputReport"); ::SWGSDRangel::setValue(&soapy_sdr_input_report, pJson["soapySDRInputReport"], "SWGSoapySDRReport", "SWGSoapySDRReport"); @@ -391,6 +400,9 @@ SWGDeviceReport::asJsonObject() { if((sdr_play_report != nullptr) && (sdr_play_report->isSet())){ toJsonValue(QString("sdrPlayReport"), sdr_play_report, obj, QString("SWGSDRPlayReport")); } + if((sdr_play_v3_report != nullptr) && (sdr_play_v3_report->isSet())){ + toJsonValue(QString("sdrPlayV3Report"), sdr_play_v3_report, obj, QString("SWGSDRPlayV3Report")); + } if((sig_mf_file_input_report != nullptr) && (sig_mf_file_input_report->isSet())){ toJsonValue(QString("sigMFFileInputReport"), sig_mf_file_input_report, obj, QString("SWGSigMFFileInputReport")); } @@ -629,6 +641,16 @@ SWGDeviceReport::setSdrPlayReport(SWGSDRPlayReport* sdr_play_report) { this->m_sdr_play_report_isSet = true; } +SWGSDRPlayV3Report* +SWGDeviceReport::getSdrPlayV3Report() { + return sdr_play_v3_report; +} +void +SWGDeviceReport::setSdrPlayV3Report(SWGSDRPlayV3Report* sdr_play_v3_report) { + this->sdr_play_v3_report = sdr_play_v3_report; + this->m_sdr_play_v3_report_isSet = true; +} + SWGSigMFFileInputReport* SWGDeviceReport::getSigMfFileInputReport() { return sig_mf_file_input_report; @@ -777,6 +799,9 @@ SWGDeviceReport::isSet(){ if(sdr_play_report && sdr_play_report->isSet()){ isObjectUpdated = true; break; } + if(sdr_play_v3_report && sdr_play_v3_report->isSet()){ + isObjectUpdated = true; break; + } if(sig_mf_file_input_report && sig_mf_file_input_report->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h index fe081a3b4..363210779 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceReport.h @@ -41,6 +41,7 @@ #include "SWGRemoteOutputReport.h" #include "SWGRtlSdrReport.h" #include "SWGSDRPlayReport.h" +#include "SWGSDRPlayV3Report.h" #include "SWGSigMFFileInputReport.h" #include "SWGSoapySDRReport.h" #include "SWGUSRPInputReport.h" @@ -131,6 +132,9 @@ public: SWGSDRPlayReport* getSdrPlayReport(); void setSdrPlayReport(SWGSDRPlayReport* sdr_play_report); + SWGSDRPlayV3Report* getSdrPlayV3Report(); + void setSdrPlayV3Report(SWGSDRPlayV3Report* sdr_play_v3_report); + SWGSigMFFileInputReport* getSigMfFileInputReport(); void setSigMfFileInputReport(SWGSigMFFileInputReport* sig_mf_file_input_report); @@ -222,6 +226,9 @@ private: SWGSDRPlayReport* sdr_play_report; bool m_sdr_play_report_isSet; + SWGSDRPlayV3Report* sdr_play_v3_report; + bool m_sdr_play_v3_report_isSet; + SWGSigMFFileInputReport* sig_mf_file_input_report; bool m_sig_mf_file_input_report_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp index a9d12fc7e..283cf9b4d 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.cpp @@ -90,6 +90,8 @@ SWGDeviceSettings::SWGDeviceSettings() { m_remote_input_settings_isSet = false; sdr_play_settings = nullptr; m_sdr_play_settings_isSet = false; + sdr_play_v3_settings = nullptr; + m_sdr_play_v3_settings_isSet = false; sig_mf_file_input_settings = nullptr; m_sig_mf_file_input_settings_isSet = false; soapy_sdr_input_settings = nullptr; @@ -182,6 +184,8 @@ SWGDeviceSettings::init() { m_remote_input_settings_isSet = false; sdr_play_settings = new SWGSDRPlaySettings(); m_sdr_play_settings_isSet = false; + sdr_play_v3_settings = new SWGSDRPlayV3Settings(); + m_sdr_play_v3_settings_isSet = false; sig_mf_file_input_settings = new SWGSigMFFileInputSettings(); m_sig_mf_file_input_settings_isSet = false; soapy_sdr_input_settings = new SWGSoapySDRInputSettings(); @@ -297,6 +301,9 @@ SWGDeviceSettings::cleanup() { if(sdr_play_settings != nullptr) { delete sdr_play_settings; } + if(sdr_play_v3_settings != nullptr) { + delete sdr_play_v3_settings; + } if(sig_mf_file_input_settings != nullptr) { delete sig_mf_file_input_settings; } @@ -405,6 +412,8 @@ SWGDeviceSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&sdr_play_settings, pJson["sdrPlaySettings"], "SWGSDRPlaySettings", "SWGSDRPlaySettings"); + ::SWGSDRangel::setValue(&sdr_play_v3_settings, pJson["sdrPlayV3Settings"], "SWGSDRPlayV3Settings", "SWGSDRPlayV3Settings"); + ::SWGSDRangel::setValue(&sig_mf_file_input_settings, pJson["sigMFFileInputSettings"], "SWGSigMFFileInputSettings", "SWGSigMFFileInputSettings"); ::SWGSDRangel::setValue(&soapy_sdr_input_settings, pJson["soapySDRInputSettings"], "SWGSoapySDRInputSettings", "SWGSoapySDRInputSettings"); @@ -536,6 +545,9 @@ SWGDeviceSettings::asJsonObject() { if((sdr_play_settings != nullptr) && (sdr_play_settings->isSet())){ toJsonValue(QString("sdrPlaySettings"), sdr_play_settings, obj, QString("SWGSDRPlaySettings")); } + if((sdr_play_v3_settings != nullptr) && (sdr_play_v3_settings->isSet())){ + toJsonValue(QString("sdrPlayV3Settings"), sdr_play_v3_settings, obj, QString("SWGSDRPlayV3Settings")); + } if((sig_mf_file_input_settings != nullptr) && (sig_mf_file_input_settings->isSet())){ toJsonValue(QString("sigMFFileInputSettings"), sig_mf_file_input_settings, obj, QString("SWGSigMFFileInputSettings")); } @@ -883,6 +895,16 @@ SWGDeviceSettings::setSdrPlaySettings(SWGSDRPlaySettings* sdr_play_settings) { this->m_sdr_play_settings_isSet = true; } +SWGSDRPlayV3Settings* +SWGDeviceSettings::getSdrPlayV3Settings() { + return sdr_play_v3_settings; +} +void +SWGDeviceSettings::setSdrPlayV3Settings(SWGSDRPlayV3Settings* sdr_play_v3_settings) { + this->sdr_play_v3_settings = sdr_play_v3_settings; + this->m_sdr_play_v3_settings_isSet = true; +} + SWGSigMFFileInputSettings* SWGDeviceSettings::getSigMfFileInputSettings() { return sig_mf_file_input_settings; @@ -1091,6 +1113,9 @@ SWGDeviceSettings::isSet(){ if(sdr_play_settings && sdr_play_settings->isSet()){ isObjectUpdated = true; break; } + if(sdr_play_v3_settings && sdr_play_v3_settings->isSet()){ + isObjectUpdated = true; break; + } if(sig_mf_file_input_settings && sig_mf_file_input_settings->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h index ef74f5bc6..e7f01b239 100644 --- a/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGDeviceSettings.h @@ -50,6 +50,7 @@ #include "SWGRemoteOutputSettings.h" #include "SWGRtlSdrSettings.h" #include "SWGSDRPlaySettings.h" +#include "SWGSDRPlayV3Settings.h" #include "SWGSigMFFileInputSettings.h" #include "SWGSoapySDRInputSettings.h" #include "SWGSoapySDROutputSettings.h" @@ -174,6 +175,9 @@ public: SWGSDRPlaySettings* getSdrPlaySettings(); void setSdrPlaySettings(SWGSDRPlaySettings* sdr_play_settings); + SWGSDRPlayV3Settings* getSdrPlayV3Settings(); + void setSdrPlayV3Settings(SWGSDRPlayV3Settings* sdr_play_v3_settings); + SWGSigMFFileInputSettings* getSigMfFileInputSettings(); void setSigMfFileInputSettings(SWGSigMFFileInputSettings* sig_mf_file_input_settings); @@ -304,6 +308,9 @@ private: SWGSDRPlaySettings* sdr_play_settings; bool m_sdr_play_settings_isSet; + SWGSDRPlayV3Settings* sdr_play_v3_settings; + bool m_sdr_play_v3_settings_isSet; + SWGSigMFFileInputSettings* sig_mf_file_input_settings; bool m_sig_mf_file_input_settings_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h index c2c54478e..3548dd07b 100644 --- a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h +++ b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h @@ -201,6 +201,8 @@ #include "SWGRtlSdrSettings.h" #include "SWGSDRPlayReport.h" #include "SWGSDRPlaySettings.h" +#include "SWGSDRPlayV3Report.h" +#include "SWGSDRPlayV3Settings.h" #include "SWGSSBDemodReport.h" #include "SWGSSBDemodSettings.h" #include "SWGSSBModReport.h" @@ -821,6 +823,12 @@ namespace SWGSDRangel { if(QString("SWGSDRPlaySettings").compare(type) == 0) { return new SWGSDRPlaySettings(); } + if(QString("SWGSDRPlayV3Report").compare(type) == 0) { + return new SWGSDRPlayV3Report(); + } + if(QString("SWGSDRPlayV3Settings").compare(type) == 0) { + return new SWGSDRPlayV3Settings(); + } if(QString("SWGSSBDemodReport").compare(type) == 0) { return new SWGSSBDemodReport(); } diff --git a/swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Report.cpp b/swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Report.cpp new file mode 100644 index 000000000..21b71a07a --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Report.cpp @@ -0,0 +1,143 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGSDRPlayV3Report.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGSDRPlayV3Report::SWGSDRPlayV3Report(QString* json) { + init(); + this->fromJson(*json); +} + +SWGSDRPlayV3Report::SWGSDRPlayV3Report() { + bandwidths = nullptr; + m_bandwidths_isSet = false; + intermediate_frequencies = nullptr; + m_intermediate_frequencies_isSet = false; +} + +SWGSDRPlayV3Report::~SWGSDRPlayV3Report() { + this->cleanup(); +} + +void +SWGSDRPlayV3Report::init() { + bandwidths = new QList(); + m_bandwidths_isSet = false; + intermediate_frequencies = new QList(); + m_intermediate_frequencies_isSet = false; +} + +void +SWGSDRPlayV3Report::cleanup() { + if(bandwidths != nullptr) { + auto arr = bandwidths; + for(auto o: *arr) { + delete o; + } + delete bandwidths; + } + if(intermediate_frequencies != nullptr) { + auto arr = intermediate_frequencies; + for(auto o: *arr) { + delete o; + } + delete intermediate_frequencies; + } +} + +SWGSDRPlayV3Report* +SWGSDRPlayV3Report::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGSDRPlayV3Report::fromJsonObject(QJsonObject &pJson) { + + ::SWGSDRangel::setValue(&bandwidths, pJson["bandwidths"], "QList", "SWGBandwidth"); + + ::SWGSDRangel::setValue(&intermediate_frequencies, pJson["intermediateFrequencies"], "QList", "SWGFrequency"); +} + +QString +SWGSDRPlayV3Report::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGSDRPlayV3Report::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(bandwidths && bandwidths->size() > 0){ + toJsonArray((QList*)bandwidths, obj, "bandwidths", "SWGBandwidth"); + } + if(intermediate_frequencies && intermediate_frequencies->size() > 0){ + toJsonArray((QList*)intermediate_frequencies, obj, "intermediateFrequencies", "SWGFrequency"); + } + + return obj; +} + +QList* +SWGSDRPlayV3Report::getBandwidths() { + return bandwidths; +} +void +SWGSDRPlayV3Report::setBandwidths(QList* bandwidths) { + this->bandwidths = bandwidths; + this->m_bandwidths_isSet = true; +} + +QList* +SWGSDRPlayV3Report::getIntermediateFrequencies() { + return intermediate_frequencies; +} +void +SWGSDRPlayV3Report::setIntermediateFrequencies(QList* intermediate_frequencies) { + this->intermediate_frequencies = intermediate_frequencies; + this->m_intermediate_frequencies_isSet = true; +} + + +bool +SWGSDRPlayV3Report::isSet(){ + bool isObjectUpdated = false; + do{ + if(bandwidths && (bandwidths->size() > 0)){ + isObjectUpdated = true; break; + } + if(intermediate_frequencies && (intermediate_frequencies->size() > 0)){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Report.h b/swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Report.h new file mode 100644 index 000000000..1f78abd9d --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Report.h @@ -0,0 +1,67 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGSDRPlayV3Report.h + * + * SDRplayV3 + */ + +#ifndef SWGSDRPlayV3Report_H_ +#define SWGSDRPlayV3Report_H_ + +#include + + +#include "SWGBandwidth.h" +#include "SWGFrequency.h" +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGSDRPlayV3Report: public SWGObject { +public: + SWGSDRPlayV3Report(); + SWGSDRPlayV3Report(QString* json); + virtual ~SWGSDRPlayV3Report(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGSDRPlayV3Report* fromJson(QString &jsonString) override; + + QList* getBandwidths(); + void setBandwidths(QList* bandwidths); + + QList* getIntermediateFrequencies(); + void setIntermediateFrequencies(QList* intermediate_frequencies); + + + virtual bool isSet() override; + +private: + QList* bandwidths; + bool m_bandwidths_isSet; + + QList* intermediate_frequencies; + bool m_intermediate_frequencies_isSet; + +}; + +} + +#endif /* SWGSDRPlayV3Report_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Settings.cpp b/swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Settings.cpp new file mode 100644 index 000000000..777ae2e44 --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Settings.cpp @@ -0,0 +1,593 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGSDRPlayV3Settings.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGSDRPlayV3Settings::SWGSDRPlayV3Settings(QString* json) { + init(); + this->fromJson(*json); +} + +SWGSDRPlayV3Settings::SWGSDRPlayV3Settings() { + center_frequency = 0L; + m_center_frequency_isSet = false; + l_oppm_tenths = 0; + m_l_oppm_tenths_isSet = false; + if_frequency_index = 0; + m_if_frequency_index_isSet = false; + bandwidth_index = 0; + m_bandwidth_index_isSet = false; + dev_sample_rate = 0; + m_dev_sample_rate_isSet = false; + log2_decim = 0; + m_log2_decim_isSet = false; + fc_pos = 0; + m_fc_pos_isSet = false; + dc_block = 0; + m_dc_block_isSet = false; + iq_correction = 0; + m_iq_correction_isSet = false; + lna_index = 0; + m_lna_index_isSet = false; + if_agc = 0; + m_if_agc_isSet = false; + if_gain = 0; + m_if_gain_isSet = false; + am_notch = 0; + m_am_notch_isSet = false; + fm_notch = 0; + m_fm_notch_isSet = false; + dab_notch = 0; + m_dab_notch_isSet = false; + ext_ref = 0; + m_ext_ref_isSet = false; + tuner = 0; + m_tuner_isSet = false; + antenna = 0; + m_antenna_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; +} + +SWGSDRPlayV3Settings::~SWGSDRPlayV3Settings() { + this->cleanup(); +} + +void +SWGSDRPlayV3Settings::init() { + center_frequency = 0L; + m_center_frequency_isSet = false; + l_oppm_tenths = 0; + m_l_oppm_tenths_isSet = false; + if_frequency_index = 0; + m_if_frequency_index_isSet = false; + bandwidth_index = 0; + m_bandwidth_index_isSet = false; + dev_sample_rate = 0; + m_dev_sample_rate_isSet = false; + log2_decim = 0; + m_log2_decim_isSet = false; + fc_pos = 0; + m_fc_pos_isSet = false; + dc_block = 0; + m_dc_block_isSet = false; + iq_correction = 0; + m_iq_correction_isSet = false; + lna_index = 0; + m_lna_index_isSet = false; + if_agc = 0; + m_if_agc_isSet = false; + if_gain = 0; + m_if_gain_isSet = false; + am_notch = 0; + m_am_notch_isSet = false; + fm_notch = 0; + m_fm_notch_isSet = false; + dab_notch = 0; + m_dab_notch_isSet = false; + ext_ref = 0; + m_ext_ref_isSet = false; + tuner = 0; + m_tuner_isSet = false; + antenna = 0; + m_antenna_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 +SWGSDRPlayV3Settings::cleanup() { + + + + + + + + + + + + + + + + + + + + if(reverse_api_address != nullptr) { + delete reverse_api_address; + } + + +} + +SWGSDRPlayV3Settings* +SWGSDRPlayV3Settings::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGSDRPlayV3Settings::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(¢er_frequency, pJson["centerFrequency"], "qint64", ""); + + ::SWGSDRangel::setValue(&l_oppm_tenths, pJson["LOppmTenths"], "qint32", ""); + + ::SWGSDRangel::setValue(&if_frequency_index, pJson["ifFrequencyIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&bandwidth_index, pJson["bandwidthIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&dev_sample_rate, pJson["devSampleRate"], "qint32", ""); + + ::SWGSDRangel::setValue(&log2_decim, pJson["log2Decim"], "qint32", ""); + + ::SWGSDRangel::setValue(&fc_pos, pJson["fcPos"], "qint32", ""); + + ::SWGSDRangel::setValue(&dc_block, pJson["dcBlock"], "qint32", ""); + + ::SWGSDRangel::setValue(&iq_correction, pJson["iqCorrection"], "qint32", ""); + + ::SWGSDRangel::setValue(&lna_index, pJson["lnaIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&if_agc, pJson["ifAGC"], "qint32", ""); + + ::SWGSDRangel::setValue(&if_gain, pJson["ifGain"], "qint32", ""); + + ::SWGSDRangel::setValue(&am_notch, pJson["amNotch"], "qint32", ""); + + ::SWGSDRangel::setValue(&fm_notch, pJson["fmNotch"], "qint32", ""); + + ::SWGSDRangel::setValue(&dab_notch, pJson["dabNotch"], "qint32", ""); + + ::SWGSDRangel::setValue(&ext_ref, pJson["extRef"], "qint32", ""); + + ::SWGSDRangel::setValue(&tuner, pJson["tuner"], "qint32", ""); + + ::SWGSDRangel::setValue(&antenna, pJson["antenna"], "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 +SWGSDRPlayV3Settings::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGSDRPlayV3Settings::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_center_frequency_isSet){ + obj->insert("centerFrequency", QJsonValue(center_frequency)); + } + if(m_l_oppm_tenths_isSet){ + obj->insert("LOppmTenths", QJsonValue(l_oppm_tenths)); + } + if(m_if_frequency_index_isSet){ + obj->insert("ifFrequencyIndex", QJsonValue(if_frequency_index)); + } + if(m_bandwidth_index_isSet){ + obj->insert("bandwidthIndex", QJsonValue(bandwidth_index)); + } + if(m_dev_sample_rate_isSet){ + obj->insert("devSampleRate", QJsonValue(dev_sample_rate)); + } + if(m_log2_decim_isSet){ + obj->insert("log2Decim", QJsonValue(log2_decim)); + } + if(m_fc_pos_isSet){ + obj->insert("fcPos", QJsonValue(fc_pos)); + } + if(m_dc_block_isSet){ + obj->insert("dcBlock", QJsonValue(dc_block)); + } + if(m_iq_correction_isSet){ + obj->insert("iqCorrection", QJsonValue(iq_correction)); + } + if(m_lna_index_isSet){ + obj->insert("lnaIndex", QJsonValue(lna_index)); + } + if(m_if_agc_isSet){ + obj->insert("ifAGC", QJsonValue(if_agc)); + } + if(m_if_gain_isSet){ + obj->insert("ifGain", QJsonValue(if_gain)); + } + if(m_am_notch_isSet){ + obj->insert("amNotch", QJsonValue(am_notch)); + } + if(m_fm_notch_isSet){ + obj->insert("fmNotch", QJsonValue(fm_notch)); + } + if(m_dab_notch_isSet){ + obj->insert("dabNotch", QJsonValue(dab_notch)); + } + if(m_ext_ref_isSet){ + obj->insert("extRef", QJsonValue(ext_ref)); + } + if(m_tuner_isSet){ + obj->insert("tuner", QJsonValue(tuner)); + } + if(m_antenna_isSet){ + obj->insert("antenna", QJsonValue(antenna)); + } + 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 +SWGSDRPlayV3Settings::getCenterFrequency() { + return center_frequency; +} +void +SWGSDRPlayV3Settings::setCenterFrequency(qint64 center_frequency) { + this->center_frequency = center_frequency; + this->m_center_frequency_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getLOppmTenths() { + return l_oppm_tenths; +} +void +SWGSDRPlayV3Settings::setLOppmTenths(qint32 l_oppm_tenths) { + this->l_oppm_tenths = l_oppm_tenths; + this->m_l_oppm_tenths_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getIfFrequencyIndex() { + return if_frequency_index; +} +void +SWGSDRPlayV3Settings::setIfFrequencyIndex(qint32 if_frequency_index) { + this->if_frequency_index = if_frequency_index; + this->m_if_frequency_index_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getBandwidthIndex() { + return bandwidth_index; +} +void +SWGSDRPlayV3Settings::setBandwidthIndex(qint32 bandwidth_index) { + this->bandwidth_index = bandwidth_index; + this->m_bandwidth_index_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getDevSampleRate() { + return dev_sample_rate; +} +void +SWGSDRPlayV3Settings::setDevSampleRate(qint32 dev_sample_rate) { + this->dev_sample_rate = dev_sample_rate; + this->m_dev_sample_rate_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getLog2Decim() { + return log2_decim; +} +void +SWGSDRPlayV3Settings::setLog2Decim(qint32 log2_decim) { + this->log2_decim = log2_decim; + this->m_log2_decim_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getFcPos() { + return fc_pos; +} +void +SWGSDRPlayV3Settings::setFcPos(qint32 fc_pos) { + this->fc_pos = fc_pos; + this->m_fc_pos_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getDcBlock() { + return dc_block; +} +void +SWGSDRPlayV3Settings::setDcBlock(qint32 dc_block) { + this->dc_block = dc_block; + this->m_dc_block_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getIqCorrection() { + return iq_correction; +} +void +SWGSDRPlayV3Settings::setIqCorrection(qint32 iq_correction) { + this->iq_correction = iq_correction; + this->m_iq_correction_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getLnaIndex() { + return lna_index; +} +void +SWGSDRPlayV3Settings::setLnaIndex(qint32 lna_index) { + this->lna_index = lna_index; + this->m_lna_index_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getIfAgc() { + return if_agc; +} +void +SWGSDRPlayV3Settings::setIfAgc(qint32 if_agc) { + this->if_agc = if_agc; + this->m_if_agc_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getIfGain() { + return if_gain; +} +void +SWGSDRPlayV3Settings::setIfGain(qint32 if_gain) { + this->if_gain = if_gain; + this->m_if_gain_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getAmNotch() { + return am_notch; +} +void +SWGSDRPlayV3Settings::setAmNotch(qint32 am_notch) { + this->am_notch = am_notch; + this->m_am_notch_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getFmNotch() { + return fm_notch; +} +void +SWGSDRPlayV3Settings::setFmNotch(qint32 fm_notch) { + this->fm_notch = fm_notch; + this->m_fm_notch_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getDabNotch() { + return dab_notch; +} +void +SWGSDRPlayV3Settings::setDabNotch(qint32 dab_notch) { + this->dab_notch = dab_notch; + this->m_dab_notch_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getExtRef() { + return ext_ref; +} +void +SWGSDRPlayV3Settings::setExtRef(qint32 ext_ref) { + this->ext_ref = ext_ref; + this->m_ext_ref_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getTuner() { + return tuner; +} +void +SWGSDRPlayV3Settings::setTuner(qint32 tuner) { + this->tuner = tuner; + this->m_tuner_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getAntenna() { + return antenna; +} +void +SWGSDRPlayV3Settings::setAntenna(qint32 antenna) { + this->antenna = antenna; + this->m_antenna_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getUseReverseApi() { + return use_reverse_api; +} +void +SWGSDRPlayV3Settings::setUseReverseApi(qint32 use_reverse_api) { + this->use_reverse_api = use_reverse_api; + this->m_use_reverse_api_isSet = true; +} + +QString* +SWGSDRPlayV3Settings::getReverseApiAddress() { + return reverse_api_address; +} +void +SWGSDRPlayV3Settings::setReverseApiAddress(QString* reverse_api_address) { + this->reverse_api_address = reverse_api_address; + this->m_reverse_api_address_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getReverseApiPort() { + return reverse_api_port; +} +void +SWGSDRPlayV3Settings::setReverseApiPort(qint32 reverse_api_port) { + this->reverse_api_port = reverse_api_port; + this->m_reverse_api_port_isSet = true; +} + +qint32 +SWGSDRPlayV3Settings::getReverseApiDeviceIndex() { + return reverse_api_device_index; +} +void +SWGSDRPlayV3Settings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) { + this->reverse_api_device_index = reverse_api_device_index; + this->m_reverse_api_device_index_isSet = true; +} + + +bool +SWGSDRPlayV3Settings::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_center_frequency_isSet){ + isObjectUpdated = true; break; + } + if(m_l_oppm_tenths_isSet){ + isObjectUpdated = true; break; + } + if(m_if_frequency_index_isSet){ + isObjectUpdated = true; break; + } + if(m_bandwidth_index_isSet){ + isObjectUpdated = true; break; + } + if(m_dev_sample_rate_isSet){ + isObjectUpdated = true; break; + } + if(m_log2_decim_isSet){ + isObjectUpdated = true; break; + } + if(m_fc_pos_isSet){ + isObjectUpdated = true; break; + } + if(m_dc_block_isSet){ + isObjectUpdated = true; break; + } + if(m_iq_correction_isSet){ + isObjectUpdated = true; break; + } + if(m_lna_index_isSet){ + isObjectUpdated = true; break; + } + if(m_if_agc_isSet){ + isObjectUpdated = true; break; + } + if(m_if_gain_isSet){ + isObjectUpdated = true; break; + } + if(m_am_notch_isSet){ + isObjectUpdated = true; break; + } + if(m_fm_notch_isSet){ + isObjectUpdated = true; break; + } + if(m_dab_notch_isSet){ + isObjectUpdated = true; break; + } + if(m_ext_ref_isSet){ + isObjectUpdated = true; break; + } + if(m_tuner_isSet){ + isObjectUpdated = true; break; + } + if(m_antenna_isSet){ + isObjectUpdated = true; break; + } + if(m_use_reverse_api_isSet){ + isObjectUpdated = true; break; + } + if(reverse_api_address && *reverse_api_address != QString("")){ + isObjectUpdated = true; break; + } + if(m_reverse_api_port_isSet){ + isObjectUpdated = true; break; + } + if(m_reverse_api_device_index_isSet){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Settings.h b/swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Settings.h new file mode 100644 index 000000000..7426749de --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGSDRPlayV3Settings.h @@ -0,0 +1,185 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGSDRPlayV3Settings.h + * + * SDRplayV3 + */ + +#ifndef SWGSDRPlayV3Settings_H_ +#define SWGSDRPlayV3Settings_H_ + +#include + + +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGSDRPlayV3Settings: public SWGObject { +public: + SWGSDRPlayV3Settings(); + SWGSDRPlayV3Settings(QString* json); + virtual ~SWGSDRPlayV3Settings(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGSDRPlayV3Settings* fromJson(QString &jsonString) override; + + qint64 getCenterFrequency(); + void setCenterFrequency(qint64 center_frequency); + + qint32 getLOppmTenths(); + void setLOppmTenths(qint32 l_oppm_tenths); + + qint32 getIfFrequencyIndex(); + void setIfFrequencyIndex(qint32 if_frequency_index); + + qint32 getBandwidthIndex(); + void setBandwidthIndex(qint32 bandwidth_index); + + qint32 getDevSampleRate(); + void setDevSampleRate(qint32 dev_sample_rate); + + qint32 getLog2Decim(); + void setLog2Decim(qint32 log2_decim); + + qint32 getFcPos(); + void setFcPos(qint32 fc_pos); + + qint32 getDcBlock(); + void setDcBlock(qint32 dc_block); + + qint32 getIqCorrection(); + void setIqCorrection(qint32 iq_correction); + + qint32 getLnaIndex(); + void setLnaIndex(qint32 lna_index); + + qint32 getIfAgc(); + void setIfAgc(qint32 if_agc); + + qint32 getIfGain(); + void setIfGain(qint32 if_gain); + + qint32 getAmNotch(); + void setAmNotch(qint32 am_notch); + + qint32 getFmNotch(); + void setFmNotch(qint32 fm_notch); + + qint32 getDabNotch(); + void setDabNotch(qint32 dab_notch); + + qint32 getExtRef(); + void setExtRef(qint32 ext_ref); + + qint32 getTuner(); + void setTuner(qint32 tuner); + + qint32 getAntenna(); + void setAntenna(qint32 antenna); + + 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 l_oppm_tenths; + bool m_l_oppm_tenths_isSet; + + qint32 if_frequency_index; + bool m_if_frequency_index_isSet; + + qint32 bandwidth_index; + bool m_bandwidth_index_isSet; + + qint32 dev_sample_rate; + bool m_dev_sample_rate_isSet; + + qint32 log2_decim; + bool m_log2_decim_isSet; + + qint32 fc_pos; + bool m_fc_pos_isSet; + + qint32 dc_block; + bool m_dc_block_isSet; + + qint32 iq_correction; + bool m_iq_correction_isSet; + + qint32 lna_index; + bool m_lna_index_isSet; + + qint32 if_agc; + bool m_if_agc_isSet; + + qint32 if_gain; + bool m_if_gain_isSet; + + qint32 am_notch; + bool m_am_notch_isSet; + + qint32 fm_notch; + bool m_fm_notch_isSet; + + qint32 dab_notch; + bool m_dab_notch_isSet; + + qint32 ext_ref; + bool m_ext_ref_isSet; + + qint32 tuner; + bool m_tuner_isSet; + + qint32 antenna; + bool m_antenna_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 /* SWGSDRPlayV3Settings_H_ */