From b0d12fbb232a030859710c1afd0a2de6bfed608f Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 25 Dec 2018 21:05:24 +0100 Subject: [PATCH] Reverse API: Blade RF input changes --- .../bladerf1input/bladerf1input.cpp | 242 +++++++++++++----- .../bladerf1input/bladerf1input.h | 23 +- .../bladerf1input/bladerf1inputgui.cpp | 23 ++ .../bladerf1input/bladerf1inputgui.h | 1 + .../bladerf1input/bladerf1inputplugin.cpp | 2 +- .../bladerf1input/bladerf1inputsettings.cpp | 21 ++ .../bladerf1input/bladerf1inputsettings.h | 4 + .../bladerf2input/bladerf2input.cpp | 161 ++++++++++++ .../bladerf2input/bladerf2input.h | 17 +- .../bladerf2input/bladerf2inputgui.cpp | 24 ++ .../bladerf2input/bladerf2inputgui.h | 1 + .../bladerf2input/bladerf2inputplugin.cpp | 2 +- .../bladerf2input/bladerf2inputsettings.cpp | 21 ++ .../bladerf2input/bladerf2inputsettings.h | 4 + 14 files changed, 467 insertions(+), 79 deletions(-) diff --git a/plugins/samplesource/bladerf1input/bladerf1input.cpp b/plugins/samplesource/bladerf1input/bladerf1input.cpp index f21349624..11bd0392b 100644 --- a/plugins/samplesource/bladerf1input/bladerf1input.cpp +++ b/plugins/samplesource/bladerf1input/bladerf1input.cpp @@ -14,11 +14,12 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include "bladerf1input.h" - #include #include + #include +#include +#include #include "SWGDeviceSettings.h" #include "SWGDeviceState.h" @@ -30,6 +31,7 @@ #include "device/devicesourceapi.h" #include "device/devicesinkapi.h" +#include "bladerf1input.h" #include "bladerf1inputthread.h" MESSAGE_CLASS_DEFINITION(Bladerf1Input::MsgConfigureBladerf1, Message) @@ -49,11 +51,20 @@ Bladerf1Input::Bladerf1Input(DeviceSourceAPI *deviceAPI) : m_deviceAPI->addSink(m_fileSink); m_deviceAPI->setBuddySharedPtr(&m_sharedParams); + + m_networkManager = new QNetworkAccessManager(); + connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); } Bladerf1Input::~Bladerf1Input() { - if (m_running) stop(); + disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); + delete m_networkManager; + + if (m_running) { + stop(); + } + m_deviceAPI->removeSink(m_fileSink); delete m_fileSink; closeDevice(); @@ -311,6 +322,10 @@ bool Bladerf1Input::handleMessage(const Message& message) m_deviceAPI->stopAcquisition(); } + if (m_settings.m_useReverseAPI) { + webapiReverseSendStartStop(cmd.getStartStop()); + } + return true; } else @@ -322,30 +337,33 @@ bool Bladerf1Input::handleMessage(const Message& message) bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool force) { bool forwardChange = false; + QList reverseAPIKeys; // QMutexLocker mutexLocker(&m_mutex); qDebug() << "BladerfInput::applySettings: m_dev: " << m_dev; + if ((m_settings.m_dcBlock != settings.m_dcBlock) || force) { + reverseAPIKeys.append("dcBlock"); + } + if ((m_settings.m_iqCorrection != settings.m_iqCorrection) || force) { + reverseAPIKeys.append("iqCorrection"); + } + if ((m_settings.m_dcBlock != settings.m_dcBlock) || (m_settings.m_iqCorrection != settings.m_iqCorrection) || force) { -// m_settings.m_dcBlock = settings.m_dcBlock; -// m_settings.m_iqCorrection = settings.m_iqCorrection; m_deviceAPI->configureCorrections(settings.m_dcBlock, settings.m_iqCorrection); } if ((m_settings.m_lnaGain != settings.m_lnaGain) || force) { -// m_settings.m_lnaGain = settings.m_lnaGain; + reverseAPIKeys.append("lnaGain"); if (m_dev != 0) { - if(bladerf_set_lna_gain(m_dev, getLnaGain(settings.m_lnaGain)) != 0) - { + if(bladerf_set_lna_gain(m_dev, getLnaGain(settings.m_lnaGain)) != 0) { qDebug("BladerfInput::applySettings: bladerf_set_lna_gain() failed"); - } - else - { + } else { qDebug() << "BladerfInput::applySettings: LNA gain set to " << getLnaGain(settings.m_lnaGain); } } @@ -353,16 +371,13 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool fo if ((m_settings.m_vga1 != settings.m_vga1) || force) { -// m_settings.m_vga1 = settings.m_vga1; + reverseAPIKeys.append("vga1"); if (m_dev != 0) { - if(bladerf_set_rxvga1(m_dev, settings.m_vga1) != 0) - { + if(bladerf_set_rxvga1(m_dev, settings.m_vga1) != 0) { qDebug("BladerfInput::applySettings: bladerf_set_rxvga1() failed"); - } - else - { + } else { qDebug() << "BladerfInput::applySettings: VGA1 gain set to " << settings.m_vga1; } } @@ -370,16 +385,13 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool fo if ((m_settings.m_vga2 != settings.m_vga2) || force) { -// m_settings.m_vga2 = settings.m_vga2; + reverseAPIKeys.append("vga2"); if(m_dev != 0) { - if(bladerf_set_rxvga2(m_dev, settings.m_vga2) != 0) - { + if(bladerf_set_rxvga2(m_dev, settings.m_vga2) != 0) { qDebug("BladerfInput::applySettings: bladerf_set_rxvga2() failed"); - } - else - { + } else { qDebug() << "BladerfInput::applySettings: VGA2 gain set to " << settings.m_vga2; } } @@ -387,7 +399,7 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool fo if ((m_settings.m_xb200 != settings.m_xb200) || force) { -// m_settings.m_xb200 = settings.m_xb200; + reverseAPIKeys.append("xb200"); if (m_dev != 0) { @@ -397,12 +409,9 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool fo { DeviceSinkAPI *buddy = m_deviceAPI->getSinkBuddies()[0]; - if (buddy->getDeviceSinkEngine()->state() == DSPDeviceSinkEngine::StRunning) // Tx side running - { + if (buddy->getDeviceSinkEngine()->state() == DSPDeviceSinkEngine::StRunning) { // Tx side running changeSettings = false; - } - else - { + } else { changeSettings = true; } } @@ -415,23 +424,17 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool fo { if (settings.m_xb200) { - if (bladerf_expansion_attach(m_dev, BLADERF_XB_200) != 0) - { + if (bladerf_expansion_attach(m_dev, BLADERF_XB_200) != 0) { qDebug("BladerfInput::applySettings: bladerf_expansion_attach(xb200) failed"); - } - else - { + } else { qDebug() << "BladerfInput::applySettings: Attach XB200"; } } else { - if (bladerf_expansion_attach(m_dev, BLADERF_XB_NONE) != 0) - { + if (bladerf_expansion_attach(m_dev, BLADERF_XB_NONE) != 0) { qDebug("BladerfInput::applySettings: bladerf_expansion_attach(none) failed"); - } - else - { + } else { qDebug() << "BladerfInput::applySettings: Detach XB200"; } } @@ -443,16 +446,13 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool fo if ((m_settings.m_xb200Path != settings.m_xb200Path) || force) { -// m_settings.m_xb200Path = settings.m_xb200Path; + reverseAPIKeys.append("xb200Path"); if (m_dev != 0) { - if(bladerf_xb200_set_path(m_dev, BLADERF_MODULE_RX, settings.m_xb200Path) != 0) - { + if(bladerf_xb200_set_path(m_dev, BLADERF_MODULE_RX, settings.m_xb200Path) != 0) { qDebug("BladerfInput::applySettings: bladerf_xb200_set_path(BLADERF_MODULE_RX) failed"); - } - else - { + } else { qDebug() << "BladerfInput::applySettings: set xb200 path to " << settings.m_xb200Path; } } @@ -460,16 +460,13 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool fo if ((m_settings.m_xb200Filter != settings.m_xb200Filter) || force) { -// m_settings.m_xb200Filter = settings.m_xb200Filter; + reverseAPIKeys.append("xb200Filter"); if (m_dev != 0) { - if(bladerf_xb200_set_filterbank(m_dev, BLADERF_MODULE_RX, settings.m_xb200Filter) != 0) - { + if(bladerf_xb200_set_filterbank(m_dev, BLADERF_MODULE_RX, settings.m_xb200Filter) != 0) { qDebug("BladerfInput::applySettings: bladerf_xb200_set_filterbank(BLADERF_MODULE_RX) failed"); - } - else - { + } else { qDebug() << "BladerfInput::applySettings: set xb200 filter to " << settings.m_xb200Filter; } } @@ -477,19 +474,16 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool fo if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force) { -// m_settings.m_devSampleRate = settings.m_devSampleRate; + reverseAPIKeys.append("devSampleRate"); forwardChange = true; if (m_dev != 0) { unsigned int actualSamplerate; - if (bladerf_set_sample_rate(m_dev, BLADERF_MODULE_RX, settings.m_devSampleRate, &actualSamplerate) < 0) - { + if (bladerf_set_sample_rate(m_dev, BLADERF_MODULE_RX, settings.m_devSampleRate, &actualSamplerate) < 0) { qCritical("BladerfInput::applySettings: could not set sample rate: %d", settings.m_devSampleRate); - } - else - { + } else { qDebug() << "BladerfInput::applySettings: bladerf_set_sample_rate(BLADERF_MODULE_RX) actual sample rate is " << actualSamplerate; } } @@ -497,18 +491,15 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool fo if ((m_settings.m_bandwidth != settings.m_bandwidth) || force) { -// m_settings.m_bandwidth = settings.m_bandwidth; + reverseAPIKeys.append("bandwidth"); if(m_dev != 0) { unsigned int actualBandwidth; - if( bladerf_set_bandwidth(m_dev, BLADERF_MODULE_RX, settings.m_bandwidth, &actualBandwidth) < 0) - { + if( bladerf_set_bandwidth(m_dev, BLADERF_MODULE_RX, settings.m_bandwidth, &actualBandwidth) < 0) { qCritical("BladerfInput::applySettings: could not set bandwidth: %d", settings.m_bandwidth); - } - else - { + } else { qDebug() << "BladerfInput::applySettings: bladerf_set_bandwidth(BLADERF_MODULE_RX) actual bandwidth is " << actualBandwidth; } } @@ -516,6 +507,8 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool fo if ((m_settings.m_fcPos != settings.m_fcPos) || force) { + reverseAPIKeys.append("fcPos"); + if (m_bladerfThread != 0) { m_bladerfThread->setFcPos((int) settings.m_fcPos); @@ -525,7 +518,7 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool fo if ((m_settings.m_log2Decim != settings.m_log2Decim) || force) { -// m_settings.m_log2Decim = settings.m_log2Decim; + reverseAPIKeys.append("log2Decim"); forwardChange = true; if (m_bladerfThread != 0) @@ -535,6 +528,10 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool fo } } + if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) { + reverseAPIKeys.append("centerFrequency"); + } + if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || (m_settings.m_devSampleRate != settings.m_devSampleRate) || (m_settings.m_fcPos != settings.m_fcPos) @@ -547,10 +544,6 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool fo (DeviceSampleSource::fcPos_t) settings.m_fcPos, settings.m_devSampleRate); -// m_settings.m_centerFrequency = settings.m_centerFrequency; -// m_settings.m_log2Decim = settings.m_log2Decim; -// m_settings.m_fcPos = settings.m_fcPos; - forwardChange = true; if (m_dev != 0) @@ -571,6 +564,15 @@ bool Bladerf1Input::applySettings(const BladeRF1InputSettings& settings, bool fo m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif); } + 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; qDebug() << "BladerfInput::applySettings: " @@ -733,3 +735,107 @@ int Bladerf1Input::webapiRun( return 200; } + +void Bladerf1Input::webapiReverseSendSettings(QList& deviceSettingsKeys, const BladeRF1InputSettings& settings, bool force) +{ + SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings(); + swgDeviceSettings->setTx(0); + swgDeviceSettings->setDeviceHwType(new QString("BladeRF1")); + swgDeviceSettings->setBladeRf1InputSettings(new SWGSDRangel::SWGBladeRF1InputSettings()); + SWGSDRangel::SWGBladeRF1InputSettings *swgBladeRF1Settings = swgDeviceSettings->getBladeRf1InputSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (deviceSettingsKeys.contains("centerFrequency") || force) { + swgBladeRF1Settings->setCenterFrequency(settings.m_centerFrequency); + } + if (deviceSettingsKeys.contains("devSampleRate") || force) { + swgBladeRF1Settings->setDevSampleRate(settings.m_devSampleRate); + } + if (deviceSettingsKeys.contains("lnaGain") || force) { + swgBladeRF1Settings->setLnaGain(settings.m_lnaGain); + } + if (deviceSettingsKeys.contains("vga1") || force) { + swgBladeRF1Settings->setVga1(settings.m_vga1); + } + if (deviceSettingsKeys.contains("vga2") || force) { + swgBladeRF1Settings->setVga1(settings.m_vga2); + } + if (deviceSettingsKeys.contains("bandwidth") || force) { + swgBladeRF1Settings->setBandwidth(settings.m_bandwidth); + } + if (deviceSettingsKeys.contains("log2Decim") || force) { + swgBladeRF1Settings->setLog2Decim(settings.m_log2Decim); + } + if (deviceSettingsKeys.contains("fcPos") || force) { + swgBladeRF1Settings->setFcPos((int) settings.m_fcPos); + } + if (deviceSettingsKeys.contains("xb200") || force) { + swgBladeRF1Settings->setXb200(settings.m_xb200 ? 1 : 0); + } + if (deviceSettingsKeys.contains("xb200Path") || force) { + swgBladeRF1Settings->setXb200Path((int) settings.m_xb200Path); + } + if (deviceSettingsKeys.contains("xb200Filter") || force) { + swgBladeRF1Settings->setXb200Filter((int) settings.m_xb200Filter); + } + if (deviceSettingsKeys.contains("dcBlock") || force) { + swgBladeRF1Settings->setDcBlock(settings.m_dcBlock ? 1 : 0); + } + if (deviceSettingsKeys.contains("iqCorrection") || force) { + swgBladeRF1Settings->setIqCorrection(settings.m_iqCorrection ? 1 : 0); + } + if (deviceSettingsKeys.contains("fileRecordName") || force) { + swgBladeRF1Settings->setFileRecordName(new QString(settings.m_fileRecordName)); + } + + QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex); + m_networkRequest.setUrl(QUrl(deviceSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer=new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgDeviceSettings->asJson().toUtf8()); + buffer->seek(0); + + // Always use PATCH to avoid passing reverse API settings + m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + + delete swgDeviceSettings; +} + +void Bladerf1Input::webapiReverseSendStartStop(bool start) +{ + QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run") + .arg(m_settings.m_reverseAPIAddress) + .arg(m_settings.m_reverseAPIPort) + .arg(m_settings.m_reverseAPIDeviceIndex); + m_networkRequest.setUrl(QUrl(deviceSettingsURL)); + + if (start) { + m_networkManager->sendCustomRequest(m_networkRequest, "POST"); + } else { + m_networkManager->sendCustomRequest(m_networkRequest, "DELETE"); + } +} + +void Bladerf1Input::networkManagerFinished(QNetworkReply *reply) +{ + QNetworkReply::NetworkError replyError = reply->error(); + + if (replyError) + { + qWarning() << "Bladerf1Input::networkManagerFinished:" + << " error(" << (int) replyError + << "): " << replyError + << ": " << reply->errorString(); + return; + } + + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("Bladerf1Input::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); +} diff --git a/plugins/samplesource/bladerf1input/bladerf1input.h b/plugins/samplesource/bladerf1input/bladerf1input.h index 19b8feefb..ec3265c4f 100644 --- a/plugins/samplesource/bladerf1input/bladerf1input.h +++ b/plugins/samplesource/bladerf1input/bladerf1input.h @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -27,11 +28,14 @@ #include "../../../devices/bladerf1/devicebladerf1param.h" #include "bladerf1inputsettings.h" +class QNetworkAccessManager; +class QNetworkReply; class DeviceSourceAPI; class Bladerf1InputThread; class FileRecord; class Bladerf1Input : public DeviceSampleSource { + Q_OBJECT public: class MsgConfigureBladerf1 : public Message { MESSAGE_CLASS_DECLARATION @@ -133,12 +137,6 @@ public: QString& errorMessage); private: - bool openDevice(); - void closeDevice(); - bool applySettings(const BladeRF1InputSettings& settings, bool force); - bladerf_lna_gain getLnaGain(int lnaGain); - void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const BladeRF1InputSettings& settings); - DeviceSourceAPI *m_deviceAPI; QMutex m_mutex; BladeRF1InputSettings m_settings; @@ -148,6 +146,19 @@ private: DeviceBladeRF1Params m_sharedParams; bool m_running; FileRecord *m_fileSink; //!< File sink to record device I/Q output + QNetworkAccessManager *m_networkManager; + QNetworkRequest m_networkRequest; + + bool openDevice(); + void closeDevice(); + bool applySettings(const BladeRF1InputSettings& settings, bool force); + bladerf_lna_gain getLnaGain(int lnaGain); + void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const BladeRF1InputSettings& settings); + void webapiReverseSendSettings(QList& deviceSettingsKeys, const BladeRF1InputSettings& settings, bool force); + void webapiReverseSendStartStop(bool start); + +private slots: + void networkManagerFinished(QNetworkReply *reply); }; #endif // INCLUDE_BLADERFINPUT_H diff --git a/plugins/samplesource/bladerf1input/bladerf1inputgui.cpp b/plugins/samplesource/bladerf1input/bladerf1inputgui.cpp index 3978c3f6e..a627961ec 100644 --- a/plugins/samplesource/bladerf1input/bladerf1inputgui.cpp +++ b/plugins/samplesource/bladerf1input/bladerf1inputgui.cpp @@ -22,6 +22,8 @@ #include "ui_bladerf1inputgui.h" #include "gui/colormapper.h" #include "gui/glspectrum.h" +#include "gui/crightclickenabler.h" +#include "gui/basicdevicesettingsdialog.h" #include "dsp/dspengine.h" #include "dsp/dspcommands.h" #include "device/devicesourceapi.h" @@ -60,6 +62,9 @@ Bladerf1InputGui::Bladerf1InputGui(DeviceUISet *deviceUISet, QWidget* parent) : connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); m_statusTimer.start(500); + CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop); + connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &))); + displaySettings(); connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection); @@ -475,3 +480,21 @@ unsigned int Bladerf1InputGui::getXb200Index(bool xb_200, bladerf_xb200_path xb2 } } +void Bladerf1InputGui::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/bladerf1input/bladerf1inputgui.h b/plugins/samplesource/bladerf1input/bladerf1inputgui.h index c27a8f8cf..156aed389 100644 --- a/plugins/samplesource/bladerf1input/bladerf1inputgui.h +++ b/plugins/samplesource/bladerf1input/bladerf1inputgui.h @@ -89,6 +89,7 @@ private slots: void on_record_toggled(bool checked); void updateHardware(); void updateStatus(); + void openDeviceSettingsDialog(const QPoint& p); }; #endif // INCLUDE_BLADERFINPUTGUI_H diff --git a/plugins/samplesource/bladerf1input/bladerf1inputplugin.cpp b/plugins/samplesource/bladerf1input/bladerf1inputplugin.cpp index 6a826eedc..e208439ab 100644 --- a/plugins/samplesource/bladerf1input/bladerf1inputplugin.cpp +++ b/plugins/samplesource/bladerf1input/bladerf1inputplugin.cpp @@ -30,7 +30,7 @@ const PluginDescriptor Blderf1InputPlugin::m_pluginDescriptor = { QString("BladeRF1 Input"), - QString("4.2.0"), + QString("4.3.2"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplesource/bladerf1input/bladerf1inputsettings.cpp b/plugins/samplesource/bladerf1input/bladerf1inputsettings.cpp index 922b93c81..336501a93 100644 --- a/plugins/samplesource/bladerf1input/bladerf1inputsettings.cpp +++ b/plugins/samplesource/bladerf1input/bladerf1inputsettings.cpp @@ -41,6 +41,10 @@ void BladeRF1InputSettings::resetToDefaults() m_dcBlock = false; m_iqCorrection = false; m_fileRecordName = ""; + m_useReverseAPI = false; + m_reverseAPIAddress = "127.0.0.1"; + m_reverseAPIPort = 8888; + m_reverseAPIDeviceIndex = 0; } QByteArray BladeRF1InputSettings::serialize() const @@ -59,6 +63,10 @@ QByteArray BladeRF1InputSettings::serialize() const s.writeS32(10, (int) m_xb200Filter); s.writeBool(11, m_dcBlock); s.writeBool(12, m_iqCorrection); + s.writeBool(13, m_useReverseAPI); + s.writeString(14, m_reverseAPIAddress); + s.writeU32(15, m_reverseAPIPort); + s.writeU32(16, m_reverseAPIDeviceIndex); return s.final(); } @@ -76,6 +84,7 @@ bool BladeRF1InputSettings::deserialize(const QByteArray& data) if (d.getVersion() == 1) { int intval; + uint32_t uintval; d.readS32(1, &m_devSampleRate, 3072000); d.readS32(2, &m_lnaGain); @@ -92,6 +101,18 @@ bool BladeRF1InputSettings::deserialize(const QByteArray& data) m_xb200Filter = (bladerf_xb200_filter) intval; d.readBool(11, &m_dcBlock); d.readBool(12, &m_iqCorrection); + d.readBool(13, &m_useReverseAPI, false); + d.readString(14, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(15, &uintval, 0); + + if ((uintval > 1023) && (uintval < 65535)) { + m_reverseAPIPort = uintval; + } else { + m_reverseAPIPort = 8888; + } + + d.readU32(16, &uintval, 0); + m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval; return true; } diff --git a/plugins/samplesource/bladerf1input/bladerf1inputsettings.h b/plugins/samplesource/bladerf1input/bladerf1inputsettings.h index ddaf11b6f..850ab4261 100644 --- a/plugins/samplesource/bladerf1input/bladerf1inputsettings.h +++ b/plugins/samplesource/bladerf1input/bladerf1inputsettings.h @@ -42,6 +42,10 @@ struct BladeRF1InputSettings { bool m_dcBlock; bool m_iqCorrection; QString m_fileRecordName; + bool m_useReverseAPI; + QString m_reverseAPIAddress; + uint16_t m_reverseAPIPort; + uint16_t m_reverseAPIDeviceIndex; BladeRF1InputSettings(); void resetToDefaults(); diff --git a/plugins/samplesource/bladerf2input/bladerf2input.cpp b/plugins/samplesource/bladerf2input/bladerf2input.cpp index 2f3faa600..175afea03 100644 --- a/plugins/samplesource/bladerf2input/bladerf2input.cpp +++ b/plugins/samplesource/bladerf2input/bladerf2input.cpp @@ -15,6 +15,8 @@ /////////////////////////////////////////////////////////////////////////////////// #include +#include +#include #include "libbladeRF.h" @@ -65,10 +67,15 @@ BladeRF2Input::BladeRF2Input(DeviceSourceAPI *deviceAPI) : m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID())); m_deviceAPI->addSink(m_fileSink); + m_networkManager = new QNetworkAccessManager(); + connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); } BladeRF2Input::~BladeRF2Input() { + disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); + delete m_networkManager; + if (m_running) { stop(); } @@ -743,6 +750,10 @@ bool BladeRF2Input::handleMessage(const Message& message) m_deviceAPI->stopAcquisition(); } + if (m_settings.m_useReverseAPI) { + webapiReverseSendStartStop(cmd.getStartStop()); + } + return true; } else @@ -762,6 +773,14 @@ bool BladeRF2Input::applySettings(const BladeRF2InputSettings& settings, bool fo qint64 xlatedDeviceCenterFrequency = settings.m_centerFrequency; xlatedDeviceCenterFrequency -= settings.m_transverterMode ? settings.m_transverterDeltaFrequency : 0; xlatedDeviceCenterFrequency = xlatedDeviceCenterFrequency < 0 ? 0 : xlatedDeviceCenterFrequency; + QList reverseAPIKeys; + + if ((m_settings.m_dcBlock != settings.m_dcBlock) || force) { + reverseAPIKeys.append("dcBlock"); + } + if ((m_settings.m_iqCorrection != settings.m_iqCorrection) || force) { + reverseAPIKeys.append("iqCorrection"); + } if ((m_settings.m_dcBlock != settings.m_dcBlock) || (m_settings.m_iqCorrection != settings.m_iqCorrection) || force) @@ -771,6 +790,7 @@ bool BladeRF2Input::applySettings(const BladeRF2InputSettings& settings, bool fo if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force) { + reverseAPIKeys.append("devSampleRate"); forwardChangeOwnDSP = true; forwardChangeRxBuddies = true; forwardChangeTxBuddies = true; @@ -794,6 +814,7 @@ bool BladeRF2Input::applySettings(const BladeRF2InputSettings& settings, bool fo if ((m_settings.m_bandwidth != settings.m_bandwidth) || force) { + reverseAPIKeys.append("bandwidth"); forwardChangeRxBuddies = true; if (dev != 0) @@ -815,6 +836,7 @@ bool BladeRF2Input::applySettings(const BladeRF2InputSettings& settings, bool fo if ((m_settings.m_fcPos != settings.m_fcPos) || force) { + reverseAPIKeys.append("fcPos"); BladeRF2InputThread *inputThread = findThread(); if (inputThread != 0) @@ -826,6 +848,7 @@ bool BladeRF2Input::applySettings(const BladeRF2InputSettings& settings, bool fo if ((m_settings.m_log2Decim != settings.m_log2Decim) || force) { + reverseAPIKeys.append("log2Decim"); forwardChangeOwnDSP = true; BladeRF2InputThread *inputThread = findThread(); @@ -836,6 +859,22 @@ bool BladeRF2Input::applySettings(const BladeRF2InputSettings& settings, bool fo } } + if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) { + reverseAPIKeys.append("centerFrequency"); + } + if ((m_settings.m_transverterMode != settings.m_transverterMode) || force) { + reverseAPIKeys.append("transverterMode"); + } + if ((m_settings.m_transverterDeltaFrequency != settings.m_transverterDeltaFrequency) || force) { + reverseAPIKeys.append("transverterDeltaFrequency"); + } + if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) { + reverseAPIKeys.append("LOppmTenths"); + } + if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force) { + reverseAPIKeys.append("devSampleRate"); + } + if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || (m_settings.m_transverterMode != settings.m_transverterMode) || (m_settings.m_transverterDeltaFrequency != settings.m_transverterDeltaFrequency) @@ -871,12 +910,14 @@ bool BladeRF2Input::applySettings(const BladeRF2InputSettings& settings, bool fo if ((m_settings.m_biasTee != settings.m_biasTee) || force) { + reverseAPIKeys.append("biasTee"); forwardChangeRxBuddies = true; m_deviceShared.m_dev->setBiasTeeRx(settings.m_biasTee); } if ((m_settings.m_gainMode != settings.m_gainMode) || force) { + reverseAPIKeys.append("gainMode"); forwardChangeRxBuddies = true; if (dev) @@ -892,6 +933,13 @@ bool BladeRF2Input::applySettings(const BladeRF2InputSettings& settings, bool fo } } + if ((m_settings.m_globalGain != settings.m_globalGain) || force) { + reverseAPIKeys.append("globalGain"); + } + if ((m_settings.m_gainMode != settings.m_gainMode) || force) { + reverseAPIKeys.append("gainMode"); + } + if ((m_settings.m_globalGain != settings.m_globalGain) || ((m_settings.m_gainMode != settings.m_gainMode) && (settings.m_gainMode == BLADERF_GAIN_MANUAL)) || force) { @@ -955,6 +1003,15 @@ bool BladeRF2Input::applySettings(const BladeRF2InputSettings& settings, bool fo } } + 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; qDebug() << "BladeRF2Input::applySettings: " @@ -1161,3 +1218,107 @@ int BladeRF2Input::webapiRun( return 200; } + +void BladeRF2Input::webapiReverseSendSettings(QList& deviceSettingsKeys, const BladeRF2InputSettings& settings, bool force) +{ + SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings(); + swgDeviceSettings->setTx(0); + swgDeviceSettings->setDeviceHwType(new QString("BladeRF2")); + swgDeviceSettings->setBladeRf2InputSettings(new SWGSDRangel::SWGBladeRF2InputSettings()); + SWGSDRangel::SWGBladeRF2InputSettings *swgBladeRF2Settings = swgDeviceSettings->getBladeRf2InputSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (deviceSettingsKeys.contains("centerFrequency") || force) { + swgBladeRF2Settings->setCenterFrequency(settings.m_centerFrequency); + } + if (deviceSettingsKeys.contains("LOppmTenths") || force) { + swgBladeRF2Settings->setLOppmTenths(settings.m_LOppmTenths); + } + if (deviceSettingsKeys.contains("log2Decim") || force) { + swgBladeRF2Settings->setLog2Decim(settings.m_log2Decim); + } + if (deviceSettingsKeys.contains("fcPos") || force) { + swgBladeRF2Settings->setFcPos((int) settings.m_fcPos); + } + if (deviceSettingsKeys.contains("dcBlock") || force) { + swgBladeRF2Settings->setDcBlock(settings.m_dcBlock ? 1 : 0); + } + if (deviceSettingsKeys.contains("iqCorrection") || force) { + swgBladeRF2Settings->setIqCorrection(settings.m_iqCorrection ? 1 : 0); + } + if (deviceSettingsKeys.contains("transverterDeltaFrequency") || force) { + swgBladeRF2Settings->setTransverterDeltaFrequency(settings.m_transverterDeltaFrequency); + } + if (deviceSettingsKeys.contains("transverterMode") || force) { + swgBladeRF2Settings->setTransverterMode(settings.m_transverterMode ? 1 : 0); + } + if (deviceSettingsKeys.contains("fileRecordName") || force) { + swgBladeRF2Settings->setFileRecordName(new QString(settings.m_fileRecordName)); + } + if (deviceSettingsKeys.contains("devSampleRate")) { + swgBladeRF2Settings->setDevSampleRate(settings.m_devSampleRate); + } + if (deviceSettingsKeys.contains("bandwidth")) { + swgBladeRF2Settings->setBandwidth(settings.m_bandwidth); + } + if (deviceSettingsKeys.contains("biasTee")) { + swgBladeRF2Settings->setBiasTee(settings.m_biasTee); + } + if (deviceSettingsKeys.contains("gainMode")) { + swgBladeRF2Settings->setGainMode(settings.m_gainMode); + } + if (deviceSettingsKeys.contains("globalGain")) { + swgBladeRF2Settings->setGlobalGain(settings.m_globalGain); + } + + QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex); + m_networkRequest.setUrl(QUrl(deviceSettingsURL)); + m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QBuffer *buffer=new QBuffer(); + buffer->open((QBuffer::ReadWrite)); + buffer->write(swgDeviceSettings->asJson().toUtf8()); + buffer->seek(0); + + // Always use PATCH to avoid passing reverse API settings + m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer); + + delete swgDeviceSettings; +} + +void BladeRF2Input::webapiReverseSendStartStop(bool start) +{ + QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run") + .arg(m_settings.m_reverseAPIAddress) + .arg(m_settings.m_reverseAPIPort) + .arg(m_settings.m_reverseAPIDeviceIndex); + m_networkRequest.setUrl(QUrl(deviceSettingsURL)); + + if (start) { + m_networkManager->sendCustomRequest(m_networkRequest, "POST"); + } else { + m_networkManager->sendCustomRequest(m_networkRequest, "DELETE"); + } +} + +void BladeRF2Input::networkManagerFinished(QNetworkReply *reply) +{ + QNetworkReply::NetworkError replyError = reply->error(); + + if (replyError) + { + qWarning() << "BladeRF2Input::networkManagerFinished:" + << " error(" << (int) replyError + << "): " << replyError + << ": " << reply->errorString(); + return; + } + + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("BladeRF2Input::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); +} diff --git a/plugins/samplesource/bladerf2input/bladerf2input.h b/plugins/samplesource/bladerf2input/bladerf2input.h index 4b9a79561..ea4498c5f 100644 --- a/plugins/samplesource/bladerf2input/bladerf2input.h +++ b/plugins/samplesource/bladerf2input/bladerf2input.h @@ -17,22 +17,26 @@ #ifndef PLUGINS_SAMPLESOURCE_BLADERF2INPUT_BLADERF2INPUT_H_ #define PLUGINS_SAMPLESOURCE_BLADERF2INPUT_BLADERF2INPUT_H_ +#include + #include #include -#include +#include #include "dsp/devicesamplesource.h" #include "bladerf2/devicebladerf2shared.h" #include "bladerf2inputsettings.h" +class QNetworkAccessManager; +class QNetworkReply; class DeviceSourceAPI; class BladeRF2InputThread; class FileRecord; struct bladerf_gain_modes; struct bladerf; -class BladeRF2Input : public DeviceSampleSource -{ +class BladeRF2Input : public DeviceSampleSource { + Q_OBJECT public: class MsgConfigureBladeRF2 : public Message { MESSAGE_CLASS_DECLARATION @@ -186,6 +190,8 @@ private: BladeRF2InputThread *m_thread; FileRecord *m_fileSink; //!< File sink to record device I/Q output std::vector m_gainModes; + QNetworkAccessManager *m_networkManager; + QNetworkRequest m_networkRequest; bool openDevice(); void closeDevice(); @@ -195,6 +201,11 @@ private: bool setDeviceCenterFrequency(struct bladerf *dev, int requestedChannel, quint64 freq_hz, int loPpmTenths); void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const BladeRF2InputSettings& settings); void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response); + void webapiReverseSendSettings(QList& deviceSettingsKeys, const BladeRF2InputSettings& settings, bool force); + void webapiReverseSendStartStop(bool start); + +private slots: + void networkManagerFinished(QNetworkReply *reply); }; #endif /* PLUGINS_SAMPLESOURCE_BLADERF2INPUT_BLADERF2INPUT_H_ */ diff --git a/plugins/samplesource/bladerf2input/bladerf2inputgui.cpp b/plugins/samplesource/bladerf2input/bladerf2inputgui.cpp index 02e78775a..e00db93d2 100644 --- a/plugins/samplesource/bladerf2input/bladerf2inputgui.cpp +++ b/plugins/samplesource/bladerf2input/bladerf2inputgui.cpp @@ -22,6 +22,8 @@ #include "ui_bladerf2inputgui.h" #include "gui/colormapper.h" #include "gui/glspectrum.h" +#include "gui/crightclickenabler.h" +#include "gui/basicdevicesettingsdialog.h" #include "dsp/dspengine.h" #include "dsp/dspcommands.h" #include "device/devicesourceapi.h" @@ -81,6 +83,9 @@ BladeRF2InputGui::BladeRF2InputGui(DeviceUISet *deviceUISet, QWidget* parent) : connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); m_statusTimer.start(500); + CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop); + connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &))); + displaySettings(); connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection); @@ -457,3 +462,22 @@ void BladeRF2InputGui::updateStatus() m_lastEngineState = state; } } + +void BladeRF2InputGui::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/bladerf2input/bladerf2inputgui.h b/plugins/samplesource/bladerf2input/bladerf2inputgui.h index 665670f3d..0b2483793 100644 --- a/plugins/samplesource/bladerf2input/bladerf2inputgui.h +++ b/plugins/samplesource/bladerf2input/bladerf2inputgui.h @@ -91,6 +91,7 @@ private slots: void on_record_toggled(bool checked); void updateHardware(); void updateStatus(); + void openDeviceSettingsDialog(const QPoint& p); }; diff --git a/plugins/samplesource/bladerf2input/bladerf2inputplugin.cpp b/plugins/samplesource/bladerf2input/bladerf2inputplugin.cpp index 2008e9bd7..af26bfb3c 100644 --- a/plugins/samplesource/bladerf2input/bladerf2inputplugin.cpp +++ b/plugins/samplesource/bladerf2input/bladerf2inputplugin.cpp @@ -30,7 +30,7 @@ const PluginDescriptor Blderf2InputPlugin::m_pluginDescriptor = { QString("BladeRF2 Input"), - QString("4.3.0"), + QString("4.3.2"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplesource/bladerf2input/bladerf2inputsettings.cpp b/plugins/samplesource/bladerf2input/bladerf2inputsettings.cpp index 21e939ff2..597891783 100644 --- a/plugins/samplesource/bladerf2input/bladerf2inputsettings.cpp +++ b/plugins/samplesource/bladerf2input/bladerf2inputsettings.cpp @@ -39,6 +39,10 @@ void BladeRF2InputSettings::resetToDefaults() m_transverterMode = false; m_transverterDeltaFrequency = 0; m_fileRecordName = ""; + m_useReverseAPI = false; + m_reverseAPIAddress = "127.0.0.1"; + m_reverseAPIPort = 8888; + m_reverseAPIDeviceIndex = 0; } QByteArray BladeRF2InputSettings::serialize() const @@ -57,6 +61,10 @@ QByteArray BladeRF2InputSettings::serialize() const s.writeS32(10, m_LOppmTenths); s.writeBool(11, m_transverterMode); s.writeS64(12, m_transverterDeltaFrequency); + s.writeBool(13, m_useReverseAPI); + s.writeString(14, m_reverseAPIAddress); + s.writeU32(15, m_reverseAPIPort); + s.writeU32(16, m_reverseAPIDeviceIndex); return s.final(); } @@ -74,6 +82,7 @@ bool BladeRF2InputSettings::deserialize(const QByteArray& data) if (d.getVersion() == 1) { int intval; + uint32_t uintval; d.readS32(1, &m_devSampleRate, 3072000); d.readS32(2, &m_bandwidth); @@ -88,6 +97,18 @@ bool BladeRF2InputSettings::deserialize(const QByteArray& data) d.readS32(10, &m_LOppmTenths); d.readBool(11, &m_transverterMode, false); d.readS64(12, &m_transverterDeltaFrequency, 0); + d.readBool(13, &m_useReverseAPI, false); + d.readString(14, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(15, &uintval, 0); + + if ((uintval > 1023) && (uintval < 65535)) { + m_reverseAPIPort = uintval; + } else { + m_reverseAPIPort = 8888; + } + + d.readU32(16, &uintval, 0); + m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval; return true; } diff --git a/plugins/samplesource/bladerf2input/bladerf2inputsettings.h b/plugins/samplesource/bladerf2input/bladerf2inputsettings.h index 722be9e6e..26ad4ca56 100644 --- a/plugins/samplesource/bladerf2input/bladerf2inputsettings.h +++ b/plugins/samplesource/bladerf2input/bladerf2inputsettings.h @@ -41,6 +41,10 @@ struct BladeRF2InputSettings { bool m_transverterMode; qint64 m_transverterDeltaFrequency; QString m_fileRecordName; + bool m_useReverseAPI; + QString m_reverseAPIAddress; + uint16_t m_reverseAPIPort; + uint16_t m_reverseAPIDeviceIndex; BladeRF2InputSettings(); void resetToDefaults();