1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2026-06-05 07:24:44 -04:00

Add SDRplay V3 API sample source.

This commit is contained in:
Jon Beniston
2021-04-11 21:21:36 +01:00
parent c5ece265e9
commit 7aebff1082
36 changed files with 5282 additions and 13 deletions
+4
View File
@@ -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()
@@ -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})
+118
View File
@@ -0,0 +1,118 @@
<h1>SDRplay plugin</h1>
<h2>Introduction</h2>
This plugin supports input from SDRplay RSP devices using V3 of SDRplay's API, including RSP1, RSP1A, RSP2, RSPduo and RSPdx.
<h2>Interface</h2>
![SDRplay v3 plugin GUI](../../../doc/img/SDRPlayV3_plugin.png)
<h3>1: Start/Stop</h3>
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.
<h3>2: Sample rate</h3>
This is the sample rate at which IQ samples are transfered from the device to SDRangel, in kS/s (k).
<h3>3: Center frequency</h3>
This is the center frequency of reception in kHz.
<h3>4: Local oscillator frequency correction</h3>
This is the correction in tenths of ppm steps.
<h3>5: Tuner selection</h3>
Selects which tuner is used for input. For RSPduo this can be 1 or 2. Other RSP devices only have a single tuner.
<h3>6: Antenna port</h3>
Selects which antenna port is used. The antenna ports available depend upon the RSP device and tuner selected.
<h3>7: DC offset correction</h3>
Check this button to enable DC offset correction.
<h3>8: IQ imbalance correction</h3>
Check this button to enable IQ imbalance correction.
<h3>9: External reference clock output</h3>
Enable reference clock output. This is only available for RSP2 and DSPduo.
<h3>10: Bias tee</h3>
Enable bias tee. This is only available for RSP1A, RSP2, RSPduo tuner 2 and RSPdx.
<h3>11: AM notch filter</h3>
Enable AM notch filter. This is only available for RSPduo tuner 1.
<h3>12: MW/FM notch filter</h3>
Enable MW/FM notch filter. This is only available for RSP1A, RSP2, RSPduo and RSPdx.
<h3>13: DAB notch filter</h3>
Enable DAB notch filter. This is only available for RSP1A, RSPduo and RSPdx.
<h3>14: IF bandwidth</h3>
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
<h3>15: IF frequency</h3>
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)
<h3>16: Sample rate</h3>
Sets the ADC IQ sample rats from 2M to 10.66M Hz.
<h3>17: Decimation</h3>
Decimation in powers of two from 1 (no decimation) to 64.
<h3>18: Decimated bandpass center frequency position relative the SDRplay center frequency</h3>
- **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.
<h3>19. RF gain setting</h3>
Sets the LNA and mixer gain dB. The settings available depended upon the RSP device and frequency band.
<h3>20. IF AGC</h3>
Check this button to enable IF automatic gain control,
<h3>21. IF gain</h3>
Manual IF gain from 0 to -59 dB. Only enabled when IF AGC is disabled.
@@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QDebug>
#include <QMessageBox>
#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();
}
@@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3GUI_H_
#define PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3GUI_H_
#include <device/devicegui.h>
#include <QTimer>
#include <QWidget>
#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_ */
@@ -0,0 +1,799 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SDRPlayV3Gui</class>
<widget class="QWidget" name="SDRPlayV3Gui">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>317</width>
<height>260</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>260</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>SDRPlayV3</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_freq">
<property name="topMargin">
<number>4</number>
</property>
<item>
<layout class="QVBoxLayout" name="deviceUILayout">
<item>
<layout class="QHBoxLayout" name="deviceButtonsLayout">
<item>
<widget class="ButtonSwitch" name="startStop">
<property name="toolTip">
<string>start/stop acquisition</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/play.png</normaloff>
<normalon>:/stop.png</normalon>:/play.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="deviceRateLayout">
<item>
<widget class="QLabel" name="deviceRateText">
<property name="toolTip">
<string>I/Q sample rate kS/s</string>
</property>
<property name="text">
<string>00000k</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="freqLeftSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="ValueDial" name="centerFrequency" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>16</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Mono</family>
<pointsize>20</pointsize>
</font>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>Tuner center frequency in kHz</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="freqUnits">
<property name="text">
<string> kHz</string>
</property>
</widget>
</item>
<item>
<spacer name="freqRightlSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_ppm">
<property name="spacing">
<number>3</number>
</property>
<item row="0" column="2">
<widget class="QLabel" name="ppmText">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="ppmLabel">
<property name="text">
<string>LO ppm</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSlider" name="ppm">
<property name="toolTip">
<string>Local Oscillator ppm correction</string>
</property>
<property name="minimum">
<number>-200</number>
</property>
<property name="maximum">
<number>200</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="Line" name="line_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="inputLayout">
<item>
<widget class="QLabel" name="tunerLabel">
<property name="text">
<string>Tuner</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="tuner">
<property name="toolTip">
<string>Tuner</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="antennaLabel">
<property name="text">
<string>Ant</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="antenna">
<property name="toolTip">
<string>Antenna port</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_corr">
<item row="1" column="0">
<widget class="QLabel" name="corrLabel">
<property name="text">
<string>Auto</string>
</property>
</widget>
</item>
<item row="1" column="10">
<widget class="ButtonSwitch" name="dabNotch">
<property name="toolTip">
<string>Enable DAB notch filter</string>
</property>
<property name="text">
<string>DAB</string>
</property>
</widget>
</item>
<item row="1" column="7">
<widget class="ButtonSwitch" name="biasTee">
<property name="toolTip">
<string>Enable bias tee</string>
</property>
<property name="text">
<string>T</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="ButtonSwitch" name="iqImbalance">
<property name="toolTip">
<string>Automatic IQ imbalance correction</string>
</property>
<property name="text">
<string>IQ</string>
</property>
</widget>
</item>
<item row="1" column="5">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="ButtonSwitch" name="dcOffset">
<property name="toolTip">
<string>Automatic DC offset removal</string>
</property>
<property name="text">
<string>DC</string>
</property>
</widget>
</item>
<item row="1" column="9">
<widget class="ButtonSwitch" name="fmNotch">
<property name="toolTip">
<string>Enable MW/FM notch filter</string>
</property>
<property name="text">
<string>MW/FM</string>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="ButtonSwitch" name="extRef">
<property name="toolTip">
<string>Enable external reference clock output</string>
</property>
<property name="text">
<string>REF</string>
</property>
</widget>
</item>
<item row="1" column="8">
<widget class="ButtonSwitch" name="amNotch">
<property name="toolTip">
<string>Enable AM notch filter</string>
</property>
<property name="text">
<string>AM</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_freq">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_samplerate">
<property name="spacing">
<number>3</number>
</property>
<item row="0" column="4">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="bandwidth">
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>IF bandwidth in kHz</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="bandwidthLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>BW </string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="bandwidthUnit">
<property name="text">
<string>kHz</string>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QComboBox" name="ifFrequency">
<property name="toolTip">
<string>IF frequency in kHz</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QLabel" name="ifFrequencyLabel">
<property name="text">
<string>IF</string>
</property>
</widget>
</item>
<item row="0" column="7">
<widget class="QLabel" name="label">
<property name="text">
<string>kHz</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_decim" columnstretch="0,0,0,0,0,0,0,0,0">
<property name="spacing">
<number>3</number>
</property>
<item row="0" column="5">
<widget class="QComboBox" name="decim">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Decimation factor</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<item>
<property name="text">
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>2</string>
</property>
</item>
<item>
<property name="text">
<string>4</string>
</property>
</item>
<item>
<property name="text">
<string>8</string>
</property>
</item>
<item>
<property name="text">
<string>16</string>
</property>
</item>
<item>
<property name="text">
<string>32</string>
</property>
</item>
<item>
<property name="text">
<string>64</string>
</property>
</item>
</widget>
</item>
<item row="0" column="3">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="6">
<widget class="QLabel" name="label_fcPos">
<property name="text">
<string>Fp</string>
</property>
</widget>
</item>
<item row="0" column="8">
<spacer name="fcPosRightSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="7">
<widget class="QComboBox" name="fcPos">
<property name="toolTip">
<string>Relative position of device center frequency</string>
</property>
<item>
<property name="text">
<string>Inf</string>
</property>
</item>
<item>
<property name="text">
<string>Sup</string>
</property>
</item>
<item>
<property name="text">
<string>Cen</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="samplerateLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>SR</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_decim">
<property name="text">
<string>Dec</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="samplerateUnit">
<property name="text">
<string>S/s</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="ValueDial" name="samplerate" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>16</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Mono</family>
<pointsize>12</pointsize>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="toolTip">
<string>Sample rate</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_lna">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_gain">
<property name="spacing">
<number>3</number>
</property>
<item row="0" column="5">
<widget class="ButtonSwitch" name="gainIFAGC">
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Enable IF AGC</string>
</property>
<property name="text">
<string>IF AGC</string>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QLabel" name="gainIFLabel">
<property name="text">
<string>IF</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="0" column="7">
<widget class="QDial" name="gainIF">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>IF gain (dB)</string>
</property>
<property name="minimum">
<number>-59</number>
</property>
<property name="maximum">
<number>0</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="gainLabel">
<property name="text">
<string>Gain</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QComboBox" name="gainLNA">
<property name="toolTip">
<string>RF (LNA and mixer) gain in dB</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="gainLNALabel">
<property name="text">
<string>RF</string>
</property>
</widget>
</item>
<item row="0" column="8">
<widget class="QLabel" name="gainIFText">
<property name="toolTip">
<string>Baseband amplifier gain in dB</string>
</property>
<property name="text">
<string>00</string>
</property>
</widget>
</item>
<item row="0" column="9">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_vga1">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="padLayout">
<item>
<spacer name="verticalPadSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_vga2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ButtonSwitch</class>
<extends>QToolButton</extends>
<header>gui/buttonswitch.h</header>
</customwidget>
<customwidget>
<class>ValueDial</class>
<extends>QWidget</extends>
<header>gui/valuedial.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections/>
</ui>
File diff suppressed because it is too large Load Diff
@@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3INPUT_H_
#define PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3INPUT_H_
#include <stdint.h>
#include <QString>
#include <QByteArray>
#include <QNetworkRequest>
#include <sdrplay_api.h>
#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<QString>& 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_ */
@@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QtPlugin>
#include <sdrplay_api.h>
#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();
}
@@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3PLUGIN_H_
#define PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3PLUGIN_H_
#include <QObject>
#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_ */
@@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "sdrplayv3settings.h"
#include <QtGlobal>
#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;
}
}
@@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef _SDRPLAYV3_SDRPLAYV3SETTINGS_H_
#define _SDRPLAYV3_SDRPLAYV3SETTINGS_H_
#include <stdint.h>
#include <QByteArray>
#include <QString>
#include <QDebug>
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_ */
@@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <errno.h>
#include "sdrplayv3thread.h"
#include "dsp/samplesinkfifo.h"
#include <QDebug>
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);
}
@@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3THREAD_H_
#define PLUGINS_SAMPLESOURCE_SDRPLAYV3_SDRPLAYV3THREAD_H_
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <sdrplay_api.h>
#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<qint32, qint16, SDR_RX_SAMP_SZ, 16, true> 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_ */
@@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#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;
}
@@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#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;
};