1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-12-23 10:05:46 -05:00
sdrangel/plugins/samplesource/sdrplayv3/sdrplayv3input.cpp

1480 lines
54 KiB
C++

///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021-2023 Jon Beniston, M7RCE <jon@beniston.com> //
// Copyright (C) 2021-2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// Copyright (C) 2021 Franco Venturi <fventuri@comcast.net> //
// Copyright (C) 2022 Piotr Majkrzak <piotr@majkrzak.dev> //
// Copyright (C) 2023 Daniele Forsi <iu5hkx@gmail.com> //
// //
// 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <string.h>
#include <errno.h>
#include <QDebug>
#include <QNetworkReply>
#include <QBuffer>
#include "SWGDeviceSettings.h"
#include "SWGDeviceState.h"
#include "SWGDeviceReport.h"
#include "SWGSDRPlayV3Report.h"
#include "util/simpleserializer.h"
#include "dsp/dspcommands.h"
#include "sdrplayv3input.h"
#include <device/deviceapi.h>
#include "sdrplayv3thread.h"
MESSAGE_CLASS_DEFINITION(SDRPlayV3Input::MsgConfigureSDRPlayV3, Message)
MESSAGE_CLASS_DEFINITION(SDRPlayV3Input::MsgStartStop, Message)
MESSAGE_CLASS_DEFINITION(SDRPlayV3Input::MsgSaveReplay, 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)
{
m_sampleFifo.setLabel(m_deviceDescription);
openDevice();
m_deviceAPI->setNbSourceStreams(1);
m_networkManager = new QNetworkAccessManager();
QObject::connect(
m_networkManager,
&QNetworkAccessManager::finished,
this,
&SDRPlayV3Input::networkManagerFinished
);
}
SDRPlayV3Input::~SDRPlayV3Input()
{
QObject::disconnect(
m_networkManager,
&QNetworkAccessManager::finished,
this,
&SDRPlayV3Input::networkManagerFinished
);
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 successfully";
}
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()
{
QMutexLocker mutexLocker(&m_mutex);
if (m_running) {
return true;
}
if (!m_dev) {
return false;
}
qDebug() << "SDRPlayV3Input::start";
m_sdrPlayThread = new SDRPlayV3Thread(m_dev, &m_sampleFifo, &m_replayBuffer);
m_sdrPlayThread->setLog2Decimation(m_settings.m_log2Decim);
m_sdrPlayThread->setFcPos((int) m_settings.m_fcPos);
m_sdrPlayThread->startWork();
m_running = m_sdrPlayThread->isRunning();
mutexLocker.unlock();
applySettings(m_settings, QList<QString>(), true, 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, QList<QString>(), true, true);
}
void SDRPlayV3Input::stop()
{
QMutexLocker mutexLocker(&m_mutex);
if (!m_running) {
return;
}
qDebug() << "SDRPlayV3Input::stop";
m_running = false;
if(m_sdrPlayThread)
{
m_sdrPlayThread->stopWork();
delete m_sdrPlayThread;
m_sdrPlayThread = nullptr;
}
}
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, QList<QString>(), true);
m_inputMessageQueue.push(message);
if (m_guiMessageQueue)
{
MsgConfigureSDRPlayV3* messageToGUI = MsgConfigureSDRPlayV3::create(m_settings, QList<QString>(), true);
m_guiMessageQueue->push(messageToGUI);
}
return success;
}
const QString& SDRPlayV3Input::getDeviceDescription() const
{
return m_deviceDescription;
}
int SDRPlayV3Input::getSampleRate() const
{
uint32_t fsHz = m_settings.m_devSampleRate;
sdrplay_api_Bw_MHzT bwType = SDRPlayV3Bandwidths::getBandwidthEnum(m_settings.m_bandwidthIndex);
sdrplay_api_If_kHzT ifType = SDRPlayV3IF::getIFEnum(m_settings.m_ifFrequencyIndex);
if(
((fsHz == 8192000) && (bwType == sdrplay_api_BW_1_536) && (ifType == sdrplay_api_IF_2_048)) ||
((fsHz == 8000000) && (bwType == sdrplay_api_BW_1_536) && (ifType == sdrplay_api_IF_2_048)) ||
((fsHz == 8000000) && (bwType == sdrplay_api_BW_5_000) && (ifType == sdrplay_api_IF_2_048)) ||
((fsHz == 2000000) && (bwType <= sdrplay_api_BW_0_300) && (ifType == sdrplay_api_IF_0_450))) {
fsHz /= 4;
} else if ((fsHz == 2000000) && (bwType == sdrplay_api_BW_0_600) && (ifType == sdrplay_api_IF_0_450)) {
fsHz /= 2;
}else if ((fsHz == 6000000) && (bwType <= sdrplay_api_BW_1_536) && (ifType == sdrplay_api_IF_1_620)) {
fsHz /= 3;
}
return fsHz / (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, QList<QString>{"centerFrequency"}, false);
m_inputMessageQueue.push(message);
if (m_guiMessageQueue)
{
MsgConfigureSDRPlayV3* messageToGUI = MsgConfigureSDRPlayV3::create(settings, QList<QString>{"centerFrequency"}, false);
m_guiMessageQueue->push(messageToGUI);
}
}
bool SDRPlayV3Input::handleMessage(const Message& message)
{
if (MsgConfigureSDRPlayV3::match(message))
{
MsgConfigureSDRPlayV3& conf = (MsgConfigureSDRPlayV3&) message;
qDebug() << "SDRPlayV3Input::handleMessage: MsgConfigureSDRPlayV3";
if (!applySettings( conf.getSettings(), conf.getSettingsKeys(), 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 if (MsgSaveReplay::match(message))
{
MsgSaveReplay& cmd = (MsgSaveReplay&) message;
m_replayBuffer.save(cmd.getFilename(), m_settings.m_devSampleRate, getCenterFrequency());
return true;
}
else
{
return false;
}
}
bool SDRPlayV3Input::applySettings(const SDRPlayV3Settings& settings, const QList<QString>& settingsKeys, bool forwardChange, bool force)
{
qDebug() << "SDRPlayV3Input::applySettings: forwardChange: " << forwardChange << " force: " << force << settings.getDebugString(settingsKeys, force);
QMutexLocker mutexLocker(&m_mutex);
sdrplay_api_ErrT err;
if (settingsKeys.contains("tuner") || force)
{
if (m_running)
{
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 (settingsKeys.contains("dcBlock") || force)
{
if (m_running)
{
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 (settingsKeys.contains("iqCorrection") || force)
{
if (m_running)
{
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 (settingsKeys.contains("ifAGC") || force)
{
if (m_running)
{
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 (settingsKeys.contains("lnaIndex")
|| settingsKeys.contains("ifGain")
|| settingsKeys.contains("ifAGC") || force)
{
if (m_running)
{
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 (settingsKeys.contains("devSampleRate") || force)
{
if (m_running)
{
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 (settings.m_devSampleRate != m_settings.m_devSampleRate) {
m_replayBuffer.clear();
}
}
}
if (settingsKeys.contains("log2Decim") || force)
{
if (m_sdrPlayThread)
{
m_sdrPlayThread->setLog2Decimation(settings.m_log2Decim);
qDebug() << "SDRPlayV3Input::applySettings: set decimation to " << (1<<settings.m_log2Decim);
}
}
if (settingsKeys.contains("fcPos") || force)
{
if (m_sdrPlayThread)
{
m_sdrPlayThread->setFcPos((int) settings.m_fcPos);
qDebug() << "SDRPlayV3Input:applySettings: set fc pos (enum) to " << (int) settings.m_fcPos;
}
}
if (settingsKeys.contains("iqOrder") || force)
{
if (m_sdrPlayThread) {
m_sdrPlayThread->setIQOrder(settings.m_iqOrder);
}
}
if (settingsKeys.contains("centerFrequency")
|| settingsKeys.contains("LOppmTenths")
|| settingsKeys.contains("fcPos")
|| settingsKeys.contains("log2Decim")
|| settingsKeys.contains("transverterMode")
|| settingsKeys.contains("transverterDeltaFrequency") || force)
{
qint64 deviceCenterFrequency = DeviceSampleSource::calculateDeviceCenterFrequency(
settings.m_centerFrequency,
settings.m_transverterDeltaFrequency,
settings.m_log2Decim,
(DeviceSampleSource::fcPos_t) settings.m_fcPos,
settings.m_devSampleRate,
DeviceSampleSource::FrequencyShiftScheme::FSHIFT_STD,
settings.m_transverterMode);
forwardChange = true;
if (m_running)
{
if (setDeviceCenterFrequency(deviceCenterFrequency)) {
qDebug() << "SDRPlayV3Input::applySettings: center freq: " << settings.m_centerFrequency << " Hz";
}
}
}
if (settingsKeys.contains("bandwidthIndex") || force)
{
if (m_running)
{
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);
m_sdrPlayThread->resetRfChanged();
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_sdrPlayThread->waitForRfChanged())
qCritical() << "SDRPlayV3Input::applySettings: could not set bandwidth: Rf update timed out";
}
}
if (settingsKeys.contains("ifFrequencyIndex") || force)
{
if (m_running)
{
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);
m_sdrPlayThread->resetRfChanged();
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_sdrPlayThread->waitForRfChanged())
qCritical() << "SDRPlayV3Input::applySettings: could not set IF frequency: Rf update timed out";
}
}
if (settingsKeys.contains("biasTee") || force)
{
if (m_running)
{
sdrplay_api_ReasonForUpdateT update = sdrplay_api_Update_None;
sdrplay_api_ReasonForUpdateExtension1T updateExt = sdrplay_api_Update_Ext1_None;
switch (getDeviceId())
{
case SDRPLAY_RSP1A_ID:
case SDRPLAY_RSP1B_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:
case SDRPLAY_RSPdxR2_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 (settingsKeys.contains("amNotch") || force)
{
if (m_running)
{
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 (settingsKeys.contains("fmNotch") || force)
{
if (m_running)
{
sdrplay_api_ReasonForUpdateT update = sdrplay_api_Update_None;
sdrplay_api_ReasonForUpdateExtension1T updateExt = sdrplay_api_Update_Ext1_None;
switch (getDeviceId())
{
case SDRPLAY_RSP1A_ID:
case SDRPLAY_RSP1B_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:
case SDRPLAY_RSPdxR2_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 (settingsKeys.contains("dabNotch") || force)
{
if (m_running)
{
sdrplay_api_ReasonForUpdateT update = sdrplay_api_Update_None;
sdrplay_api_ReasonForUpdateExtension1T updateExt = sdrplay_api_Update_Ext1_None;
switch (getDeviceId())
{
case SDRPLAY_RSP1A_ID:
case SDRPLAY_RSP1B_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:
case SDRPLAY_RSPdxR2_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 (settingsKeys.contains("antenna") || force)
{
if (m_running)
{
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:
case SDRPLAY_RSPdxR2_ID:
m_devParams->devParams->rspDxParams.antennaSel = (sdrplay_api_RspDx_AntennaSelectT)settings.m_antenna;
updateExt = sdrplay_api_Update_RspDx_AntennaControl;
break;
default:
// SDRPLAY_RSP1_ID, SDRPLAY_RSP1A_ID, SDRPLAY_RSP1B_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 (settingsKeys.contains("extRef") || force)
{
if (m_running)
{
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 = (settingsKeys.contains("useReverseAPI") && settings.m_useReverseAPI) ||
settingsKeys.contains("reverseAPIAddress") ||
settingsKeys.contains("reverseAPIPort") ||
settingsKeys.contains("reverseAPIDeviceIndex");
webapiReverseSendSettings(settingsKeys, settings, fullUpdate || force);
}
if (force) {
m_settings = settings;
} else {
m_settings.applySettings(settingsKeys, settings);
}
if (settingsKeys.contains("replayLength") || settingsKeys.contains("devSampleRate") || force) {
m_replayBuffer.setSize(m_settings.m_replayLength, m_settings.m_devSampleRate);
}
if (settingsKeys.contains("replayOffset") || settingsKeys.contains("devSampleRate") || force) {
m_replayBuffer.setReadOffset(((unsigned)(m_settings.m_replayOffset * m_settings.m_devSampleRate)) * 2);
}
if (settingsKeys.contains("replayLoop") || force) {
m_replayBuffer.setLoop(m_settings.m_replayLoop);
}
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;
m_sdrPlayThread->resetRfChanged();
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 set frequency to %llu Hz", freq_hz);
return false;
}
else if (!m_sdrPlayThread->waitForRfChanged())
{
qWarning() << "SDRPlayV3Input::setDeviceCenterFrequency: could not set frequency: Rf update timed out";
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;
QStringList deviceSettingsKeysModifiable = deviceSettingsKeys;
webapiUpdateDeviceSettings(settings, deviceSettingsKeysModifiable, response);
// Convert lnaGain to lnaIndex
if (deviceSettingsKeysModifiable.contains("lnaGain"))
{
int lnaGain = response.getSdrPlayV3Settings()->getLnaGain();
settings.m_lnaIndex = mapLNAGainDBToLNAIndex(lnaGain, settings.m_centerFrequency);
deviceSettingsKeysModifiable.append("lnaIndex");
}
MsgConfigureSDRPlayV3 *msg = MsgConfigureSDRPlayV3::create(settings, deviceSettingsKeysModifiable, force);
m_inputMessageQueue.push(msg);
if (m_guiMessageQueue) // forward to GUI if any
{
MsgConfigureSDRPlayV3 *msgToGUI = MsgConfigureSDRPlayV3::create(settings, deviceSettingsKeysModifiable, 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("transverterDeltaFrequency")) {
settings.m_transverterDeltaFrequency = response.getSdrPlayV3Settings()->getTransverterDeltaFrequency();
}
if (deviceSettingsKeys.contains("transverterMode")) {
settings.m_transverterMode = response.getSdrPlayV3Settings()->getTransverterMode() != 0;
}
if (deviceSettingsKeys.contains("iqOrder")) {
settings.m_iqOrder = response.getSdrPlayV3Settings()->getIqOrder() != 0;
}
if (deviceSettingsKeys.contains("biasTee")) {
settings.m_biasTee = response.getSdrPlayV3Settings()->getBiasTee() != 0;
}
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()->setLnaGain(0); // Write only setting
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()->setTransverterDeltaFrequency(settings.m_transverterDeltaFrequency);
response.getSdrPlayV3Settings()->setTransverterMode(settings.m_transverterMode ? 1 : 0);
response.getSdrPlayV3Settings()->setIqOrder(settings.m_iqOrder ? 1 : 0);
response.getSdrPlayV3Settings()->setBiasTee(settings.m_biasTee ? 1 : 0);
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<SWGSDRangel::SWGFrequency*>);
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<SWGSDRangel::SWGBandwidth*>);
for (unsigned int i = 0; i < SDRPlayV3Bandwidths::getNbBandwidths(); i++)
{
response.getSdrPlayV3Report()->getBandwidths()->append(new SWGSDRangel::SWGBandwidth);
response.getSdrPlayV3Report()->getBandwidths()->back()->setBandwidth(SDRPlayV3Bandwidths::getBandwidth(i));
}
switch(getDeviceId())
{
case SDRPLAY_RSP1_ID:
response.getSdrPlayV3Report()->setDeviceType(new QString("RSP1"));
break;
case SDRPLAY_RSP1A_ID:
response.getSdrPlayV3Report()->setDeviceType(new QString("RSP1A"));
break;
case SDRPLAY_RSP1B_ID:
response.getSdrPlayV3Report()->setDeviceType(new QString("RSP1B"));
break;
case SDRPLAY_RSP2_ID:
response.getSdrPlayV3Report()->setDeviceType(new QString("RSP2"));
break;
case SDRPLAY_RSPduo_ID:
response.getSdrPlayV3Report()->setDeviceType(new QString("RSPduo"));
break;
case SDRPLAY_RSPdx_ID:
response.getSdrPlayV3Report()->setDeviceType(new QString("RSPdx"));
break;
case SDRPLAY_RSPdxR2_ID:
response.getSdrPlayV3Report()->setDeviceType(new QString("RSPdx-R2"));
break;
default:
response.getSdrPlayV3Report()->setDeviceType(new QString("Unknown"));
break;
}
}
void SDRPlayV3Input::webapiReverseSendSettings(const QList<QString>& 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("SDRplayV3"));
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("lnaGain") || force) {
swgSDRPlayV3Settings->setLnaGain(0); // Write only setting
}
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);
}
if (deviceSettingsKeys.contains("transverterDeltaFrequency") || force) {
swgSDRPlayV3Settings->setTransverterDeltaFrequency(settings.m_transverterDeltaFrequency);
}
if (deviceSettingsKeys.contains("transverterMode") || force) {
swgSDRPlayV3Settings->setTransverterMode(settings.m_transverterMode ? 1 : 0);
}
if (deviceSettingsKeys.contains("iqOrder") || force) {
swgSDRPlayV3Settings->setIqOrder(settings.m_iqOrder ? 1 : 0);
}
if (deviceSettingsKeys.contains("biasTee") || force) {
swgSDRPlayV3Settings->setBiasTee(settings.m_biasTee ? 1 : 0);
}
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("SDRplayV3"));
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() const
{
if (m_dev != nullptr)
return m_dev->hwVer; // E.g. SDRPLAY_RSPduo_ID
else
return -1;
}
// Convert gain in dB to closest index
int SDRPlayV3Input::mapLNAGainDBToLNAIndex(int gainDB, qint64 frequency) const
{
const int *attenuations = SDRPlayV3LNA::getAttenuations(getDeviceId(), frequency);
int len = attenuations[0];
for (int i = 1; i <= len; i++)
{
if (gainDB >= -attenuations[i]) {
return i - 1;
}
}
return len - 1;
}
// Convert index to gain in dB
int SDRPlayV3Input::mapLNAIndexToLNAGainDB(int lnaIndex, qint64 frequency) const
{
const int *attenuations = SDRPlayV3LNA::getAttenuations(getDeviceId(), frequency);
int len = attenuations[0];
if (lnaIndex < len) {
return attenuations[lnaIndex+1];
} else {
return -1000;
}
}
// ====================================================================
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::rsp1BAttenuation[5][11] =
{
{7, 0, 6, 12, 18, 37, 42, 61},
{10, 0, 6, 12, 18, 20, 26, 32, 38, 57, 62},
{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} // HiZ port
};
const int SDRPlayV3LNA::rspDxAttenuation[7][29] =
{
{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},
{28, 0, 3, 6, 9, 12, 15, 18, 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_RSP1B_ID:
if (frequency < 50000000)
row = 0;
else if (frequency < 60000000)
row = 1;
else if (frequency < 420000000)
row = 2;
else if (frequency < 1000000000)
row = 3;
else
row = 4;
lnaAttenuation = &rsp1BAttenuation[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:
case SDRPLAY_RSPdxR2_ID:
if (frequency < 2000000)
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;
}