1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-11-29 19:33:26 -05:00

Metis MISO: initial commit with 4 receivers

This commit is contained in:
f4exb 2020-09-05 10:41:14 +02:00
parent 4254d1fa5d
commit a180c552f8
37 changed files with 5569 additions and 2 deletions

View File

@ -35,3 +35,5 @@ endif()
if(ENABLE_SOAPYSDR AND SOAPYSDR_FOUND)
add_subdirectory(soapysdr)
endif()
add_subdirectory(metis)

View File

@ -0,0 +1,24 @@
project(metisdevice)
set(metisdevice_SOURCES
devicemetis.cpp
devicemetisscan.cpp
)
set(metisdevice_HEADERS
devicemetis.h
devicemetisscan.h
)
add_library(metisdevice SHARED
${metisdevice_SOURCES}
)
set_target_properties(metisdevice
PROPERTIES DEFINE_SYMBOL "devices_EXPORTS")
target_link_libraries(metisdevice
sdrbase
)
install(TARGETS metisdevice DESTINATION ${INSTALL_LIB_DIR})

View File

@ -0,0 +1,32 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 "devicemetis.h"
DeviceMetis::DeviceMetis()
{
}
DeviceMetis::~DeviceMetis()
{
}
DeviceMetis& DeviceMetis::instance()
{
static DeviceMetis inst;
return inst;
}

View File

@ -0,0 +1,42 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 DEVICES_METIS_DEVICEMETIS_H_
#define DEVICES_METIS_DEVICEMETIS_H_
#include "export.h"
#include "devicemetisscan.h"
class DEVICES_API DeviceMetis
{
public:
static DeviceMetis& instance();
void scan() { m_scan.scan(); }
void enumOriginDevices(const QString& hardwareId, PluginInterface::OriginDevices& originDevices) {
m_scan.enumOriginDevices(hardwareId, originDevices);
}
const DeviceMetisScan::DeviceScan* getDeviceScanAt(unsigned int index) const { return m_scan.getDeviceAt(index); }
protected:
DeviceMetis();
~DeviceMetis();
private:
DeviceMetisScan m_scan;
};
#endif // DEVICES_METIS_DEVICEMETIS_H_

View File

@ -0,0 +1,146 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 <QEventLoop>
#include <QTimer>
#include "devicemetisscan.h"
void DeviceMetisScan::scan()
{
m_scans.clear();
if (m_udpSocket.bind(QHostAddress::AnyIPv4, 10001, QUdpSocket::ShareAddress))
{
connect(&m_udpSocket, SIGNAL(readyRead()), this, SLOT(readyRead()));
}
else
{
qDebug() << "DeviceMetisScan::scan: cannot bind socket";
return;
}
unsigned char buffer[63];
buffer[0] = (unsigned char) 0xEF;
buffer[1] = (unsigned char) 0XFE;
buffer[2] = (unsigned char) 0x02;
std::fill(&buffer[3], &buffer[63], 0);
if (m_udpSocket.writeDatagram((const char*) buffer, sizeof(buffer), QHostAddress::Broadcast, 1024) < 0)
{
qDebug() << "DeviceMetisScan::scan: discovery writeDatagram failed " << m_udpSocket.errorString();
return;
}
else
{
qDebug() << "DeviceMetisScan::scan: discovery writeDatagram sent";
}
// wait for 1 second before returning
QEventLoop loop;
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), &loop, SLOT(quit()));
timer->start(500);
qDebug() << "DeviceMetisScan::scan: start 0.5 second timeout loop";
// Execute the event loop here and wait for the timeout to trigger
// which in turn will trigger event loop quit.
loop.exec();
disconnect(&m_udpSocket, SIGNAL(readyRead()), this, SLOT(readyRead()));
m_udpSocket.close();
}
void DeviceMetisScan::enumOriginDevices(const QString& hardwareId, PluginInterface::OriginDevices& originDevices)
{
scan();
for (int i = 0; i < m_scans.size(); i++)
{
const DeviceScan& deviceInfo = m_scans.at(i);
QString serial = QString("%1:%2_%3").arg(deviceInfo.m_address.toString()).arg(deviceInfo.m_port).arg(deviceInfo.m_serial);
QString displayableName(QString("Metis[%1] %2").arg(i).arg(serial));
originDevices.append(PluginInterface::OriginDevice(
displayableName,
hardwareId,
serial,
i, // sequence
4, // Nb Rx
1 // Nb Tx
));
}
}
const DeviceMetisScan::DeviceScan* DeviceMetisScan::getDeviceAt(unsigned int index) const
{
if (index < m_scans.size()) {
return &m_scans.at(index);
} else {
return nullptr;
}
}
void DeviceMetisScan::getSerials(QList<QString>& serials) const
{
for (int i = 0; i < m_scans.size(); i++) {
serials.append(m_scans.at(i).m_serial);
}
}
void DeviceMetisScan::readyRead()
{
QHostAddress metisAddress;
quint16 metisPort;
unsigned char buffer[1024];
if (m_udpSocket.readDatagram((char*) &buffer, (qint64) sizeof(buffer), &metisAddress, &metisPort) < 0)
{
qDebug() << "DeviceMetisScan::readyRead: readDatagram failed " << m_udpSocket.errorString();
return;
}
QString metisIP = QString("%1:%2").arg(metisAddress.toString()).arg(metisPort);
if (buffer[0] == 0xEF && buffer[1] == 0xFE)
{
switch(buffer[2])
{
case 3: // reply
// should not happen on this port
break;
case 2: // response to a discovery packet
{
QByteArray array((char *) &buffer[3], 6);
QString serial = QString(array.toHex());
m_scans.append(DeviceScan(
serial,
metisAddress,
metisPort
));
m_serialMap.insert(serial, &m_scans.back());
qDebug() << "DeviceMetisScan::readyRead: found Metis at:" << metisIP << "MAC:" << serial;
}
break;
case 1: // a data packet
break;
}
}
else
{
qDebug() << "DeviceMetisScan::readyRead: received invalid response to discovery";
}
}

View File

@ -0,0 +1,71 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 DEVICES_METIS_DEVICEMETISSCAN_H_
#define DEVICES_METIS_DEVICEMETISSCAN_H_
#include <QObject>
#include <QString>
#include <QUdpSocket>
#include <QList>
#include <QMap>
#include <string>
#include <vector>
#include <map>
#include "plugin/plugininterface.h"
#include "export.h"
class DEVICES_API DeviceMetisScan : public QObject
{
Q_OBJECT
public:
struct DeviceScan
{
QString m_serial;
QHostAddress m_address;
quint16 m_port;
DeviceScan(
const QString& serial,
const QHostAddress& address,
quint16 port
) :
m_serial(serial),
m_address(address),
m_port(port)
{}
};
void scan();
int getNbDevices() const { return m_scans.size(); }
const DeviceScan* getDeviceAt(unsigned int index) const;
void getSerials(QList<QString>& serials) const;
void enumOriginDevices(const QString& hardwareId, PluginInterface::OriginDevices& originDevices);
public slots:
void readyRead();
private:
QUdpSocket m_udpSocket;
QList<DeviceScan> m_scans;
QMap<QString, DeviceScan*> m_serialMap;
};
#endif /* DEVICES_METIS_DEVICEMETISSCAN_H_ */

View File

@ -12,5 +12,6 @@ if(ENABLE_XTRX AND LIBXTRX_FOUND)
add_subdirectory(xtrxmimo)
endif()
add_subdirectory(metismiso)
add_subdirectory(testmi)
add_subdirectory(testmosync)

View File

@ -0,0 +1,60 @@
project(metismiso)
set(metismiso_SOURCES
metismiso.cpp
metismisoplugin.cpp
metismisoudphandler.cpp
metismisosettings.cpp
metismisowebapiadapter.cpp
metismisodecimators.cpp
)
set(metismiso_HEADERS
metismiso.h
metismisoplugin.h
metismisoudphandler.h
metismisosettings.h
metismisowebapiadapter.h
metismisodecimators.h
)
include_directories(
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
${CMAKE_SOURCE_DIR}/devices
)
if (NOT SERVER_MODE)
set (metismiso_SOURCES
${metismiso_SOURCES}
metismisogui.cpp
metismisogui.ui
)
set(metismiso_HEADERS
${metismiso_HEADERS}
metismisogui.h
)
set(TARGET_NAME mimometismiso)
set(TARGET_LIB "Qt5::Widgets")
set(TARGET_LIB_GUI "sdrgui")
set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR})
else()
set(TARGET_NAME mimometismisosrv)
set(TARGET_LIB "")
set(TARGET_LIB_GUI "")
set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR})
endif()
add_library(${TARGET_NAME} SHARED
${metismiso_SOURCES}
)
target_link_libraries(${TARGET_NAME}
Qt5::Core
${TARGET_LIB}
sdrbase
${TARGET_LIB_GUI}
swagger
metisdevice
)
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})

View File

@ -0,0 +1,706 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 <QNetworkAccessManager>
#include <QBuffer>
#include "SWGDeviceSettings.h"
#include "SWGDeviceState.h"
#include "SWGMetisMISOSettings.h"
#include "device/deviceapi.h"
#include "dsp/dspcommands.h"
#include "dsp/dspengine.h"
#include "dsp/dspdevicemimoengine.h"
#include "dsp/devicesamplesource.h"
#include "metis/devicemetis.h"
#include "metismisoudphandler.h"
#include "metismiso.h"
MESSAGE_CLASS_DEFINITION(MetisMISO::MsgConfigureMetisMISO, Message)
MESSAGE_CLASS_DEFINITION(MetisMISO::MsgStartStop, Message)
MetisMISO::MetisMISO(DeviceAPI *deviceAPI) :
m_deviceAPI(deviceAPI),
m_settings(),
m_udpHandler(&m_sampleMIFifo, deviceAPI),
m_deviceDescription("MetisMISO"),
m_running(false),
m_masterTimer(deviceAPI->getMasterTimer())
{
m_mimoType = MIMOHalfSynchronous;
m_sampleMIFifo.init(4, 96000 * 4);
m_deviceAPI->setNbSourceStreams(4);
m_deviceAPI->setNbSinkStreams(1);
int deviceSequence = m_deviceAPI->getSamplingDeviceSequence();
const DeviceMetisScan::DeviceScan *deviceScan = DeviceMetis::instance().getDeviceScanAt(deviceSequence);
m_udpHandler.setMetisAddress(deviceScan->m_address, deviceScan->m_port);
m_networkManager = new QNetworkAccessManager();
connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
}
MetisMISO::~MetisMISO()
{
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
delete m_networkManager;
if (m_running) {
stopRx();
}
}
void MetisMISO::destroy()
{
delete this;
}
void MetisMISO::init()
{
applySettings(m_settings, true);
}
bool MetisMISO::startRx()
{
qDebug("MetisMISO::startRx");
QMutexLocker mutexLocker(&m_mutex);
if (!m_running) {
startMetis();
}
mutexLocker.unlock();
applySettings(m_settings, true);
m_running = true;
return true;
}
bool MetisMISO::startTx()
{
qDebug("MetisMISO::startTx");
QMutexLocker mutexLocker(&m_mutex);
if (!m_running) {
startMetis();
}
mutexLocker.unlock();
applySettings(m_settings, true);
m_running = true;
return true;
}
void MetisMISO::stopRx()
{
qDebug("MetisMISO::stopRx");
QMutexLocker mutexLocker(&m_mutex);
if (m_running) {
stopMetis();
}
m_running = false;
}
void MetisMISO::stopTx()
{
qDebug("MetisMISO::stopTx");
QMutexLocker mutexLocker(&m_mutex);
if (m_running) {
stopMetis();
}
m_running = false;
}
void MetisMISO::startMetis()
{
MetisMISOUDPHandler::MsgStartStop *message = MetisMISOUDPHandler::MsgStartStop::create(true);
m_udpHandler.getInputMessageQueue()->push(message);
}
void MetisMISO::stopMetis()
{
MetisMISOUDPHandler::MsgStartStop *message = MetisMISOUDPHandler::MsgStartStop::create(false);
m_udpHandler.getInputMessageQueue()->push(message);
}
QByteArray MetisMISO::serialize() const
{
return m_settings.serialize();
}
bool MetisMISO::deserialize(const QByteArray& data)
{
bool success = true;
if (!m_settings.deserialize(data))
{
m_settings.resetToDefaults();
success = false;
}
MsgConfigureMetisMISO* message = MsgConfigureMetisMISO::create(m_settings, true);
m_inputMessageQueue.push(message);
if (m_guiMessageQueue)
{
MsgConfigureMetisMISO* messageToGUI = MsgConfigureMetisMISO::create(m_settings, true);
m_guiMessageQueue->push(messageToGUI);
}
return success;
}
const QString& MetisMISO::getDeviceDescription() const
{
return m_deviceDescription;
}
int MetisMISO::getSourceSampleRate(int index) const
{
if (index < 3) {
return MetisMISOSettings::getSampleRateFromIndex(m_settings.m_sampleRateIndex);
} else {
return 0;
}
}
quint64 MetisMISO::getSourceCenterFrequency(int index) const
{
switch(index)
{
case 0:
return m_settings.m_rx1CenterFrequency;
break;
case 1:
return m_settings.m_rx2CenterFrequency;
break;
default:
return 0;
}
}
void MetisMISO::setSourceCenterFrequency(qint64 centerFrequency, int index)
{
MetisMISOSettings settings = m_settings; // note: calls copy constructor
if (index < 2)
{
if (index == 0) {
settings.m_rx1CenterFrequency = centerFrequency;
} else {
settings.m_rx2CenterFrequency = centerFrequency;
}
MsgConfigureMetisMISO* message = MsgConfigureMetisMISO::create(settings, false);
m_inputMessageQueue.push(message);
if (m_guiMessageQueue)
{
MsgConfigureMetisMISO* messageToGUI = MsgConfigureMetisMISO::create(settings, false);
m_guiMessageQueue->push(messageToGUI);
}
}
}
bool MetisMISO::handleMessage(const Message& message)
{
if (MsgConfigureMetisMISO::match(message))
{
MsgConfigureMetisMISO& conf = (MsgConfigureMetisMISO&) message;
qDebug() << "MetisMISO::handleMessage: MsgConfigureMetisMISO";
bool success = applySettings(conf.getSettings(), conf.getForce());
if (!success)
{
qDebug("MetisMISO::handleMessage: config error");
}
return true;
}
else if (MsgStartStop::match(message))
{
MsgStartStop& cmd = (MsgStartStop&) message;
qDebug() << "MetisMISO::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
if (cmd.getStartStop())
{
if (m_deviceAPI->initDeviceEngine())
{
m_deviceAPI->startDeviceEngine();
}
}
else
{
m_deviceAPI->stopDeviceEngine();
}
if (m_settings.m_useReverseAPI) {
webapiReverseSendStartStop(cmd.getStartStop());
}
return true;
}
else
{
return false;
}
}
bool MetisMISO::applySettings(const MetisMISOSettings& settings, bool force)
{
QList<QString> reverseAPIKeys;
qDebug() << "MetisMISO::applySettings: "
<< " m_nbReceivers:" << settings.m_nbReceivers
<< " m_rx1CenterFrequency:" << settings.m_rx1CenterFrequency
<< " m_rx2CenterFrequency:" << settings.m_rx2CenterFrequency
<< " m_rx3CenterFrequency:" << settings.m_rx3CenterFrequency
<< " m_rx3CenterFrequency:" << settings.m_rx4CenterFrequency
<< " m_txCenterFrequency:" << settings.m_txCenterFrequency
<< " m_sampleRateIndex:" << settings.m_sampleRateIndex
<< " m_log2Decim:" << settings.m_log2Decim
<< " m_preamp:" << settings.m_preamp
<< " m_random:" << settings.m_random
<< " m_dither:" << settings.m_dither
<< " m_duplex:" << settings.m_duplex
<< " m_dcBlock:" << settings.m_dcBlock
<< " m_iqCorrection:" << settings.m_iqCorrection
<< " m_useReverseAPI: " << settings.m_useReverseAPI
<< " m_reverseAPIAddress: " << settings.m_reverseAPIAddress
<< " m_reverseAPIPort: " << settings.m_reverseAPIPort
<< " m_reverseAPIDeviceIndex: " << settings.m_reverseAPIDeviceIndex;
bool propagateSettings = false;
if ((m_settings.m_nbReceivers != settings.m_nbReceivers) || force)
{
reverseAPIKeys.append("nbReceivers");
propagateSettings = true;
}
if ((m_settings.m_rx1CenterFrequency != settings.m_rx1CenterFrequency) || force)
{
reverseAPIKeys.append("rx1CenterFrequency");
propagateSettings = true;
}
if ((m_settings.m_rx2CenterFrequency != settings.m_rx2CenterFrequency) || force)
{
reverseAPIKeys.append("rx2CenterFrequency");
propagateSettings = true;
}
if ((m_settings.m_rx3CenterFrequency != settings.m_rx3CenterFrequency) || force)
{
reverseAPIKeys.append("rx3CenterFrequency");
propagateSettings = true;
}
if ((m_settings.m_rx4CenterFrequency != settings.m_rx4CenterFrequency) || force)
{
reverseAPIKeys.append("rx4CenterFrequency");
propagateSettings = true;
}
if ((m_settings.m_txCenterFrequency != settings.m_txCenterFrequency) || force)
{
reverseAPIKeys.append("txCenterFrequency");
propagateSettings = true;
}
if ((m_settings.m_sampleRateIndex != settings.m_sampleRateIndex) || force)
{
reverseAPIKeys.append("sampleRateIndex");
propagateSettings = true;
}
if ((m_settings.m_log2Decim != settings.m_log2Decim) || force)
{
reverseAPIKeys.append("log2Decim");
propagateSettings = true;
}
if ((m_settings.m_dcBlock != settings.m_dcBlock) || force) {
reverseAPIKeys.append("dcBlock");
}
if ((m_settings.m_iqCorrection != settings.m_iqCorrection) || force) {
reverseAPIKeys.append("iqCorrection");
}
if ((m_settings.m_dcBlock != settings.m_dcBlock) ||
(m_settings.m_iqCorrection != settings.m_iqCorrection) || force)
{
m_deviceAPI->configureCorrections(settings.m_dcBlock, settings.m_iqCorrection, 0);
m_deviceAPI->configureCorrections(settings.m_dcBlock, settings.m_iqCorrection, 1);
}
if ((m_settings.m_rx1CenterFrequency != settings.m_rx1CenterFrequency) ||
(m_settings.m_sampleRateIndex != settings.m_sampleRateIndex) ||
(m_settings.m_log2Decim != settings.m_log2Decim) || force)
{
int devSampleRate = (1<<settings.m_sampleRateIndex) * 48000;
int sampleRate = devSampleRate / (1<<settings.m_log2Decim);
DSPMIMOSignalNotification *engineRx1Notif = new DSPMIMOSignalNotification(
sampleRate, settings.m_rx1CenterFrequency, true, 0);
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(engineRx1Notif);
}
if ((m_settings.m_rx2CenterFrequency != settings.m_rx2CenterFrequency) ||
(m_settings.m_sampleRateIndex != settings.m_sampleRateIndex) ||
(m_settings.m_log2Decim != settings.m_log2Decim) || force)
{
int devSampleRate = (1<<settings.m_sampleRateIndex) * 48000;
int sampleRate = devSampleRate / (1<<settings.m_log2Decim);
DSPMIMOSignalNotification *engineRx2Notif = new DSPMIMOSignalNotification(
sampleRate, settings.m_rx2CenterFrequency, true, 1);
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(engineRx2Notif);
}
if ((m_settings.m_rx3CenterFrequency != settings.m_rx3CenterFrequency) ||
(m_settings.m_sampleRateIndex != settings.m_sampleRateIndex) ||
(m_settings.m_log2Decim != settings.m_log2Decim) || force)
{
int devSampleRate = (1<<settings.m_sampleRateIndex) * 48000;
int sampleRate = devSampleRate / (1<<settings.m_log2Decim);
DSPMIMOSignalNotification *engineRx3Notif = new DSPMIMOSignalNotification(
sampleRate, settings.m_rx3CenterFrequency, true, 2);
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(engineRx3Notif);
}
if ((m_settings.m_rx4CenterFrequency != settings.m_rx4CenterFrequency) ||
(m_settings.m_sampleRateIndex != settings.m_sampleRateIndex) ||
(m_settings.m_log2Decim != settings.m_log2Decim) || force)
{
int devSampleRate = (1<<settings.m_sampleRateIndex) * 48000;
int sampleRate = devSampleRate / (1<<settings.m_log2Decim);
DSPMIMOSignalNotification *engineRx4Notif = new DSPMIMOSignalNotification(
sampleRate, settings.m_rx4CenterFrequency, true, 3);
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(engineRx4Notif);
}
if ((m_settings.m_txCenterFrequency != settings.m_txCenterFrequency) ||
(m_settings.m_sampleRateIndex != settings.m_sampleRateIndex) ||
(m_settings.m_log2Decim != settings.m_log2Decim) || force)
{
int devSampleRate = (1<<settings.m_sampleRateIndex) * 48000;
int sampleRate = devSampleRate / (1<<settings.m_log2Decim);
DSPMIMOSignalNotification *engineTxNotif = new DSPMIMOSignalNotification(
sampleRate, settings.m_txCenterFrequency, false, 0);
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(engineTxNotif);
}
if (propagateSettings) {
m_udpHandler.applySettings(settings);
}
if (settings.m_useReverseAPI)
{
qDebug("MetisMISO::applySettings: call webapiReverseSendSettings");
bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
(m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) ||
(m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) ||
(m_settings.m_reverseAPIDeviceIndex != settings.m_reverseAPIDeviceIndex);
webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
}
m_settings = settings;
return true;
}
int MetisMISO::webapiRunGet(
int subsystemIndex,
SWGSDRangel::SWGDeviceState& response,
QString& errorMessage)
{
if (subsystemIndex == 0)
{
m_deviceAPI->getDeviceEngineStateStr(*response.getState()); // Rx only
return 200;
}
else
{
errorMessage = QString("Subsystem index invalid: expect 0 (Rx) only");
return 404;
}
}
int MetisMISO::webapiRun(
bool run,
int subsystemIndex,
SWGSDRangel::SWGDeviceState& response,
QString& errorMessage)
{
if (subsystemIndex == 0)
{
m_deviceAPI->getDeviceEngineStateStr(*response.getState()); // Rx only
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;
}
else
{
errorMessage = QString("Subsystem index invalid: expect 0 (Rx) only");
return 404;
}
}
int MetisMISO::webapiSettingsGet(
SWGSDRangel::SWGDeviceSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setMetisMisoSettings(new SWGSDRangel::SWGMetisMISOSettings());
response.getMetisMisoSettings()->init();
webapiFormatDeviceSettings(response, m_settings);
return 200;
}
int MetisMISO::webapiSettingsPutPatch(
bool force,
const QStringList& deviceSettingsKeys,
SWGSDRangel::SWGDeviceSettings& response, // query + response
QString& errorMessage)
{
(void) errorMessage;
MetisMISOSettings settings = m_settings;
webapiUpdateDeviceSettings(settings, deviceSettingsKeys, response);
MsgConfigureMetisMISO *msg = MsgConfigureMetisMISO::create(settings, force);
m_inputMessageQueue.push(msg);
if (m_guiMessageQueue) // forward to GUI if any
{
MsgConfigureMetisMISO *msgToGUI = MsgConfigureMetisMISO::create(settings, force);
m_guiMessageQueue->push(msgToGUI);
}
webapiFormatDeviceSettings(response, settings);
return 200;
}
void MetisMISO::webapiUpdateDeviceSettings(
MetisMISOSettings& settings,
const QStringList& deviceSettingsKeys,
SWGSDRangel::SWGDeviceSettings& response)
{
if (deviceSettingsKeys.contains("rx1CenterFrequency")) {
settings.m_rx1CenterFrequency = response.getMetisMisoSettings()->getRx1CenterFrequency();
}
if (deviceSettingsKeys.contains("rx2CenterFrequency")) {
settings.m_rx2CenterFrequency = response.getMetisMisoSettings()->getRx2CenterFrequency();
}
if (deviceSettingsKeys.contains("rx3CenterFrequency")) {
settings.m_rx3CenterFrequency = response.getMetisMisoSettings()->getRx3CenterFrequency();
}
if (deviceSettingsKeys.contains("txCenterFrequency")) {
settings.m_txCenterFrequency = response.getMetisMisoSettings()->getTxCenterFrequency();
}
if (deviceSettingsKeys.contains("sampleRateIndex")) {
settings.m_sampleRateIndex = response.getMetisMisoSettings()->getSampleRateIndex();
}
if (deviceSettingsKeys.contains("preamp")) {
settings.m_preamp = response.getMetisMisoSettings()->getPreamp() != 0;
}
if (deviceSettingsKeys.contains("random")) {
settings.m_random = response.getMetisMisoSettings()->getRandom() != 0;
}
if (deviceSettingsKeys.contains("dither")) {
settings.m_dither = response.getMetisMisoSettings()->getDither() != 0;
}
if (deviceSettingsKeys.contains("duplex")) {
settings.m_duplex = response.getMetisMisoSettings()->getDuplex() != 0;
}
if (deviceSettingsKeys.contains("dcBlock")) {
settings.m_dcBlock = response.getMetisMisoSettings()->getDcBlock() != 0;
}
if (deviceSettingsKeys.contains("iqCorrection")) {
settings.m_iqCorrection = response.getMetisMisoSettings()->getIqCorrection() != 0;
}
if (deviceSettingsKeys.contains("useReverseAPI")) {
settings.m_useReverseAPI = response.getMetisMisoSettings()->getUseReverseApi() != 0;
}
if (deviceSettingsKeys.contains("reverseAPIAddress")) {
settings.m_reverseAPIAddress = *response.getMetisMisoSettings()->getReverseApiAddress();
}
if (deviceSettingsKeys.contains("reverseAPIPort")) {
settings.m_reverseAPIPort = response.getMetisMisoSettings()->getReverseApiPort();
}
if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) {
settings.m_reverseAPIDeviceIndex = response.getMetisMisoSettings()->getReverseApiDeviceIndex();
}
}
void MetisMISO::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const MetisMISOSettings& settings)
{
response.getMetisMisoSettings()->setRx1CenterFrequency(settings.m_rx1CenterFrequency);
response.getMetisMisoSettings()->setRx2CenterFrequency(settings.m_rx2CenterFrequency);
response.getMetisMisoSettings()->setRx3CenterFrequency(settings.m_rx3CenterFrequency);
response.getMetisMisoSettings()->setTxCenterFrequency(settings.m_txCenterFrequency);
response.getMetisMisoSettings()->setSampleRateIndex(settings.m_sampleRateIndex);
response.getMetisMisoSettings()->setPreamp(settings.m_preamp ? 1 : 0);
response.getMetisMisoSettings()->setRandom(settings.m_random ? 1 : 0);
response.getMetisMisoSettings()->setDither(settings.m_dither ? 1 : 0);
response.getMetisMisoSettings()->setDuplex(settings.m_duplex ? 1 : 0);
response.getMetisMisoSettings()->setDcBlock(settings.m_dcBlock ? 1 : 0);
response.getMetisMisoSettings()->setIqCorrection(settings.m_iqCorrection ? 1 : 0);
response.getMetisMisoSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
if (response.getMetisMisoSettings()->getReverseApiAddress()) {
*response.getMetisMisoSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress;
} else {
response.getMetisMisoSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
}
response.getMetisMisoSettings()->setReverseApiPort(settings.m_reverseAPIPort);
response.getMetisMisoSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex);
}
void MetisMISO::webapiReverseSendSettings(const QList<QString>& deviceSettingsKeys, const MetisMISOSettings& settings, bool force)
{
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
swgDeviceSettings->setDirection(2); // MIMO
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
swgDeviceSettings->setDeviceHwType(new QString("MetisMISO"));
swgDeviceSettings->setMetisMisoSettings(new SWGSDRangel::SWGMetisMISOSettings());
SWGSDRangel::SWGMetisMISOSettings *swgMetisMISOSettings = swgDeviceSettings->getMetisMisoSettings();
if (deviceSettingsKeys.contains("rx1CenterFrequency") || force) {
swgMetisMISOSettings->setRx1CenterFrequency(settings.m_rx1CenterFrequency);
}
if (deviceSettingsKeys.contains("rx2CenterFrequency") || force) {
swgMetisMISOSettings->setRx2CenterFrequency(settings.m_rx2CenterFrequency);
}
if (deviceSettingsKeys.contains("rx3CenterFrequency") || force) {
swgMetisMISOSettings->setRx3CenterFrequency(settings.m_rx3CenterFrequency);
}
if (deviceSettingsKeys.contains("txCenterFrequency") || force) {
swgMetisMISOSettings->setTxCenterFrequency(settings.m_txCenterFrequency);
}
if (deviceSettingsKeys.contains("sampleRateIndex") || force) {
swgMetisMISOSettings->setSampleRateIndex(settings.m_sampleRateIndex);
}
if (deviceSettingsKeys.contains("preamp") || force) {
swgMetisMISOSettings->setPreamp(settings.m_preamp ? 1 : 0);
}
if (deviceSettingsKeys.contains("random") || force) {
swgMetisMISOSettings->setRandom(settings.m_random ? 1 : 0);
}
if (deviceSettingsKeys.contains("dither") || force) {
swgMetisMISOSettings->setDither(settings.m_dither ? 1 : 0);
}
if (deviceSettingsKeys.contains("duplex") || force) {
swgMetisMISOSettings->setDuplex(settings.m_duplex ? 1 : 0);
}
if (deviceSettingsKeys.contains("dcBlock") || force) {
swgMetisMISOSettings->setDcBlock(settings.m_dcBlock ? 1 : 0);
}
if (deviceSettingsKeys.contains("iqCorrection") || force) {
swgMetisMISOSettings->setIqCorrection(settings.m_iqCorrection ? 1 : 0);
}
QString channelSettingsURL = 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(channelSettingsURL));
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 MetisMISO::webapiReverseSendStartStop(bool start)
{
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
swgDeviceSettings->setDirection(2); // MIMO
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
swgDeviceSettings->setDeviceHwType(new QString("MetisMISO"));
QString channelSettingsURL = 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(channelSettingsURL));
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 MetisMISO::networkManagerFinished(QNetworkReply *reply)
{
QNetworkReply::NetworkError replyError = reply->error();
if (replyError)
{
qWarning() << "MetisMISO::networkManagerFinished:"
<< " error(" << (int) replyError
<< "): " << replyError
<< ": " << reply->errorString();
}
else
{
QString answer = reply->readAll();
answer.chop(1); // remove last \n
qDebug("MetisMISO::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
}
reply->deleteLater();
}

View File

@ -0,0 +1,169 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 _METISMISO_METISMISO_H_
#define _METISMISO_METISMISO_H_
#include <QString>
#include <QByteArray>
#include <QTimer>
#include <QNetworkRequest>
#include <QThread>
#include "dsp/devicesamplemimo.h"
#include "metismisoudphandler.h"
#include "metismisosettings.h"
class DeviceAPI;
class MetisMISOWorker;
class QNetworkAccessManager;
class QNetworkReply;
class MetisMISO : public DeviceSampleMIMO {
Q_OBJECT
public:
class MsgConfigureMetisMISO : public Message {
MESSAGE_CLASS_DECLARATION
public:
const MetisMISOSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureMetisMISO* create(const MetisMISOSettings& settings, bool force)
{
return new MsgConfigureMetisMISO(settings, force);
}
private:
MetisMISOSettings m_settings;
bool m_force;
MsgConfigureMetisMISO(const MetisMISOSettings& 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)
{ }
};
MetisMISO(DeviceAPI *deviceAPI);
virtual ~MetisMISO();
virtual void destroy();
virtual void init();
virtual bool startRx();
virtual void stopRx();
virtual bool startTx();
virtual void stopTx();
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 getSourceSampleRate(int index) const;
virtual void setSourceSampleRate(int sampleRate, int index) { (void) sampleRate; (void) index; }
virtual quint64 getSourceCenterFrequency(int index) const;
virtual void setSourceCenterFrequency(qint64 centerFrequency, int index);
virtual int getSinkSampleRate(int index) const { return 0; (void) index; }
virtual void setSinkSampleRate(int sampleRate, int index) { (void) sampleRate; (void) index; }
virtual quint64 getSinkCenterFrequency(int index) const { return 0; (void) index; }
virtual void setSinkCenterFrequency(qint64 centerFrequency, int index) { (void) centerFrequency; (void) index; }
virtual quint64 getMIMOCenterFrequency() const { return getSourceCenterFrequency(0); }
virtual unsigned int getMIMOSampleRate() const { return getSourceSampleRate(0); }
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 webapiRunGet(
int subsystemIndex,
SWGSDRangel::SWGDeviceState& response,
QString& errorMessage);
virtual int webapiRun(
bool run,
int subsystemIndex,
SWGSDRangel::SWGDeviceState& response,
QString& errorMessage);
static void webapiFormatDeviceSettings(
SWGSDRangel::SWGDeviceSettings& response,
const MetisMISOSettings& settings);
static void webapiUpdateDeviceSettings(
MetisMISOSettings& settings,
const QStringList& deviceSettingsKeys,
SWGSDRangel::SWGDeviceSettings& response);
private:
struct DeviceSettingsKeys
{
QList<QString> m_commonSettingsKeys;
QList<QList<QString>> m_streamsSettingsKeys;
};
DeviceAPI *m_deviceAPI;
QMutex m_mutex;
MetisMISOSettings m_settings;
MetisMISOUDPHandler m_udpHandler;
QString m_deviceDescription;
bool m_running;
const QTimer& m_masterTimer;
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
void startMetis();
void stopMetis();
bool applySettings(const MetisMISOSettings& settings, bool force);
void webapiReverseSendSettings(const QList<QString>& deviceSettingsKeys, const MetisMISOSettings& settings, bool force);
void webapiReverseSendStartStop(bool start);
private slots:
void networkManagerFinished(QNetworkReply *reply);
};
#endif // _METISMISO_METISMISO_H_

View File

@ -0,0 +1,85 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 "metismisodecimators.h"
MetisMISODecimators::MetisMISODecimators()
{
resetCounters();
m_wSampleVector.resize(1);
}
void MetisMISODecimators::resetCounters()
{
std::fill(m_counters, m_counters+MetisMISOSettings::m_maxReceivers, 0);
}
int MetisMISODecimators::decimate2(qint32 sampleI, qint32 sampleQ, SampleVector& result, unsigned int streamIndex)
{
if (streamIndex < MetisMISOSettings::m_maxReceivers)
{
m_accumulators[streamIndex][m_counters[streamIndex]++] = sampleI;
m_accumulators[streamIndex][m_counters[streamIndex]++] = sampleQ;
if (m_counters[streamIndex] >= 8)
{
SampleVector::iterator it = result.begin();
m_decimatorsIQ[streamIndex].decimate2_cen(&it, m_accumulators[streamIndex], 8);
m_counters[streamIndex] = 0;
return 2; // 2 samples available
}
}
return 0;
}
int MetisMISODecimators::decimate4(qint32 sampleI, qint32 sampleQ, SampleVector& result, unsigned int streamIndex)
{
if (streamIndex < MetisMISOSettings::m_maxReceivers)
{
m_accumulators[streamIndex][m_counters[streamIndex]++] = sampleI;
m_accumulators[streamIndex][m_counters[streamIndex]++] = sampleQ;
if (m_counters[streamIndex] >= 16)
{
SampleVector::iterator it = result.begin();
m_decimatorsIQ[streamIndex].decimate4_cen(&it, m_accumulators[streamIndex], 16);
m_counters[streamIndex] = 0;
return 2; // 2 samples available
}
}
return 0;
}
int MetisMISODecimators::decimate8(qint32 sampleI, qint32 sampleQ, SampleVector& result, unsigned int streamIndex)
{
if (streamIndex < MetisMISOSettings::m_maxReceivers)
{
m_accumulators[streamIndex][m_counters[streamIndex]++] = sampleI;
m_accumulators[streamIndex][m_counters[streamIndex]++] = sampleQ;
if (m_counters[streamIndex] >= 16)
{
SampleVector::iterator it = result.begin();
m_decimatorsIQ[streamIndex].decimate8_cen(&it, m_accumulators[streamIndex], 16);
m_counters[streamIndex] = 0;
return 1; // 1 sample available
}
}
return 0;
}

View File

@ -0,0 +1,47 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// Decimators adapters specific to Metis //
// //
// 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 _METISMISO_METISMISODECIMATORS_H_
#define _METISMISO_METISMISODECIMATORS_H_
#include "dsp/decimators.h"
#include "metismisosettings.h"
class MetisMISODecimators
{
public:
MetisMISODecimators();
int decimate2(qint32 sampleI, qint32 sampleQ, SampleVector& result, unsigned int streamIndex);
int decimate4(qint32 sampleI, qint32 sampleQ, SampleVector& result, unsigned int streamIndex);
int decimate8(qint32 sampleI, qint32 sampleQ, SampleVector& result, unsigned int streamIndex);
void resetCounters();
private:
qint32 m_accumulators[MetisMISOSettings::m_maxReceivers][256*2];
int m_counters[MetisMISOSettings::m_maxReceivers];
Decimators<qint32, qint32, SDR_RX_SAMP_SZ, 24, true> m_decimatorsIQ[MetisMISOSettings::m_maxReceivers];
Decimators<qint32, qint32, SDR_RX_SAMP_SZ, 24, false> m_decimatorsQI[MetisMISOSettings::m_maxReceivers];
SampleVector m_wSampleVector;
};
#endif // _METISMISO_METISMISODECIMATORS_H_

View File

@ -0,0 +1,517 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 <QTime>
#include <QDateTime>
#include <QString>
#include <QMessageBox>
#include <QFileDialog>
#include "plugin/pluginapi.h"
#include "device/deviceapi.h"
#include "device/deviceuiset.h"
#include "gui/colormapper.h"
#include "gui/glspectrum.h"
#include "gui/crightclickenabler.h"
#include "gui/basicdevicesettingsdialog.h"
#include "dsp/dspengine.h"
#include "dsp/dspdevicemimoengine.h"
#include "dsp/dspcommands.h"
#include "util/db.h"
#include "mainwindow.h"
#include "ui_metismisogui.h"
#include "metismisogui.h"
MetisMISOGui::MetisMISOGui(DeviceUISet *deviceUISet, QWidget* parent) :
QWidget(parent),
ui(new Ui::MetisMISOGui),
m_deviceUISet(deviceUISet),
m_settings(),
m_doApplySettings(true),
m_forceSettings(true),
m_sampleMIMO(nullptr),
m_tickCount(0),
m_lastEngineState(DeviceAPI::StNotStarted)
{
qDebug("MetisMISOGui::MetisMISOGui");
m_sampleMIMO = m_deviceUISet->m_deviceAPI->getSampleMIMO();
m_streamIndex = 0;
m_spectrumStreamIndex = 0;
m_rxSampleRate = 48000;
ui->setupUi(this);
ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->centerFrequency->setValueRange(7, 0, 61440000);
displaySettings();
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
m_statusTimer.start(500);
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
m_sampleMIMO->setMessageQueueToGUI(&m_inputMessageQueue);
CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop);
connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &)));
}
MetisMISOGui::~MetisMISOGui()
{
delete ui;
}
void MetisMISOGui::destroy()
{
delete this;
}
void MetisMISOGui::setName(const QString& name)
{
setObjectName(name);
}
QString MetisMISOGui::getName() const
{
return objectName();
}
void MetisMISOGui::resetToDefaults()
{
m_settings.resetToDefaults();
displaySettings();
sendSettings();
}
qint64 MetisMISOGui::getCenterFrequency() const
{
if (m_streamIndex == 0) {
return m_settings.m_rx1CenterFrequency;
} else if (m_streamIndex == 1) {
return m_settings.m_rx2CenterFrequency;
} else if (m_streamIndex == 2) {
return m_settings.m_rx3CenterFrequency;
} else if (m_streamIndex == 3) {
return m_settings.m_rx4CenterFrequency;
} else if (m_streamIndex == 4) {
return m_settings.m_txCenterFrequency;
} else {
return 0;
}
}
void MetisMISOGui::setCenterFrequency(qint64 centerFrequency)
{
if (m_streamIndex == 0) {
m_settings.m_rx1CenterFrequency = centerFrequency;
} else if (m_streamIndex == 1) {
m_settings.m_rx2CenterFrequency = centerFrequency;
} else if (m_streamIndex == 2) {
m_settings.m_rx3CenterFrequency = centerFrequency;
} else if (m_streamIndex == 3) {
m_settings.m_rx4CenterFrequency = centerFrequency;
} else if (m_streamIndex == 4) {
m_settings.m_txCenterFrequency = centerFrequency;
} else {
m_settings.m_txCenterFrequency = 0;
}
displaySettings();
sendSettings();
}
QByteArray MetisMISOGui::serialize() const
{
return m_settings.serialize();
}
bool MetisMISOGui::deserialize(const QByteArray& data)
{
if(m_settings.deserialize(data)) {
displaySettings();
m_forceSettings = true;
sendSettings();
return true;
} else {
resetToDefaults();
return false;
}
}
void MetisMISOGui::on_startStop_toggled(bool checked)
{
if (m_doApplySettings)
{
MetisMISO::MsgStartStop *message = MetisMISO::MsgStartStop::create(checked);
m_sampleMIMO->getInputMessageQueue()->push(message);
}
}
void MetisMISOGui::on_streamIndex_currentIndexChanged(int index)
{
if (ui->streamLock->isChecked())
{
m_spectrumStreamIndex = index;
if (m_spectrumStreamIndex < MetisMISOSettings::m_maxReceivers)
{
m_deviceUISet->m_spectrum->setDisplayedStream(true, index);
m_deviceUISet->m_deviceAPI->setSpectrumSinkInput(true, m_spectrumStreamIndex);
}
else
{
m_deviceUISet->m_spectrum->setDisplayedStream(false, 0);
m_deviceUISet->m_deviceAPI->setSpectrumSinkInput(false, 0);
}
ui->spectrumSource->blockSignals(true);
ui->spectrumSource->setCurrentIndex(index);
ui->spectrumSource->blockSignals(false);
}
m_streamIndex = index;
displayFrequency();
}
void MetisMISOGui::on_spectrumSource_currentIndexChanged(int index)
{
m_spectrumStreamIndex = index;
if (m_spectrumStreamIndex < MetisMISOSettings::m_maxReceivers)
{
m_deviceUISet->m_spectrum->setDisplayedStream(true, index);
m_deviceUISet->m_deviceAPI->setSpectrumSinkInput(true, m_spectrumStreamIndex);
}
else
{
m_deviceUISet->m_spectrum->setDisplayedStream(false, 0);
m_deviceUISet->m_deviceAPI->setSpectrumSinkInput(false, 0);
}
updateSpectrum();
if (ui->streamLock->isChecked())
{
ui->streamIndex->blockSignals(true);
ui->streamIndex->setCurrentIndex(index);
ui->streamIndex->blockSignals(false);
m_streamIndex = index;
displayFrequency();
}
}
void MetisMISOGui::on_streamLock_toggled(bool checked)
{
if (checked && (ui->streamIndex->currentIndex() != ui->spectrumSource->currentIndex())) {
ui->spectrumSource->setCurrentIndex(ui->streamIndex->currentIndex());
}
}
void MetisMISOGui::on_centerFrequency_changed(quint64 value)
{
if (m_streamIndex == 0) {
m_settings.m_rx1CenterFrequency = value * 1000;
} else if (m_streamIndex == 1) {
m_settings.m_rx2CenterFrequency = value * 1000;
} else if (m_streamIndex == 2) {
m_settings.m_rx3CenterFrequency = value * 1000;
} else if (m_streamIndex == 3) {
m_settings.m_rx4CenterFrequency = value * 1000;
} else if (m_streamIndex == 4) {
m_settings.m_txCenterFrequency = value * 1000;
} else {
m_settings.m_txCenterFrequency = 0;
}
sendSettings();
}
void MetisMISOGui::on_samplerateIndex_currentIndexChanged(int index)
{
m_settings.m_sampleRateIndex = index < 0 ? 0 : index > 3 ? 3 : index;
sendSettings();
}
void MetisMISOGui::on_log2Decim_currentIndexChanged(int index)
{
m_settings.m_log2Decim = index < 0 ? 0 : index > 3 ? 3 : index;
displaySampleRate();
sendSettings();
}
void MetisMISOGui::on_dcBlock_toggled(bool checked)
{
m_settings.m_dcBlock = checked;
sendSettings();
}
void MetisMISOGui::on_iqCorrection_toggled(bool checked)
{
m_settings.m_iqCorrection = checked;
sendSettings();
}
void MetisMISOGui::on_preamp_toggled(bool checked)
{
m_settings.m_preamp = checked;
sendSettings();
}
void MetisMISOGui::on_random_toggled(bool checked)
{
m_settings.m_random = checked;
sendSettings();
}
void MetisMISOGui::on_dither_toggled(bool checked)
{
m_settings.m_dither = checked;
sendSettings();
}
void MetisMISOGui::on_duplex_toggled(bool checked)
{
m_settings.m_duplex = checked;
sendSettings();
}
void MetisMISOGui::on_nbRxIndex_currentIndexChanged(int index)
{
m_settings.m_nbReceivers = index + 1;
sendSettings();
}
void MetisMISOGui::displaySettings()
{
blockApplySettings(true);
ui->streamIndex->setCurrentIndex(m_streamIndex);
ui->spectrumSource->setCurrentIndex(m_spectrumStreamIndex);
ui->nbRxIndex->setCurrentIndex(m_settings.m_nbReceivers - 1);
ui->samplerateIndex->setCurrentIndex(m_settings.m_sampleRateIndex);
ui->dcBlock->setChecked(m_settings.m_dcBlock);
ui->iqCorrection->setChecked(m_settings.m_iqCorrection);
ui->preamp->setChecked(m_settings.m_preamp);
ui->random->setChecked(m_settings.m_random);
ui->dither->setChecked(m_settings.m_dither);
ui->duplex->setChecked(m_settings.m_duplex);
displayFrequency();
displaySampleRate();
updateSpectrum();
blockApplySettings(false);
}
void MetisMISOGui::sendSettings()
{
if(!m_updateTimer.isActive()) {
m_updateTimer.start(100);
}
}
void MetisMISOGui::updateHardware()
{
if (m_doApplySettings)
{
MetisMISO::MsgConfigureMetisMISO* message = MetisMISO::MsgConfigureMetisMISO::create(m_settings, m_forceSettings);
m_sampleMIMO->getInputMessageQueue()->push(message);
m_forceSettings = false;
m_updateTimer.stop();
}
}
void MetisMISOGui::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;
}
}
bool MetisMISOGui::handleMessage(const Message& message)
{
if (MetisMISO::MsgConfigureMetisMISO::match(message))
{
qDebug("MetisMISOGui::handleMessage: MsgConfigureMetisMISO");
const MetisMISO::MsgConfigureMetisMISO& cfg = (MetisMISO::MsgConfigureMetisMISO&) message;
m_settings = cfg.getSettings();
displaySettings();
return true;
}
else if (MetisMISO::MsgStartStop::match(message))
{
qDebug("MetisMISOGui::handleMessage: MsgStartStop");
MetisMISO::MsgStartStop& notif = (MetisMISO::MsgStartStop&) message;
blockApplySettings(true);
ui->startStop->setChecked(notif.getStartStop());
blockApplySettings(false);
return true;
}
else
{
return false;
}
}
void MetisMISOGui::handleInputMessages()
{
Message* message;
while ((message = m_inputMessageQueue.pop()) != 0)
{
if (DSPMIMOSignalNotification::match(*message))
{
DSPMIMOSignalNotification* notif = (DSPMIMOSignalNotification*) message;
int istream = notif->getIndex();
bool sourceOrSink = notif->getSourceOrSink();
qint64 frequency = notif->getCenterFrequency();
if (sourceOrSink)
{
m_rxSampleRate = notif->getSampleRate();
if (istream == 0) {
m_settings.m_rx1CenterFrequency = frequency;
} else if (istream == 1) {
m_settings.m_rx2CenterFrequency = frequency;
} else if (istream == 2) {
m_settings.m_rx3CenterFrequency = frequency;
} else if (istream == 3) {
m_settings.m_rx4CenterFrequency = frequency;
}
}
else
{
m_settings.m_txCenterFrequency = frequency;
}
qDebug("MetisMISOGui::handleInputMessages: DSPMIMOSignalNotification: %s stream: %d m_rxSampleRate:%d, CenterFrequency:%llu",
sourceOrSink ? "source" : "sink",
istream,
m_rxSampleRate,
frequency);
displayFrequency();
updateSpectrum();
delete message;
}
else
{
if (handleMessage(*message))
{
delete message;
}
}
}
}
void MetisMISOGui::displayFrequency()
{
qint64 centerFrequency;
if (m_streamIndex == 0) {
centerFrequency = m_settings.m_rx1CenterFrequency;
} else if (m_streamIndex == 1) {
centerFrequency = m_settings.m_rx2CenterFrequency;
} else if (m_streamIndex == 2) {
centerFrequency = m_settings.m_rx3CenterFrequency;
} else if (m_streamIndex == 3) {
centerFrequency = m_settings.m_rx4CenterFrequency;
} else if (m_streamIndex == 4) {
centerFrequency = m_settings.m_txCenterFrequency;
} else {
centerFrequency = 0;
}
ui->centerFrequency->setValue(centerFrequency / 1000);
}
void MetisMISOGui::displaySampleRate()
{
int deviceSampleRate = 48000 * (1<<m_settings.m_sampleRateIndex);
int sampleRate = deviceSampleRate / (1<<m_settings.m_log2Decim);
ui->deviceRateText->setText(tr("%1k").arg((float) sampleRate / 1000));
}
void MetisMISOGui::updateSpectrum()
{
qint64 centerFrequency;
if (m_spectrumStreamIndex == 0) {
centerFrequency = m_settings.m_rx1CenterFrequency;
} else if (m_spectrumStreamIndex == 1) {
centerFrequency = m_settings.m_rx2CenterFrequency;
} else if (m_spectrumStreamIndex == 2) {
centerFrequency = m_settings.m_rx3CenterFrequency;
} else if (m_spectrumStreamIndex == 3) {
centerFrequency = m_settings.m_rx4CenterFrequency;
} else if (m_spectrumStreamIndex == 4) {
centerFrequency = m_settings.m_txCenterFrequency;
} else {
centerFrequency = 0;
}
m_deviceUISet->getSpectrum()->setSampleRate(m_rxSampleRate);
m_deviceUISet->getSpectrum()->setCenterFrequency(centerFrequency);
}
void MetisMISOGui::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();
}

View File

@ -0,0 +1,102 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 _METISMISO_METISMISOGUI_H_
#define _METISMISO_METISMISOGUI_H_
#include <plugin/plugininstancegui.h>
#include <QTimer>
#include <QWidget>
#include "util/messagequeue.h"
#include "metismisosettings.h"
#include "metismiso.h"
class DeviceUISet;
namespace Ui {
class MetisMISOGui;
}
class MetisMISOGui : public QWidget, public PluginInstanceGUI {
Q_OBJECT
public:
explicit MetisMISOGui(DeviceUISet *deviceUISet, QWidget* parent = 0);
virtual ~MetisMISOGui();
virtual void destroy();
void setName(const QString& name);
QString getName() const;
void resetToDefaults();
virtual qint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
virtual bool handleMessage(const Message& message);
private:
Ui::MetisMISOGui* ui;
DeviceUISet* m_deviceUISet;
MetisMISOSettings m_settings;
int m_streamIndex; //!< Current stream index being dealt with
int m_spectrumStreamIndex; //!< Index of the stream displayed on main spectrum
int m_rxSampleRate;
QTimer m_updateTimer;
QTimer m_statusTimer;
bool m_doApplySettings;
bool m_forceSettings;
DeviceSampleMIMO* m_sampleMIMO;
std::size_t m_tickCount;
std::vector<int> m_deviceSampleRates;
std::vector<quint64> m_deviceCenterFrequencies; //!< Center frequency in device
int m_lastEngineState;
MessageQueue m_inputMessageQueue;
void blockApplySettings(bool block) { m_doApplySettings = !block; }
void displaySettings();
void displayFrequency();
void displaySampleRate();
void updateSpectrum();
void sendSettings();
private slots:
void handleInputMessages();
void on_streamIndex_currentIndexChanged(int index);
void on_spectrumSource_currentIndexChanged(int index);
void on_streamLock_toggled(bool checked);
void on_startStop_toggled(bool checked);
void on_centerFrequency_changed(quint64 value);
void on_samplerateIndex_currentIndexChanged(int index);
void on_log2Decim_currentIndexChanged(int index);
void on_dcBlock_toggled(bool checked);
void on_iqCorrection_toggled(bool checked);
void on_preamp_toggled(bool checked);
void on_random_toggled(bool checked);
void on_dither_toggled(bool checked);
void on_duplex_toggled(bool checked);
void on_nbRxIndex_currentIndexChanged(int index);
void openDeviceSettingsDialog(const QPoint& p);
void updateStatus();
void updateHardware();
};
#endif // _METISMISO_METISMISOGUI_H_

View File

@ -0,0 +1,606 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MetisMISOGui</class>
<widget class="QWidget" name="MetisMISOGui">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>360</width>
<height>200</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>360</width>
<height>200</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="windowTitle">
<string>Metis MISO</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="streamLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Stream</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="streamIndex">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Select stream to which settings apply (frequency only)</string>
</property>
<item>
<property name="text">
<string>Rx0</string>
</property>
</item>
<item>
<property name="text">
<string>Rx1</string>
</property>
</item>
<item>
<property name="text">
<string>Rx2</string>
</property>
</item>
<item>
<property name="text">
<string>Rx3</string>
</property>
</item>
<item>
<property name="text">
<string>Tx</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="spectrumSourceLabel">
<property name="text">
<string>Spectrum</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="spectrumSource">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Select stream for main spectrum source</string>
</property>
<item>
<property name="text">
<string>Rx0</string>
</property>
</item>
<item>
<property name="text">
<string>Rx1</string>
</property>
</item>
<item>
<property name="text">
<string>Rx2</string>
</property>
</item>
<item>
<property name="text">
<string>Rx3</string>
</property>
</item>
<item>
<property name="text">
<string>Tx</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QToolButton" name="streamLock">
<property name="toolTip">
<string>Lock spectrum display to stream selection</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/unlocked.png</normaloff>
<normalon>:/locked.png</normalon>:/unlocked.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<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_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_freq">
<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="minimumSize">
<size>
<width>58</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>I/Q sample rate kS/s</string>
</property>
<property name="text">
<string>0000.00k</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer">
<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="horizontalSpacer_2">
<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>
<layout class="QHBoxLayout" name="autoCorrectionsLayout">
<item>
<widget class="QLabel" name="samplerateLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>16</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>SR</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="samplerateIndex">
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Modulation</string>
</property>
<item>
<property name="text">
<string>48k</string>
</property>
</item>
<item>
<property name="text">
<string>96k</string>
</property>
</item>
<item>
<property name="text">
<string>192k</string>
</property>
</item>
<item>
<property name="text">
<string>384k</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="decimationLabel">
<property name="text">
<string>Dec</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="log2Decim">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</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>
</widget>
</item>
<item>
<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>
<item>
<widget class="QLabel" name="autoCorrLabel">
<property name="text">
<string>Corr</string>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="dcBlock">
<property name="minimumSize">
<size>
<width>45</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>45</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>DC</string>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="iqCorrection">
<property name="minimumSize">
<size>
<width>45</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>45</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>IQ</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="switchesLayout">
<item>
<widget class="ButtonSwitch" name="preamp">
<property name="toolTip">
<string>Toggle preamplifier</string>
</property>
<property name="text">
<string>PRE</string>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="random">
<property name="toolTip">
<string>Toggle LT2208 Random</string>
</property>
<property name="text">
<string>RAN</string>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="dither">
<property name="toolTip">
<string>Toggle LT2208 Dither</string>
</property>
<property name="text">
<string>DITH</string>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="duplex">
<property name="toolTip">
<string>Toggle duplex</string>
</property>
<property name="text">
<string>DUP</string>
</property>
</widget>
</item>
<item>
<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>
<widget class="QLabel" name="nbRxLabel">
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>#Rx</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="nbRxIndex">
<property name="maximumSize">
<size>
<width>40</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Number of active receivers</string>
</property>
<item>
<property name="text">
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>2</string>
</property>
</item>
<item>
<property name="text">
<string>3</string>
</property>
</item>
<item>
<property name="text">
<string>4</string>
</property>
</item>
<item>
<property name="text">
<string>5</string>
</property>
</item>
<item>
<property name="text">
<string>6</string>
</property>
</item>
<item>
<property name="text">
<string>7</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<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>
</widget>
<customwidgets>
<customwidget>
<class>ValueDial</class>
<extends>QWidget</extends>
<header>gui/valuedial.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ButtonSwitch</class>
<extends>QToolButton</extends>
<header>gui/buttonswitch.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -0,0 +1,139 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 "plugin/pluginapi.h"
#include "metis/devicemetis.h"
#include "util/simpleserializer.h"
#ifdef SERVER_MODE
#include "metismiso.h"
#else
#include "metismisogui.h"
#endif
#include "metismisoplugin.h"
#include "metismisowebapiadapter.h"
const PluginDescriptor MetisMISOPlugin::m_pluginDescriptor = {
QString("MetisMISO"),
QString("Metis MISO"),
QString("5.10.0"),
QString("(c) Edouard Griffiths, F4EXB"),
QString("https://github.com/f4exb/sdrangel"),
true,
QString("https://github.com/f4exb/sdrangel")
};
const QString MetisMISOPlugin::m_hardwareID = "MetisMISO";
const QString MetisMISOPlugin::m_deviceTypeID = METISMISO_DEVICE_TYPE_ID;
MetisMISOPlugin::MetisMISOPlugin(QObject* parent) :
QObject(parent)
{
}
const PluginDescriptor& MetisMISOPlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void MetisMISOPlugin::initPlugin(PluginAPI* pluginAPI)
{
pluginAPI->registerSampleMIMO(m_deviceTypeID, this);
}
void MetisMISOPlugin::enumOriginDevices(QStringList& listedHwIds, OriginDevices& originDevices)
{
if (listedHwIds.contains(m_hardwareID)) { // check if it was done
return;
}
DeviceMetis::instance().enumOriginDevices(m_hardwareID, originDevices);
listedHwIds.append(m_hardwareID);
}
PluginInterface::SamplingDevices MetisMISOPlugin::enumSampleMIMO(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::StreamMIMO,
1, // MIMO is always considered as a single device
0)
);
qDebug("MetisMISOPlugin::enumSampleMIMO: enumerated Metis device #%d", it->sequence);
}
}
return result;
}
#ifdef SERVER_MODE
PluginInstanceGUI* MetisMISOPlugin::createSampleMIMOPluginInstanceGUI(
const QString& sourceId,
QWidget **widget,
DeviceUISet *deviceUISet)
{
(void) sourceId;
(void) widget;
(void) deviceUISet;
return 0;
}
#else
PluginInstanceGUI* MetisMISOPlugin::createSampleMIMOPluginInstanceGUI(
const QString& sourceId,
QWidget **widget,
DeviceUISet *deviceUISet)
{
if (sourceId == m_deviceTypeID) {
MetisMISOGui* gui = new MetisMISOGui(deviceUISet);
*widget = gui;
return gui;
} else {
return nullptr;
}
}
#endif
DeviceSampleMIMO *MetisMISOPlugin::createSampleMIMOPluginInstance(const QString& mimoId, DeviceAPI *deviceAPI)
{
if (mimoId == m_deviceTypeID)
{
MetisMISO* input = new MetisMISO(deviceAPI);
return input;
}
else
{
return nullptr;
}
}
DeviceWebAPIAdapter *MetisMISOPlugin::createDeviceWebAPIAdapter() const
{
return new MetisMISOWebAPIAdapter();
}

View File

@ -0,0 +1,56 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 _METISMISO_METISMIMOPLUGIN_H
#define _METISMISO_METISMIMOPLUGIN_H
#include <QObject>
#include "plugin/plugininterface.h"
class PluginAPI;
#define METISMISO_DEVICE_TYPE_ID "sdrangel.samplemimo.metismiso"
class MetisMISOPlugin : public QObject, public PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID METISMISO_DEVICE_TYPE_ID)
public:
explicit MetisMISOPlugin(QObject* parent = NULL);
const PluginDescriptor& getPluginDescriptor() const;
void initPlugin(PluginAPI* pluginAPI);
virtual void enumOriginDevices(QStringList& listedHwIds, OriginDevices& originDevices);
virtual SamplingDevices enumSampleMIMO(const OriginDevices& originDevices);
virtual PluginInstanceGUI* createSampleMIMOPluginInstanceGUI(
const QString& sourceId,
QWidget **widget,
DeviceUISet *deviceUISet);
virtual DeviceSampleMIMO* createSampleMIMOPluginInstance(const QString& sourceId, DeviceAPI *deviceAPI);
virtual DeviceWebAPIAdapter* createDeviceWebAPIAdapter() const;
static const QString m_hardwareID;
static const QString m_deviceTypeID;
private:
static const PluginDescriptor m_pluginDescriptor;
};
#endif // _METISMISO_METISMIMOPLUGIN_H

View File

@ -0,0 +1,155 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 <QtGlobal>
#include "util/simpleserializer.h"
#include "metismisosettings.h"
MetisMISOSettings::MetisMISOSettings()
{
resetToDefaults();
}
MetisMISOSettings::MetisMISOSettings(const MetisMISOSettings& other)
{
m_nbReceivers = other.m_nbReceivers;
m_rx1CenterFrequency = other.m_rx1CenterFrequency;
m_rx2CenterFrequency = other.m_rx2CenterFrequency;
m_rx3CenterFrequency = other.m_rx3CenterFrequency;
m_rx4CenterFrequency = other.m_rx4CenterFrequency;
m_txCenterFrequency = other.m_txCenterFrequency;
m_sampleRateIndex = other.m_sampleRateIndex;
m_log2Decim = other.m_log2Decim;
m_preamp = other.m_preamp;
m_random = other.m_random;
m_dither = other.m_dither;
m_duplex = other.m_duplex;
m_dcBlock = other.m_dcBlock;
m_iqCorrection = other.m_iqCorrection;
m_useReverseAPI = other.m_useReverseAPI;
m_reverseAPIAddress = other.m_reverseAPIAddress;
m_reverseAPIPort = other.m_reverseAPIPort;
m_reverseAPIDeviceIndex = other.m_reverseAPIDeviceIndex;
}
void MetisMISOSettings::resetToDefaults()
{
m_nbReceivers = 1;
m_rx1CenterFrequency = 7074000;
m_rx2CenterFrequency = 7074000;
m_rx3CenterFrequency = 7074000;
m_rx4CenterFrequency = 7074000;
m_txCenterFrequency = 7074000;
m_sampleRateIndex = 0; // 48000 kS/s
m_log2Decim = 0;
m_preamp = false;
m_random = false;
m_dither = false;
m_duplex = false;
m_dcBlock = false;
m_iqCorrection = false;
m_useReverseAPI = false;
m_reverseAPIAddress = "127.0.0.1";
m_reverseAPIPort = 8888;
m_reverseAPIDeviceIndex = 0;
}
QByteArray MetisMISOSettings::serialize() const
{
SimpleSerializer s(1);
s.writeU32(1, m_nbReceivers);
s.writeU64(2, m_rx1CenterFrequency);
s.writeU64(3, m_rx2CenterFrequency);
s.writeU64(4, m_rx3CenterFrequency);
s.writeU64(5, m_rx4CenterFrequency);
s.writeU64(6, m_txCenterFrequency);
s.writeU32(7, m_sampleRateIndex);
s.writeU32(8, m_log2Decim);
s.writeBool(9, m_preamp);
s.writeBool(10, m_random);
s.writeBool(11, m_dither);
s.writeBool(12, m_duplex);
s.writeBool(13, m_dcBlock);
s.writeBool(14, m_iqCorrection);
s.writeBool(15, m_useReverseAPI);
s.writeString(16, m_reverseAPIAddress);
s.writeU32(17, m_reverseAPIPort);
s.writeU32(18, m_reverseAPIDeviceIndex);
return s.final();
}
bool MetisMISOSettings::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if (!d.isValid())
{
resetToDefaults();
return false;
}
if (d.getVersion() == 1)
{
int intval;
uint32_t utmp;
d.readU32(1, &m_nbReceivers, 1);
d.readU64(2, &m_rx1CenterFrequency, 7074000);
d.readU64(3, &m_rx2CenterFrequency, 7074000);
d.readU64(4, &m_rx3CenterFrequency, 7074000);
d.readU64(5, &m_rx4CenterFrequency, 7074000);
d.readU64(6, &m_txCenterFrequency, 7074000);
d.readU32(7, &m_sampleRateIndex, 0);
d.readU32(8, &m_log2Decim, 0);
d.readBool(8, &m_preamp, false);
d.readBool(9, &m_random, false);
d.readBool(10, &m_dither, false);
d.readBool(11, &m_duplex, false);
d.readBool(12, &m_dcBlock, false);
d.readBool(13, &m_iqCorrection, false);
d.readBool(14, &m_useReverseAPI, false);
d.readString(15, &m_reverseAPIAddress, "127.0.0.1");
d.readU32(16, &utmp, 0);
if ((utmp > 1023) && (utmp < 65535)) {
m_reverseAPIPort = utmp;
} else {
m_reverseAPIPort = 8888;
}
d.readU32(17, &utmp, 0);
m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp;
return true;
}
else
{
resetToDefaults();
return false;
}
}
int MetisMISOSettings::getSampleRateFromIndex(unsigned int index)
{
if (index < 3) {
return (1<<index) * 48000;
} else {
return 48000;
}
}

View File

@ -0,0 +1,55 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 _METISMISO_METISMISOSETTINGS_H_
#define _METISMISO_METISMISOSETTINGS_H_
#include <QString>
struct MetisMISOSettings {
unsigned int m_nbReceivers;
quint64 m_rx1CenterFrequency;
quint64 m_rx2CenterFrequency;
quint64 m_rx3CenterFrequency;
quint64 m_rx4CenterFrequency;
quint64 m_txCenterFrequency;
unsigned int m_sampleRateIndex;
unsigned int m_log2Decim;
bool m_preamp;
bool m_random;
bool m_dither;
bool m_duplex;
bool m_dcBlock;
bool m_iqCorrection;
bool m_useReverseAPI;
QString m_reverseAPIAddress;
uint16_t m_reverseAPIPort;
uint16_t m_reverseAPIDeviceIndex;
static const int m_maxReceivers = 4;
MetisMISOSettings();
MetisMISOSettings(const MetisMISOSettings& other);
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
static int getSampleRateFromIndex(unsigned int index);
};
#endif /* _METISMISO_METISMISOSETTINGS_H_ */

View File

@ -0,0 +1,557 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 "dsp/samplemififo.h"
#include "metismisoudphandler.h"
MESSAGE_CLASS_DEFINITION(MetisMISOUDPHandler::MsgStartStop, Message)
MetisMISOUDPHandler::MetisMISOUDPHandler(SampleMIFifo *sampleFifo, DeviceAPI *deviceAPI) :
m_deviceAPI(deviceAPI),
m_socket(nullptr),
m_metisAddress(QHostAddress::LocalHost),
m_metisPort(9090),
m_running(false),
m_dataConnected(false),
m_sampleFifo(sampleFifo),
m_sampleCount(0),
m_messageQueueToGUI(nullptr),
m_mutex(QMutex::Recursive),
m_commandBase(0),
m_receiveSequence(0),
m_receiveSequenceError(0)
{
setNbReceivers(m_settings.m_nbReceivers);
for (unsigned int i = 0; i < MetisMISOSettings::m_maxReceivers; i++) {
m_convertBuffer[i].resize(1024, Sample{0,0});
}
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleMessages()));
}
MetisMISOUDPHandler::~MetisMISOUDPHandler()
{
stop();
}
void MetisMISOUDPHandler::start()
{
qDebug("MetisMISOUDPHandler::start");
m_rxFrame = 0;
m_txFrame = 0;
m_sendSequence = -1;
m_offset = 8;
m_receiveSequence = 0;
if (m_running) {
return;
}
if (!m_dataConnected)
{
if (m_socket.bind(QHostAddress::AnyIPv4, 10001, QUdpSocket::ShareAddress))
{
qDebug("MetisMISOUDPHandler::start: bind host socket OK");
connect(&m_socket, SIGNAL(readyRead()), this, SLOT(dataReadyRead()));
m_dataConnected = true;
}
else
{
qWarning("MetisMISOUDPHandler::start: cannot bind host socket");
m_dataConnected = false;
return;
}
}
// Start Metis
unsigned char buffer[64];
buffer[0] = (unsigned char) 0xEF;
buffer[1] = (unsigned char) 0XFE;
buffer[2] = (unsigned char) 0x04;
buffer[3] = (unsigned char) 0x01;
std::fill(&buffer[4], &buffer[64], 0);
if (m_socket.writeDatagram((const char*) buffer, sizeof(buffer), m_metisAddress, m_metisPort) < 0)
{
qDebug() << "MetisMISOUDPHandler::start: writeDatagram start command failed " << m_socket.errorString();
return;
}
else
{
qDebug() << "MetisMISOUDPHandler::start: writeDatagram start command" << m_metisAddress.toString() << ":" << m_metisPort;
}
m_socket.flush();
// send 2 frames with control data
sendNullBuffer();
sendNullBuffer(); // TODO: on the next send frequencies
m_running = true;
}
void MetisMISOUDPHandler::stop()
{
qDebug("MetisMISOUDPHandler::stop");
if (!m_running) {
return;
}
// stop Metis
unsigned char buffer[64];
buffer[0] = (unsigned char) 0xEF;
buffer[1] = (unsigned char) 0XFE;
buffer[2] = (unsigned char) 0x04;
buffer[3] = (unsigned char) 0x00;
std::fill(&buffer[4], &buffer[64], 0);
if (m_dataConnected)
{
disconnect(&m_socket, SIGNAL(readyRead()), this, SLOT(dataReadyRead()));
m_dataConnected = false;
}
if (m_socket.writeDatagram((const char*)buffer, sizeof(buffer), m_metisAddress,m_metisPort) < 0)
{
qDebug() << "MetisMISOUDPHandler::stop: writeDatagram failed " << m_socket.errorString();
return;
}
else
{
qDebug()<<"MetisMISOUDPHandler::stop: writeDatagram stop command" << m_metisAddress.toString() << ":" << m_metisPort;
}
m_socket.flush();
m_socket.close();
m_running = false;
}
void MetisMISOUDPHandler::setNbReceivers(unsigned int nbReceivers)
{
m_nbReceivers = nbReceivers;
switch(m_nbReceivers)
{
case 1: m_bMax = 512-0; break;
case 2: m_bMax = 512-0; break;
case 3: m_bMax = 512-4; break;
case 4: m_bMax = 512-10; break;
case 5: m_bMax = 512-24; break;
case 6: m_bMax = 512-10; break;
case 7: m_bMax = 512-20; break;
case 8: m_bMax = 512-4; break;
}
for (unsigned int i = 0; i < MetisMISOSettings::m_maxReceivers; i++) {
m_convertBuffer[i].resize(1024, Sample{0,0});
}
}
void MetisMISOUDPHandler::applySettings(const MetisMISOSettings& settings)
{
if (m_settings.m_nbReceivers != settings.m_nbReceivers)
{
QMutexLocker mutexLocker(&m_mutex);
int nbReceivers = settings.m_nbReceivers < 1 ?
1 : settings.m_nbReceivers > MetisMISOSettings::m_maxReceivers ?
MetisMISOSettings::m_maxReceivers : settings.m_nbReceivers;
setNbReceivers(nbReceivers);
}
if (m_settings.m_log2Decim != settings.m_log2Decim)
{
QMutexLocker mutexLocker(&m_mutex);
m_decimators.resetCounters();
}
m_settings = settings;
}
void MetisMISOUDPHandler::handleMessages()
{
Message* message;
while ((message = m_inputMessageQueue.pop()) != 0)
{
if (handleMessage(*message)) {
delete message;
}
}
}
bool MetisMISOUDPHandler::handleMessage(const Message& message)
{
if (MsgStartStop::match(message))
{
const MsgStartStop& cmd = (const MsgStartStop&) message;
if (cmd.getStartStop()) {
start();
} else {
stop();
}
return true;
}
else
{
return false;
}
}
void MetisMISOUDPHandler::sendMetisBuffer(int ep, unsigned char* buffer)
{
if (m_offset == 8) // header and first HPSDR frame
{
m_sendSequence++;
m_outputBuffer[0] = 0xEF;
m_outputBuffer[1] = 0xFE;
m_outputBuffer[2] = 0x01;
m_outputBuffer[3] = ep;
m_outputBuffer[4] = (m_sendSequence>>24) & 0xFF;
m_outputBuffer[5] = (m_sendSequence>>16) & 0xFF;
m_outputBuffer[6] = (m_sendSequence>>8) & 0xFF;
m_outputBuffer[7] = (m_sendSequence) & 0xFF;
std::copy(buffer, buffer+512, &m_outputBuffer[m_offset]); // copy the buffer over
m_offset = 520;
}
else // second HPSDR frame and send
{
std::copy(buffer, buffer+512, &m_outputBuffer[m_offset]); // copy the buffer over
m_offset = 8;
// send the buffer
if (m_socket.writeDatagram((const char*) m_outputBuffer, sizeof(m_outputBuffer), m_metisAddress, m_metisPort) < 0)
{
qDebug() << "MetisMISOUDPHandler::sendMetisBuffer: writeDatagram failed " << m_socket.errorString();
return;
}
m_socket.flush();
}
}
void MetisMISOUDPHandler::dataReadyRead()
{
QHostAddress metisAddress;
quint16 metisPort;
unsigned char receiveBuffer[1032];
qint64 length;
long sequence;
if ((length = m_socket.readDatagram((char*) &receiveBuffer, (qint64) sizeof(receiveBuffer), &metisAddress, &metisPort)) != 1032)
{
qDebug() << "MetisMISOUDPHandler::dataReadyRead: readDatagram failed " << m_socket.errorString();
return;
}
sendNullBuffer(); // TODO: for now a null payload is sent
sendNullBuffer();
if (receiveBuffer[0] == 0xEF && receiveBuffer[1] == 0xFE)
{
// valid frame
switch(receiveBuffer[2])
{
case 1: // IQ data
switch (receiveBuffer[3])
{
case 4: // EP4 data
break;
case 6: // EP6 data
sequence = ((receiveBuffer[4] & 0xFF)<<24) + ((receiveBuffer[5] & 0xFF)<<16) + ((receiveBuffer[6] & 0xFF)<<8) +(receiveBuffer[7] & 0xFF);
if (m_receiveSequence == 0)
{
m_receiveSequence = sequence;
}
else
{
m_receiveSequence++;
if (m_receiveSequence != sequence)
{
//qDebug()<<"Sequence error: expected "<<receive_sequence<<" got "<<sequence;
m_receiveSequence = sequence;
m_receiveSequenceError++;
}
}
processIQBuffer(&receiveBuffer[8]);
processIQBuffer(&receiveBuffer[520]);
break;
default:
qDebug() << "MetisMISOUDPHandler::dataReadyRead: invalid EP" << receiveBuffer[3];
break;
}
break;
default:
qDebug() << "MetisMISOUDPHandler::dataReadyRead: expected data packet (1) got " << receiveBuffer[2];
break;
}
} else {
qDebug()<<"expected EFFE";
}
}
void MetisMISOUDPHandler::sendNullBuffer()
{
unsigned char buffer[512];
if (m_txFrame % (m_settings.m_sampleRateIndex+1) == 0)
{
int commandIndex = 2*m_commandBase; // command rotation
buffer[0] = (unsigned char) 0x7F;
buffer[1] = (unsigned char) 0x7F;
buffer[2] = (unsigned char) 0x7F;
buffer[3] = commandIndex; // C0
int commandValue = getCommandValue(commandIndex);
buffer[4]= commandValue>>24; // C1
buffer[5]= (commandValue>>16) & 0xFF; // C2
buffer[6]= (commandValue>>8) & 0xFF; // C3
buffer[7]= commandValue & 0xFF; // C4
if (m_commandBase < 15) { // base count 0 to 16
m_commandBase++;
} else {
m_commandBase = 0;
}
std::fill(&buffer[8], &buffer[512], 0);
sendMetisBuffer(2, buffer);
}
m_txFrame++;
}
int MetisMISOUDPHandler::getCommandValue(int commandIndex)
{
int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
if (commandIndex == 0)
{
c1 = m_settings.m_sampleRateIndex & 0x03;
c3 = m_settings.m_preamp ? 0x04 : 0;
c3 += m_settings.m_dither ? 0x08 : 0;
c3 += m_settings.m_random ? 0x10 : 0;
c4 = m_settings.m_duplex ? 0x04 : 0;
c4 += (((m_nbReceivers-1) & 0x07)<<3);
return (c1<<24) + (c3<<8) + c4;
}
else if (commandIndex == 2)
{
return m_settings.m_txCenterFrequency;
}
else if (commandIndex == 4)
{
return m_settings.m_rx1CenterFrequency;
}
else if (commandIndex == 6)
{
return m_settings.m_rx2CenterFrequency;
}
else if (commandIndex == 8)
{
return m_settings.m_rx3CenterFrequency;
}
else if (commandIndex == 10)
{
return m_settings.m_rx4CenterFrequency;
}
else
{
return 0;
}
}
void MetisMISOUDPHandler::processIQBuffer(unsigned char* buffer)
{
int b = 0;
int b_max;
int r;
int sampleI, sampleQ, sampleMic;
if (buffer[b++]==0x7F && buffer[b++]==0x7F && buffer[b++]==0x7F)
{
QMutexLocker mutexLocker(&m_mutex);
// extract control bytes
m_controlIn[0] = buffer[b++];
m_controlIn[1] = buffer[b++];
m_controlIn[2] = buffer[b++];
m_controlIn[3] = buffer[b++];
m_controlIn[4] = buffer[b++];
// extract PTT, DOT and DASH
m_ptt = (m_controlIn[0] & 0x01) == 0x01;
m_dash = (m_controlIn[0] & 0x02) == 0x02;
m_dot = (m_controlIn[0] & 0x04) == 0x04;
switch((m_controlIn[0]>>3) & 0x1F)
{
case 0:
m_lt2208ADCOverflow = m_controlIn[1] & 0x01;
m_IO1 = (m_controlIn[1] & 0x02) ? 0 : 1;
m_IO2 = (m_controlIn[1] & 0x04) ? 0 : 1;
m_IO3 = (m_controlIn[1] & 0x08) ? 0 : 1;
// {
// int nbRx = (m_controlIn[4]>>3) & 0x07;
// nbRx++;
// qDebug("MetisMISOUDPHandler::processIQBuffer: nbRx: %d", nbRx);
// }
if (m_mercurySoftwareVersion != m_controlIn[2])
{
m_mercurySoftwareVersion = m_controlIn[2];
qDebug("MetisMISOUDPHandler::processIQBuffer: Mercury Software version: %d (0x%0X)",
m_mercurySoftwareVersion, m_mercurySoftwareVersion);
}
if (m_penelopeSoftwareVersion != m_controlIn[3])
{
m_penelopeSoftwareVersion = m_controlIn[3];
qDebug("MetisMISOUDPHandler::processIQBuffer: Penelope Software version: %d (0x%0X)",
m_penelopeSoftwareVersion, m_penelopeSoftwareVersion);
}
if (m_ozySoftwareVersion != m_controlIn[4])
{
m_ozySoftwareVersion = m_controlIn[4];
qDebug("MetisMISOUDPHandler::processIQBuffer: Ozy Software version: %d (0x%0X)",
m_ozySoftwareVersion, m_ozySoftwareVersion);
}
break;
case 1:
m_forwardPower = (m_controlIn[1]<<8) + m_controlIn[2]; // from Penelope or Hermes
m_alexForwardPower = (m_controlIn[3]<<8) + m_controlIn[4]; // from Alex or Apollo
break;
case 2:
m_alexForwardPower = (m_controlIn[1]<<8) + m_controlIn[2]; // from Alex or Apollo
m_AIN3 = (m_controlIn[3]<<8) + m_controlIn[4]; // from Pennelope or Hermes
break;
case 3:
m_AIN4 = (m_controlIn[1]<<8) + m_controlIn[2]; // from Pennelope or Hermes
m_AIN6 = (m_controlIn[3]<<8) + m_controlIn[4]; // from Pennelope or Hermes
break;
}
// extract the samples
while (b < m_bMax)
{
int samplesAdded = 0;
// extract each of the receivers
for (r = 0; r < m_nbReceivers; r++)
{
if (SDR_RX_SAMP_SZ == 16)
{
sampleQ = (int)((signed char)buffer[b++]) << 8;
sampleQ += (int)((unsigned char)buffer[b++]);
b++;
sampleI = (int)((signed char)buffer[b++]) << 8;
sampleI += (int)((unsigned char)buffer[b++]);
b++;
}
else
{
sampleQ = (int)((signed char)buffer[b++]) << 16;
sampleQ += (int)((unsigned char)buffer[b++]) << 8;
sampleQ += (int)((unsigned char)buffer[b++]);
sampleI = (int)((signed char)buffer[b++]) << 16;
sampleI += (int)((unsigned char)buffer[b++]) << 8;
sampleI += (int)((unsigned char)buffer[b++]);
}
if (r < MetisMISOSettings::m_maxReceivers)
{
if (m_settings.m_log2Decim == 0) // no decimation - direct conversion
{
m_convertBuffer[r][m_sampleCount] = Sample{sampleI, sampleQ};
samplesAdded = 1;
}
else
{
SampleVector v(2, Sample{0, 0});
switch (m_settings.m_log2Decim)
{
case 1:
samplesAdded = m_decimators.decimate2(sampleI, sampleQ, v, r);
break;
case 2:
samplesAdded = m_decimators.decimate4(sampleI, sampleQ, v, r);
break;
case 3:
samplesAdded = m_decimators.decimate8(sampleI, sampleQ, v, r);
break;
default:
break;
}
if (samplesAdded != 0)
{
std::copy(
v.begin(),
v.begin() + samplesAdded,
&m_convertBuffer[r][m_sampleCount]
);
}
}
}
}
sampleMic = (int)((signed char) buffer[b++]) << 8;
sampleMic += (int)((unsigned char)buffer[b++]);
if (samplesAdded != 0)
{
m_sampleCount += samplesAdded;
if (m_sampleCount >= 1024)
{
std::vector<SampleVector::const_iterator> vbegin;
for (unsigned int channel = 0; channel < MetisMISOSettings::m_maxReceivers; channel++) {
vbegin.push_back(m_convertBuffer[channel].begin());
}
m_sampleFifo->writeSync(vbegin, 1024);
m_sampleCount = 0;
}
}
}
}
else
{
qDebug()<<"MetisMISOUDPHandler::processIQBuffer: SYNC Error";
}
m_rxFrame++;
}

View File

@ -0,0 +1,130 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 _METISMISO_METISMISOUDPHANDLER_H_
#define _METISMISO_METISMISOUDPHANDLER_H_
#include <QObject>
#include <QUdpSocket>
#include <QHostAddress>
#include <QMutex>
#include "dsp/decimators.h"
#include "util/messagequeue.h"
#include "util/message.h"
#include "metismisosettings.h"
#include "metismisodecimators.h"
class SampleMIFifo;
class DeviceAPI;
class MetisMISOUDPHandler : public QObject
{
Q_OBJECT
public:
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)
{ }
};
MetisMISOUDPHandler(SampleMIFifo* sampleFifo, DeviceAPI *deviceAPI);
~MetisMISOUDPHandler();
void setMessageQueueToGUI(MessageQueue *queue) { m_messageQueueToGUI = queue; }
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
void start();
void stop();
void setMetisAddress(const QHostAddress& address, quint16 port) {
m_metisAddress = address;
m_metisPort = port;
}
void setNbReceivers(unsigned int nbReceivers);
void applySettings(const MetisMISOSettings& settings);
public slots:
void dataReadyRead();
private:
DeviceAPI *m_deviceAPI;
QUdpSocket m_socket;
QHostAddress m_metisAddress;
quint16 m_metisPort;
bool m_running;
bool m_dataConnected;
SampleMIFifo *m_sampleFifo;
SampleVector m_convertBuffer[MetisMISOSettings::m_maxReceivers];
int m_sampleCount;
MessageQueue *m_messageQueueToGUI;
MessageQueue m_inputMessageQueue;
MetisMISOSettings m_settings;
QMutex m_mutex;
MetisMISODecimators m_decimators;
unsigned long m_sendSequence;
int m_offset;
int m_commandBase;
unsigned long m_rxFrame;
unsigned long m_txFrame;
unsigned char m_outputBuffer[1032]; //!< buffer to send
unsigned char m_metisBuffer[512]; //!< current HPSDR frame
int metisBufferIndex;
unsigned long m_receiveSequence;
int m_receiveSequenceError;
unsigned char m_controlIn[5];
unsigned int m_nbReceivers;
int m_bMax;
bool m_ptt;
bool m_dash;
bool m_dot;
bool m_lt2208ADCOverflow;
int m_IO1;
int m_IO2;
int m_IO3;
int m_mercurySoftwareVersion;
int m_penelopeSoftwareVersion;
int m_ozySoftwareVersion;
int m_forwardPower;
int m_alexForwardPower;
int m_AIN3;
int m_AIN4;
int m_AIN6;
void sendMetisBuffer(int ep, unsigned char* buffer);
bool handleMessage(const Message& message);
void sendNullBuffer();
int getCommandValue(int commandIndex);
void processIQBuffer(unsigned char* buffer);
private slots:
void handleMessages();
};
#endif // _METISMISO_METISMISOUDPHANDLER_H_

View File

@ -0,0 +1,51 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// 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 "metismiso.h"
#include "metismisowebapiadapter.h"
MetisMISOWebAPIAdapter::MetisMISOWebAPIAdapter()
{}
MetisMISOWebAPIAdapter::~MetisMISOWebAPIAdapter()
{}
int MetisMISOWebAPIAdapter::webapiSettingsGet(
SWGSDRangel::SWGDeviceSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setMetisMisoSettings(new SWGSDRangel::SWGMetisMISOSettings());
response.getMetisMisoSettings()->init();
MetisMISO::webapiFormatDeviceSettings(response, m_settings);
return 200;
}
int MetisMISOWebAPIAdapter::webapiSettingsPutPatch(
bool force,
const QStringList& deviceSettingsKeys,
SWGSDRangel::SWGDeviceSettings& response, // query + response
QString& errorMessage)
{
(void) errorMessage;
MetisMISO::webapiUpdateDeviceSettings(m_settings, deviceSettingsKeys, response);
return 200;
}

View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// 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/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef _METISMISO_METISMISOWEBAPIADAPTER_H_
#define _METISMISO_METISMISOWEBAPIADAPTER_H_
#include "device/devicewebapiadapter.h"
#include "metismisosettings.h"
class MetisMISOWebAPIAdapter : public DeviceWebAPIAdapter
{
public:
MetisMISOWebAPIAdapter();
virtual ~MetisMISOWebAPIAdapter();
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:
MetisMISOSettings m_settings;
};
#endif // _METISMISO_METISMISOWEBAPIADAPTER_H_

View File

@ -0,0 +1,137 @@
<h1>Test source input plugin</h1>
<h2>Introduction</h2>
This is a v5 only plugin.
This input sample source plugin is an internal continuous wave generator that can be used to carry out test of software internals.
<h2>Build</h2>
The plugin is present in the core of the software and thus is always present in the list of sources.
<h2>Interface</h2>
![Test source input plugin GUI](../../../doc/img/TestSourceInput_plugin.png)
<h3>1: Common stream parameters</h3>
![Remote source input stream GUI](../../../doc/img/RemoteInput_plugin_01.png)
<h4>1.1: Frequency</h4>
This is the center frequency of reception in kHz.
<h4>1.2: Start/Stop</h4>
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, plug back in and start again.
<h4>1.3: Record</h4>
- Left click: record baseband I/Q stream toggle button
- Right click: choose record file
<h4>1.4: Stream sample rate</h4>
Baseband I/Q sample rate in kS/s. This is the device to host sample rate (3) divided by the decimation factor (4).
<h3>2: Various options</h3>
![Test source input plugin GUI 2](../../../doc/img/TestSourceInput_plugin_2.png)
<h4>2.1: Auto corrections</h4>
This combo box control the local DSP auto correction options:
- **None**: no correction
- **DC**: auto remove DC component
- **DC+IQ**: auto remove DC component and correct I/Q balance.
<h4>2.2: Decimation factor</h4>
The I/Q stream from the generator is downsampled by a power of two before being sent to the passband. Possible values are increasing powers of two: 1 (no decimation), 2, 4, 8, 16, 32. This exercises the decimation chain.
This exercises the decimation chain.
<h4>2.3: Baseband center frequency position relative the center frequency</h4>
- **Cen**: the decimation operation takes place around the 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>2.4: Sample size</h3>
This is the sample size in number of bits. It corresponds to the actual sample size used by the devices supported:
- **8**: RTL-SDR, HackRF
- **12**: Airspy, BladeRF, LimeSDR, PlutoSDR, SDRplay
- **16**: Airspy HF+, FCD Pro, FCD Pro+
<h3>3: Sample rate</h3>
This controls the generator sample rate in samples per second.
<h3>4: Modulation</h4>
- **No**: No modulation
- **AM**: Amplitude modulation (AM)
- **FM**: Frequency modulation (FM)
- **P0**: Pattern 0 is a binary pattern
- Pulse width: 150 samples
- Sync pattern: 010 at full amplitude
- Binary pattern LSB first on 3 bits from 0 to 7 at 0.3 amplitude
- **P1**: Pattern 1 is a sawtooth pattern
- Pulse width: 1000 samples
- Starts at full amplitude then amplitude decreases linearly down to zero
- **P2**: Pattern 2 is a 50% duty cycle square pattern
- Pulse width: 1000 samples
- Starts with a full amplitude pulse then down to zero for the duration of one pulse
<h3>5: Modulating tone frequency</h3>
This controls the modulating tone frequency in kHz in 10 Hz steps.
<h3>6: Carrier shift from center frequency</h3>
Use this control to set the offset of the carrier from the center frequency of reception.
<h3>7: AM modulation factor</h3>
This controls the AM modulation factor from 0 to 99%
<h3>8: FM deviation</h3>
This controls the frequency modulation deviation in kHz in 100 Hz steps. It cannot exceed the sample rate.
<h3>9: Amplitude coarse control</h3>
This slider controls the number of amplitude bits by steps of 100 bits. The total number of amplitude bits appear on the right.
<h3>10: Amplitude fine control</h3>
This slider controls the number of amplitude bits by steps of 1 bit. The signal power in dB relative to the maximum power (full bit range) appear on the right.
<h3>11: DC bias</h3>
Use this slider to give a DC component in percentage of maximum amplitude.
<h3>12: I bias</h3>
Use this slider to give an in-phase (I) bias in percentage of maximum amplitude.
<h3>13: Q bias</h3>
Use this slider to give an quadrature-phase (Q) bias in percentage of maximum amplitude.
<h3>14: Phase imbalance</h3>
Use this slider to introduce a phase imbalance in percentage of full period (continuous wave) or percentage of I signal injected in Q (AM, FM).

View File

@ -3372,6 +3372,9 @@ margin-bottom: 20px;
"localOutputSettings" : {
"$ref" : "#/definitions/LocalOutputSettings"
},
"metisMISOSettings" : {
"$ref" : "#/definitions/MetisMISOSettings"
},
"perseusSettings" : {
"$ref" : "#/definitions/PerseusSettings"
},
@ -5495,6 +5498,78 @@ margin-bottom: 20px;
}
},
"description" : "Logging parameters setting"
};
defs.MetisMISOSettings = {
"properties" : {
"nbReceivers" : {
"type" : "integer",
"description" : "Number of activated receivers"
},
"rx1CenterFrequency" : {
"type" : "integer",
"format" : "uint64"
},
"rx2CenterFrequency" : {
"type" : "integer",
"format" : "uint64"
},
"rx3CenterFrequency" : {
"type" : "integer",
"format" : "uint64"
},
"rx4CenterFrequency" : {
"type" : "integer",
"format" : "uint64"
},
"txCenterFrequency" : {
"type" : "integer",
"format" : "uint64"
},
"sampleRateIndex" : {
"type" : "integer"
},
"log2Decim" : {
"type" : "integer"
},
"preamp" : {
"type" : "integer",
"description" : "Preamplifer * 0 - disabled * 1 - enabled\n"
},
"random" : {
"type" : "integer",
"description" : "LT2208 Random * 0 - disabled * 1 - enabled\n"
},
"dither" : {
"type" : "integer",
"description" : "LT2208 Dither * 0 - disabled * 1 - enabled\n"
},
"duplex" : {
"type" : "integer",
"description" : "Duplex * 0 - disabled * 1 - enabled\n"
},
"dcBlock" : {
"type" : "integer",
"description" : "DC block in software * 0 - disabled * 1 - enabled\n"
},
"iqCorrection" : {
"type" : "integer",
"description" : "DC block in software * 0 - disabled * 1 - enabled\n"
},
"useReverseAPI" : {
"type" : "integer",
"description" : "Synchronize with reverse API * 0 - disabled * 1 - enabled\n"
},
"reverseAPIAddress" : {
"type" : "string"
},
"reverseAPIPort" : {
"type" : "integer"
},
"reverseAPIDeviceIndex" : {
"type" : "integer"
}
},
"description" : "MetisMISOSettings"
};
defs.NFMDemodReport = {
"properties" : {
@ -37459,7 +37534,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2020-08-26T20:23:03.201+02:00
Generated 2020-09-05T10:34:53.674+02:00
</div>
</div>
</div>

View File

@ -50,6 +50,8 @@ DeviceSettings:
$ref: "/doc/swagger/include/LocalInput.yaml#/LocalInputSettings"
localOutputSettings:
$ref: "/doc/swagger/include/LocalOutput.yaml#/LocalOutputSettings"
metisMISOSettings:
$ref: "/doc/swagger/include/MetisMISO.yaml#/MetisMISOSettings"
perseusSettings:
$ref: "/doc/swagger/include/Perseus.yaml#/PerseusSettings"
plutoSdrInputSettings:

View File

@ -0,0 +1,73 @@
MetisMISOSettings:
description: MetisMISOSettings
properties:
nbReceivers:
type: integer
description: Number of activated receivers
rx1CenterFrequency:
type: integer
format: uint64
rx2CenterFrequency:
type: integer
format: uint64
rx3CenterFrequency:
type: integer
format: uint64
rx4CenterFrequency:
type: integer
format: uint64
txCenterFrequency:
type: integer
format: uint64
sampleRateIndex:
type: integer
log2Decim:
type: integer
preamp:
type: integer
description: >
Preamplifer
* 0 - disabled
* 1 - enabled
random:
type: integer
description: >
LT2208 Random
* 0 - disabled
* 1 - enabled
dither:
type: integer
description: >
LT2208 Dither
* 0 - disabled
* 1 - enabled
duplex:
type: integer
description: >
Duplex
* 0 - disabled
* 1 - enabled
dcBlock:
type: integer
description: >
DC block in software
* 0 - disabled
* 1 - enabled
iqCorrection:
type: integer
description: >
DC block in software
* 0 - disabled
* 1 - enabled
useReverseAPI:
type: integer
description: >
Synchronize with reverse API
* 0 - disabled
* 1 - enabled
reverseAPIAddress:
type: string
reverseAPIPort:
type: integer
reverseAPIDeviceIndex:
type: integer

View File

@ -50,6 +50,8 @@ DeviceSettings:
$ref: "http://swgserver:8081/api/swagger/include/LocalInput.yaml#/LocalInputSettings"
localOutputSettings:
$ref: "http://swgserver:8081/api/swagger/include/LocalOutput.yaml#/LocalOutputSettings"
metisMISOSettings:
$ref: "http://swgserver:8081/api/swagger/include/MetisMISO.yaml#/MetisMISOSettings"
perseusSettings:
$ref: "http://swgserver:8081/api/swagger/include/Perseus.yaml#/PerseusSettings"
plutoSdrInputSettings:

View File

@ -0,0 +1,73 @@
MetisMISOSettings:
description: MetisMISOSettings
properties:
nbReceivers:
type: integer
description: Number of activated receivers
rx1CenterFrequency:
type: integer
format: uint64
rx2CenterFrequency:
type: integer
format: uint64
rx3CenterFrequency:
type: integer
format: uint64
rx4CenterFrequency:
type: integer
format: uint64
txCenterFrequency:
type: integer
format: uint64
sampleRateIndex:
type: integer
log2Decim:
type: integer
preamp:
type: integer
description: >
Preamplifer
* 0 - disabled
* 1 - enabled
random:
type: integer
description: >
LT2208 Random
* 0 - disabled
* 1 - enabled
dither:
type: integer
description: >
LT2208 Dither
* 0 - disabled
* 1 - enabled
duplex:
type: integer
description: >
Duplex
* 0 - disabled
* 1 - enabled
dcBlock:
type: integer
description: >
DC block in software
* 0 - disabled
* 1 - enabled
iqCorrection:
type: integer
description: >
DC block in software
* 0 - disabled
* 1 - enabled
useReverseAPI:
type: integer
description: >
Synchronize with reverse API
* 0 - disabled
* 1 - enabled
reverseAPIAddress:
type: string
reverseAPIPort:
type: integer
reverseAPIDeviceIndex:
type: integer

View File

@ -3372,6 +3372,9 @@ margin-bottom: 20px;
"localOutputSettings" : {
"$ref" : "#/definitions/LocalOutputSettings"
},
"metisMISOSettings" : {
"$ref" : "#/definitions/MetisMISOSettings"
},
"perseusSettings" : {
"$ref" : "#/definitions/PerseusSettings"
},
@ -5495,6 +5498,78 @@ margin-bottom: 20px;
}
},
"description" : "Logging parameters setting"
};
defs.MetisMISOSettings = {
"properties" : {
"nbReceivers" : {
"type" : "integer",
"description" : "Number of activated receivers"
},
"rx1CenterFrequency" : {
"type" : "integer",
"format" : "uint64"
},
"rx2CenterFrequency" : {
"type" : "integer",
"format" : "uint64"
},
"rx3CenterFrequency" : {
"type" : "integer",
"format" : "uint64"
},
"rx4CenterFrequency" : {
"type" : "integer",
"format" : "uint64"
},
"txCenterFrequency" : {
"type" : "integer",
"format" : "uint64"
},
"sampleRateIndex" : {
"type" : "integer"
},
"log2Decim" : {
"type" : "integer"
},
"preamp" : {
"type" : "integer",
"description" : "Preamplifer * 0 - disabled * 1 - enabled\n"
},
"random" : {
"type" : "integer",
"description" : "LT2208 Random * 0 - disabled * 1 - enabled\n"
},
"dither" : {
"type" : "integer",
"description" : "LT2208 Dither * 0 - disabled * 1 - enabled\n"
},
"duplex" : {
"type" : "integer",
"description" : "Duplex * 0 - disabled * 1 - enabled\n"
},
"dcBlock" : {
"type" : "integer",
"description" : "DC block in software * 0 - disabled * 1 - enabled\n"
},
"iqCorrection" : {
"type" : "integer",
"description" : "DC block in software * 0 - disabled * 1 - enabled\n"
},
"useReverseAPI" : {
"type" : "integer",
"description" : "Synchronize with reverse API * 0 - disabled * 1 - enabled\n"
},
"reverseAPIAddress" : {
"type" : "string"
},
"reverseAPIPort" : {
"type" : "integer"
},
"reverseAPIDeviceIndex" : {
"type" : "integer"
}
},
"description" : "MetisMISOSettings"
};
defs.NFMDemodReport = {
"properties" : {
@ -37459,7 +37534,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2020-08-26T20:23:03.201+02:00
Generated 2020-09-05T10:34:53.674+02:00
</div>
</div>
</div>

View File

@ -70,6 +70,8 @@ SWGDeviceSettings::SWGDeviceSettings() {
m_local_input_settings_isSet = false;
local_output_settings = nullptr;
m_local_output_settings_isSet = false;
metis_miso_settings = nullptr;
m_metis_miso_settings_isSet = false;
perseus_settings = nullptr;
m_perseus_settings_isSet = false;
pluto_sdr_input_settings = nullptr;
@ -152,6 +154,8 @@ SWGDeviceSettings::init() {
m_local_input_settings_isSet = false;
local_output_settings = new SWGLocalOutputSettings();
m_local_output_settings_isSet = false;
metis_miso_settings = new SWGMetisMISOSettings();
m_metis_miso_settings_isSet = false;
perseus_settings = new SWGPerseusSettings();
m_perseus_settings_isSet = false;
pluto_sdr_input_settings = new SWGPlutoSdrInputSettings();
@ -247,6 +251,9 @@ SWGDeviceSettings::cleanup() {
if(local_output_settings != nullptr) {
delete local_output_settings;
}
if(metis_miso_settings != nullptr) {
delete metis_miso_settings;
}
if(perseus_settings != nullptr) {
delete perseus_settings;
}
@ -350,6 +357,8 @@ SWGDeviceSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&local_output_settings, pJson["localOutputSettings"], "SWGLocalOutputSettings", "SWGLocalOutputSettings");
::SWGSDRangel::setValue(&metis_miso_settings, pJson["metisMISOSettings"], "SWGMetisMISOSettings", "SWGMetisMISOSettings");
::SWGSDRangel::setValue(&perseus_settings, pJson["perseusSettings"], "SWGPerseusSettings", "SWGPerseusSettings");
::SWGSDRangel::setValue(&pluto_sdr_input_settings, pJson["plutoSdrInputSettings"], "SWGPlutoSdrInputSettings", "SWGPlutoSdrInputSettings");
@ -461,6 +470,9 @@ SWGDeviceSettings::asJsonObject() {
if((local_output_settings != nullptr) && (local_output_settings->isSet())){
toJsonValue(QString("localOutputSettings"), local_output_settings, obj, QString("SWGLocalOutputSettings"));
}
if((metis_miso_settings != nullptr) && (metis_miso_settings->isSet())){
toJsonValue(QString("metisMISOSettings"), metis_miso_settings, obj, QString("SWGMetisMISOSettings"));
}
if((perseus_settings != nullptr) && (perseus_settings->isSet())){
toJsonValue(QString("perseusSettings"), perseus_settings, obj, QString("SWGPerseusSettings"));
}
@ -723,6 +735,16 @@ SWGDeviceSettings::setLocalOutputSettings(SWGLocalOutputSettings* local_output_s
this->m_local_output_settings_isSet = true;
}
SWGMetisMISOSettings*
SWGDeviceSettings::getMetisMisoSettings() {
return metis_miso_settings;
}
void
SWGDeviceSettings::setMetisMisoSettings(SWGMetisMISOSettings* metis_miso_settings) {
this->metis_miso_settings = metis_miso_settings;
this->m_metis_miso_settings_isSet = true;
}
SWGPerseusSettings*
SWGDeviceSettings::getPerseusSettings() {
return perseus_settings;
@ -951,6 +973,9 @@ SWGDeviceSettings::isSet(){
if(local_output_settings && local_output_settings->isSet()){
isObjectUpdated = true; break;
}
if(metis_miso_settings && metis_miso_settings->isSet()){
isObjectUpdated = true; break;
}
if(perseus_settings && perseus_settings->isSet()){
isObjectUpdated = true; break;
}

View File

@ -40,6 +40,7 @@
#include "SWGLimeSdrOutputSettings.h"
#include "SWGLocalInputSettings.h"
#include "SWGLocalOutputSettings.h"
#include "SWGMetisMISOSettings.h"
#include "SWGPerseusSettings.h"
#include "SWGPlutoSdrInputSettings.h"
#include "SWGPlutoSdrOutputSettings.h"
@ -139,6 +140,9 @@ public:
SWGLocalOutputSettings* getLocalOutputSettings();
void setLocalOutputSettings(SWGLocalOutputSettings* local_output_settings);
SWGMetisMISOSettings* getMetisMisoSettings();
void setMetisMisoSettings(SWGMetisMISOSettings* metis_miso_settings);
SWGPerseusSettings* getPerseusSettings();
void setPerseusSettings(SWGPerseusSettings* perseus_settings);
@ -254,6 +258,9 @@ private:
SWGLocalOutputSettings* local_output_settings;
bool m_local_output_settings_isSet;
SWGMetisMISOSettings* metis_miso_settings;
bool m_metis_miso_settings_isSet;
SWGPerseusSettings* perseus_settings;
bool m_perseus_settings_isSet;

View File

@ -0,0 +1,501 @@
/**
* SDRangel
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
*
* OpenAPI spec version: 5.9.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
#include "SWGMetisMISOSettings.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGMetisMISOSettings::SWGMetisMISOSettings(QString* json) {
init();
this->fromJson(*json);
}
SWGMetisMISOSettings::SWGMetisMISOSettings() {
nb_receivers = 0;
m_nb_receivers_isSet = false;
rx1_center_frequency = 0;
m_rx1_center_frequency_isSet = false;
rx2_center_frequency = 0;
m_rx2_center_frequency_isSet = false;
rx3_center_frequency = 0;
m_rx3_center_frequency_isSet = false;
rx4_center_frequency = 0;
m_rx4_center_frequency_isSet = false;
tx_center_frequency = 0;
m_tx_center_frequency_isSet = false;
sample_rate_index = 0;
m_sample_rate_index_isSet = false;
log2_decim = 0;
m_log2_decim_isSet = false;
preamp = 0;
m_preamp_isSet = false;
random = 0;
m_random_isSet = false;
dither = 0;
m_dither_isSet = false;
duplex = 0;
m_duplex_isSet = false;
dc_block = 0;
m_dc_block_isSet = false;
iq_correction = 0;
m_iq_correction_isSet = false;
use_reverse_api = 0;
m_use_reverse_api_isSet = false;
reverse_api_address = nullptr;
m_reverse_api_address_isSet = false;
reverse_api_port = 0;
m_reverse_api_port_isSet = false;
reverse_api_device_index = 0;
m_reverse_api_device_index_isSet = false;
}
SWGMetisMISOSettings::~SWGMetisMISOSettings() {
this->cleanup();
}
void
SWGMetisMISOSettings::init() {
nb_receivers = 0;
m_nb_receivers_isSet = false;
rx1_center_frequency = 0;
m_rx1_center_frequency_isSet = false;
rx2_center_frequency = 0;
m_rx2_center_frequency_isSet = false;
rx3_center_frequency = 0;
m_rx3_center_frequency_isSet = false;
rx4_center_frequency = 0;
m_rx4_center_frequency_isSet = false;
tx_center_frequency = 0;
m_tx_center_frequency_isSet = false;
sample_rate_index = 0;
m_sample_rate_index_isSet = false;
log2_decim = 0;
m_log2_decim_isSet = false;
preamp = 0;
m_preamp_isSet = false;
random = 0;
m_random_isSet = false;
dither = 0;
m_dither_isSet = false;
duplex = 0;
m_duplex_isSet = false;
dc_block = 0;
m_dc_block_isSet = false;
iq_correction = 0;
m_iq_correction_isSet = false;
use_reverse_api = 0;
m_use_reverse_api_isSet = false;
reverse_api_address = new QString("");
m_reverse_api_address_isSet = false;
reverse_api_port = 0;
m_reverse_api_port_isSet = false;
reverse_api_device_index = 0;
m_reverse_api_device_index_isSet = false;
}
void
SWGMetisMISOSettings::cleanup() {
if(reverse_api_address != nullptr) {
delete reverse_api_address;
}
}
SWGMetisMISOSettings*
SWGMetisMISOSettings::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGMetisMISOSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&nb_receivers, pJson["nbReceivers"], "qint32", "");
::SWGSDRangel::setValue(&rx1_center_frequency, pJson["rx1CenterFrequency"], "qint32", "");
::SWGSDRangel::setValue(&rx2_center_frequency, pJson["rx2CenterFrequency"], "qint32", "");
::SWGSDRangel::setValue(&rx3_center_frequency, pJson["rx3CenterFrequency"], "qint32", "");
::SWGSDRangel::setValue(&rx4_center_frequency, pJson["rx4CenterFrequency"], "qint32", "");
::SWGSDRangel::setValue(&tx_center_frequency, pJson["txCenterFrequency"], "qint32", "");
::SWGSDRangel::setValue(&sample_rate_index, pJson["sampleRateIndex"], "qint32", "");
::SWGSDRangel::setValue(&log2_decim, pJson["log2Decim"], "qint32", "");
::SWGSDRangel::setValue(&preamp, pJson["preamp"], "qint32", "");
::SWGSDRangel::setValue(&random, pJson["random"], "qint32", "");
::SWGSDRangel::setValue(&dither, pJson["dither"], "qint32", "");
::SWGSDRangel::setValue(&duplex, pJson["duplex"], "qint32", "");
::SWGSDRangel::setValue(&dc_block, pJson["dcBlock"], "qint32", "");
::SWGSDRangel::setValue(&iq_correction, pJson["iqCorrection"], "qint32", "");
::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString");
::SWGSDRangel::setValue(&reverse_api_port, pJson["reverseAPIPort"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_device_index, pJson["reverseAPIDeviceIndex"], "qint32", "");
}
QString
SWGMetisMISOSettings::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGMetisMISOSettings::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if(m_nb_receivers_isSet){
obj->insert("nbReceivers", QJsonValue(nb_receivers));
}
if(m_rx1_center_frequency_isSet){
obj->insert("rx1CenterFrequency", QJsonValue(rx1_center_frequency));
}
if(m_rx2_center_frequency_isSet){
obj->insert("rx2CenterFrequency", QJsonValue(rx2_center_frequency));
}
if(m_rx3_center_frequency_isSet){
obj->insert("rx3CenterFrequency", QJsonValue(rx3_center_frequency));
}
if(m_rx4_center_frequency_isSet){
obj->insert("rx4CenterFrequency", QJsonValue(rx4_center_frequency));
}
if(m_tx_center_frequency_isSet){
obj->insert("txCenterFrequency", QJsonValue(tx_center_frequency));
}
if(m_sample_rate_index_isSet){
obj->insert("sampleRateIndex", QJsonValue(sample_rate_index));
}
if(m_log2_decim_isSet){
obj->insert("log2Decim", QJsonValue(log2_decim));
}
if(m_preamp_isSet){
obj->insert("preamp", QJsonValue(preamp));
}
if(m_random_isSet){
obj->insert("random", QJsonValue(random));
}
if(m_dither_isSet){
obj->insert("dither", QJsonValue(dither));
}
if(m_duplex_isSet){
obj->insert("duplex", QJsonValue(duplex));
}
if(m_dc_block_isSet){
obj->insert("dcBlock", QJsonValue(dc_block));
}
if(m_iq_correction_isSet){
obj->insert("iqCorrection", QJsonValue(iq_correction));
}
if(m_use_reverse_api_isSet){
obj->insert("useReverseAPI", QJsonValue(use_reverse_api));
}
if(reverse_api_address != nullptr && *reverse_api_address != QString("")){
toJsonValue(QString("reverseAPIAddress"), reverse_api_address, obj, QString("QString"));
}
if(m_reverse_api_port_isSet){
obj->insert("reverseAPIPort", QJsonValue(reverse_api_port));
}
if(m_reverse_api_device_index_isSet){
obj->insert("reverseAPIDeviceIndex", QJsonValue(reverse_api_device_index));
}
return obj;
}
qint32
SWGMetisMISOSettings::getNbReceivers() {
return nb_receivers;
}
void
SWGMetisMISOSettings::setNbReceivers(qint32 nb_receivers) {
this->nb_receivers = nb_receivers;
this->m_nb_receivers_isSet = true;
}
qint32
SWGMetisMISOSettings::getRx1CenterFrequency() {
return rx1_center_frequency;
}
void
SWGMetisMISOSettings::setRx1CenterFrequency(qint32 rx1_center_frequency) {
this->rx1_center_frequency = rx1_center_frequency;
this->m_rx1_center_frequency_isSet = true;
}
qint32
SWGMetisMISOSettings::getRx2CenterFrequency() {
return rx2_center_frequency;
}
void
SWGMetisMISOSettings::setRx2CenterFrequency(qint32 rx2_center_frequency) {
this->rx2_center_frequency = rx2_center_frequency;
this->m_rx2_center_frequency_isSet = true;
}
qint32
SWGMetisMISOSettings::getRx3CenterFrequency() {
return rx3_center_frequency;
}
void
SWGMetisMISOSettings::setRx3CenterFrequency(qint32 rx3_center_frequency) {
this->rx3_center_frequency = rx3_center_frequency;
this->m_rx3_center_frequency_isSet = true;
}
qint32
SWGMetisMISOSettings::getRx4CenterFrequency() {
return rx4_center_frequency;
}
void
SWGMetisMISOSettings::setRx4CenterFrequency(qint32 rx4_center_frequency) {
this->rx4_center_frequency = rx4_center_frequency;
this->m_rx4_center_frequency_isSet = true;
}
qint32
SWGMetisMISOSettings::getTxCenterFrequency() {
return tx_center_frequency;
}
void
SWGMetisMISOSettings::setTxCenterFrequency(qint32 tx_center_frequency) {
this->tx_center_frequency = tx_center_frequency;
this->m_tx_center_frequency_isSet = true;
}
qint32
SWGMetisMISOSettings::getSampleRateIndex() {
return sample_rate_index;
}
void
SWGMetisMISOSettings::setSampleRateIndex(qint32 sample_rate_index) {
this->sample_rate_index = sample_rate_index;
this->m_sample_rate_index_isSet = true;
}
qint32
SWGMetisMISOSettings::getLog2Decim() {
return log2_decim;
}
void
SWGMetisMISOSettings::setLog2Decim(qint32 log2_decim) {
this->log2_decim = log2_decim;
this->m_log2_decim_isSet = true;
}
qint32
SWGMetisMISOSettings::getPreamp() {
return preamp;
}
void
SWGMetisMISOSettings::setPreamp(qint32 preamp) {
this->preamp = preamp;
this->m_preamp_isSet = true;
}
qint32
SWGMetisMISOSettings::getRandom() {
return random;
}
void
SWGMetisMISOSettings::setRandom(qint32 random) {
this->random = random;
this->m_random_isSet = true;
}
qint32
SWGMetisMISOSettings::getDither() {
return dither;
}
void
SWGMetisMISOSettings::setDither(qint32 dither) {
this->dither = dither;
this->m_dither_isSet = true;
}
qint32
SWGMetisMISOSettings::getDuplex() {
return duplex;
}
void
SWGMetisMISOSettings::setDuplex(qint32 duplex) {
this->duplex = duplex;
this->m_duplex_isSet = true;
}
qint32
SWGMetisMISOSettings::getDcBlock() {
return dc_block;
}
void
SWGMetisMISOSettings::setDcBlock(qint32 dc_block) {
this->dc_block = dc_block;
this->m_dc_block_isSet = true;
}
qint32
SWGMetisMISOSettings::getIqCorrection() {
return iq_correction;
}
void
SWGMetisMISOSettings::setIqCorrection(qint32 iq_correction) {
this->iq_correction = iq_correction;
this->m_iq_correction_isSet = true;
}
qint32
SWGMetisMISOSettings::getUseReverseApi() {
return use_reverse_api;
}
void
SWGMetisMISOSettings::setUseReverseApi(qint32 use_reverse_api) {
this->use_reverse_api = use_reverse_api;
this->m_use_reverse_api_isSet = true;
}
QString*
SWGMetisMISOSettings::getReverseApiAddress() {
return reverse_api_address;
}
void
SWGMetisMISOSettings::setReverseApiAddress(QString* reverse_api_address) {
this->reverse_api_address = reverse_api_address;
this->m_reverse_api_address_isSet = true;
}
qint32
SWGMetisMISOSettings::getReverseApiPort() {
return reverse_api_port;
}
void
SWGMetisMISOSettings::setReverseApiPort(qint32 reverse_api_port) {
this->reverse_api_port = reverse_api_port;
this->m_reverse_api_port_isSet = true;
}
qint32
SWGMetisMISOSettings::getReverseApiDeviceIndex() {
return reverse_api_device_index;
}
void
SWGMetisMISOSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) {
this->reverse_api_device_index = reverse_api_device_index;
this->m_reverse_api_device_index_isSet = true;
}
bool
SWGMetisMISOSettings::isSet(){
bool isObjectUpdated = false;
do{
if(m_nb_receivers_isSet){
isObjectUpdated = true; break;
}
if(m_rx1_center_frequency_isSet){
isObjectUpdated = true; break;
}
if(m_rx2_center_frequency_isSet){
isObjectUpdated = true; break;
}
if(m_rx3_center_frequency_isSet){
isObjectUpdated = true; break;
}
if(m_rx4_center_frequency_isSet){
isObjectUpdated = true; break;
}
if(m_tx_center_frequency_isSet){
isObjectUpdated = true; break;
}
if(m_sample_rate_index_isSet){
isObjectUpdated = true; break;
}
if(m_log2_decim_isSet){
isObjectUpdated = true; break;
}
if(m_preamp_isSet){
isObjectUpdated = true; break;
}
if(m_random_isSet){
isObjectUpdated = true; break;
}
if(m_dither_isSet){
isObjectUpdated = true; break;
}
if(m_duplex_isSet){
isObjectUpdated = true; break;
}
if(m_dc_block_isSet){
isObjectUpdated = true; break;
}
if(m_iq_correction_isSet){
isObjectUpdated = true; break;
}
if(m_use_reverse_api_isSet){
isObjectUpdated = true; break;
}
if(reverse_api_address && *reverse_api_address != QString("")){
isObjectUpdated = true; break;
}
if(m_reverse_api_port_isSet){
isObjectUpdated = true; break;
}
if(m_reverse_api_device_index_isSet){
isObjectUpdated = true; break;
}
}while(false);
return isObjectUpdated;
}
}

View File

@ -0,0 +1,161 @@
/**
* SDRangel
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
*
* OpenAPI spec version: 5.9.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/*
* SWGMetisMISOSettings.h
*
* MetisMISOSettings
*/
#ifndef SWGMetisMISOSettings_H_
#define SWGMetisMISOSettings_H_
#include <QJsonObject>
#include <QString>
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGMetisMISOSettings: public SWGObject {
public:
SWGMetisMISOSettings();
SWGMetisMISOSettings(QString* json);
virtual ~SWGMetisMISOSettings();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGMetisMISOSettings* fromJson(QString &jsonString) override;
qint32 getNbReceivers();
void setNbReceivers(qint32 nb_receivers);
qint32 getRx1CenterFrequency();
void setRx1CenterFrequency(qint32 rx1_center_frequency);
qint32 getRx2CenterFrequency();
void setRx2CenterFrequency(qint32 rx2_center_frequency);
qint32 getRx3CenterFrequency();
void setRx3CenterFrequency(qint32 rx3_center_frequency);
qint32 getRx4CenterFrequency();
void setRx4CenterFrequency(qint32 rx4_center_frequency);
qint32 getTxCenterFrequency();
void setTxCenterFrequency(qint32 tx_center_frequency);
qint32 getSampleRateIndex();
void setSampleRateIndex(qint32 sample_rate_index);
qint32 getLog2Decim();
void setLog2Decim(qint32 log2_decim);
qint32 getPreamp();
void setPreamp(qint32 preamp);
qint32 getRandom();
void setRandom(qint32 random);
qint32 getDither();
void setDither(qint32 dither);
qint32 getDuplex();
void setDuplex(qint32 duplex);
qint32 getDcBlock();
void setDcBlock(qint32 dc_block);
qint32 getIqCorrection();
void setIqCorrection(qint32 iq_correction);
qint32 getUseReverseApi();
void setUseReverseApi(qint32 use_reverse_api);
QString* getReverseApiAddress();
void setReverseApiAddress(QString* reverse_api_address);
qint32 getReverseApiPort();
void setReverseApiPort(qint32 reverse_api_port);
qint32 getReverseApiDeviceIndex();
void setReverseApiDeviceIndex(qint32 reverse_api_device_index);
virtual bool isSet() override;
private:
qint32 nb_receivers;
bool m_nb_receivers_isSet;
qint32 rx1_center_frequency;
bool m_rx1_center_frequency_isSet;
qint32 rx2_center_frequency;
bool m_rx2_center_frequency_isSet;
qint32 rx3_center_frequency;
bool m_rx3_center_frequency_isSet;
qint32 rx4_center_frequency;
bool m_rx4_center_frequency_isSet;
qint32 tx_center_frequency;
bool m_tx_center_frequency_isSet;
qint32 sample_rate_index;
bool m_sample_rate_index_isSet;
qint32 log2_decim;
bool m_log2_decim_isSet;
qint32 preamp;
bool m_preamp_isSet;
qint32 random;
bool m_random_isSet;
qint32 dither;
bool m_dither_isSet;
qint32 duplex;
bool m_duplex_isSet;
qint32 dc_block;
bool m_dc_block_isSet;
qint32 iq_correction;
bool m_iq_correction_isSet;
qint32 use_reverse_api;
bool m_use_reverse_api_isSet;
QString* reverse_api_address;
bool m_reverse_api_address_isSet;
qint32 reverse_api_port;
bool m_reverse_api_port_isSet;
qint32 reverse_api_device_index;
bool m_reverse_api_device_index_isSet;
};
}
#endif /* SWGMetisMISOSettings_H_ */

View File

@ -0,0 +1,476 @@
/**
* SDRangel
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
*
* OpenAPI spec version: 5.9.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
#include "SWGMetisMiSoStreamSettings.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGMetisMiSoStreamSettings::SWGMetisMiSoStreamSettings(QString* json) {
init();
this->fromJson(*json);
}
SWGMetisMiSoStreamSettings::SWGMetisMiSoStreamSettings() {
stream_index = 0;
m_stream_index_isSet = false;
center_frequency = 0;
m_center_frequency_isSet = false;
frequency_shift = 0;
m_frequency_shift_isSet = false;
sample_rate = 0;
m_sample_rate_isSet = false;
log2_decim = 0;
m_log2_decim_isSet = false;
fc_pos = 0;
m_fc_pos_isSet = false;
sample_size_index = 0;
m_sample_size_index_isSet = false;
amplitude_bits = 0;
m_amplitude_bits_isSet = false;
auto_corr_options = 0;
m_auto_corr_options_isSet = false;
modulation = 0;
m_modulation_isSet = false;
modulation_tone = 0;
m_modulation_tone_isSet = false;
am_modulation = 0;
m_am_modulation_isSet = false;
fm_deviation = 0;
m_fm_deviation_isSet = false;
dc_factor = 0.0f;
m_dc_factor_isSet = false;
i_factor = 0.0f;
m_i_factor_isSet = false;
q_factor = 0.0f;
m_q_factor_isSet = false;
phase_imbalance = 0.0f;
m_phase_imbalance_isSet = false;
}
SWGMetisMiSoStreamSettings::~SWGMetisMiSoStreamSettings() {
this->cleanup();
}
void
SWGMetisMiSoStreamSettings::init() {
stream_index = 0;
m_stream_index_isSet = false;
center_frequency = 0;
m_center_frequency_isSet = false;
frequency_shift = 0;
m_frequency_shift_isSet = false;
sample_rate = 0;
m_sample_rate_isSet = false;
log2_decim = 0;
m_log2_decim_isSet = false;
fc_pos = 0;
m_fc_pos_isSet = false;
sample_size_index = 0;
m_sample_size_index_isSet = false;
amplitude_bits = 0;
m_amplitude_bits_isSet = false;
auto_corr_options = 0;
m_auto_corr_options_isSet = false;
modulation = 0;
m_modulation_isSet = false;
modulation_tone = 0;
m_modulation_tone_isSet = false;
am_modulation = 0;
m_am_modulation_isSet = false;
fm_deviation = 0;
m_fm_deviation_isSet = false;
dc_factor = 0.0f;
m_dc_factor_isSet = false;
i_factor = 0.0f;
m_i_factor_isSet = false;
q_factor = 0.0f;
m_q_factor_isSet = false;
phase_imbalance = 0.0f;
m_phase_imbalance_isSet = false;
}
void
SWGMetisMiSoStreamSettings::cleanup() {
}
SWGMetisMiSoStreamSettings*
SWGMetisMiSoStreamSettings::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGMetisMiSoStreamSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&stream_index, pJson["streamIndex"], "qint32", "");
::SWGSDRangel::setValue(&center_frequency, pJson["centerFrequency"], "qint32", "");
::SWGSDRangel::setValue(&frequency_shift, pJson["frequencyShift"], "qint32", "");
::SWGSDRangel::setValue(&sample_rate, pJson["sampleRate"], "qint32", "");
::SWGSDRangel::setValue(&log2_decim, pJson["log2Decim"], "qint32", "");
::SWGSDRangel::setValue(&fc_pos, pJson["fcPos"], "qint32", "");
::SWGSDRangel::setValue(&sample_size_index, pJson["sampleSizeIndex"], "qint32", "");
::SWGSDRangel::setValue(&amplitude_bits, pJson["amplitudeBits"], "qint32", "");
::SWGSDRangel::setValue(&auto_corr_options, pJson["autoCorrOptions"], "qint32", "");
::SWGSDRangel::setValue(&modulation, pJson["modulation"], "qint32", "");
::SWGSDRangel::setValue(&modulation_tone, pJson["modulationTone"], "qint32", "");
::SWGSDRangel::setValue(&am_modulation, pJson["amModulation"], "qint32", "");
::SWGSDRangel::setValue(&fm_deviation, pJson["fmDeviation"], "qint32", "");
::SWGSDRangel::setValue(&dc_factor, pJson["dcFactor"], "float", "");
::SWGSDRangel::setValue(&i_factor, pJson["iFactor"], "float", "");
::SWGSDRangel::setValue(&q_factor, pJson["qFactor"], "float", "");
::SWGSDRangel::setValue(&phase_imbalance, pJson["phaseImbalance"], "float", "");
}
QString
SWGMetisMiSoStreamSettings::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGMetisMiSoStreamSettings::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if(m_stream_index_isSet){
obj->insert("streamIndex", QJsonValue(stream_index));
}
if(m_center_frequency_isSet){
obj->insert("centerFrequency", QJsonValue(center_frequency));
}
if(m_frequency_shift_isSet){
obj->insert("frequencyShift", QJsonValue(frequency_shift));
}
if(m_sample_rate_isSet){
obj->insert("sampleRate", QJsonValue(sample_rate));
}
if(m_log2_decim_isSet){
obj->insert("log2Decim", QJsonValue(log2_decim));
}
if(m_fc_pos_isSet){
obj->insert("fcPos", QJsonValue(fc_pos));
}
if(m_sample_size_index_isSet){
obj->insert("sampleSizeIndex", QJsonValue(sample_size_index));
}
if(m_amplitude_bits_isSet){
obj->insert("amplitudeBits", QJsonValue(amplitude_bits));
}
if(m_auto_corr_options_isSet){
obj->insert("autoCorrOptions", QJsonValue(auto_corr_options));
}
if(m_modulation_isSet){
obj->insert("modulation", QJsonValue(modulation));
}
if(m_modulation_tone_isSet){
obj->insert("modulationTone", QJsonValue(modulation_tone));
}
if(m_am_modulation_isSet){
obj->insert("amModulation", QJsonValue(am_modulation));
}
if(m_fm_deviation_isSet){
obj->insert("fmDeviation", QJsonValue(fm_deviation));
}
if(m_dc_factor_isSet){
obj->insert("dcFactor", QJsonValue(dc_factor));
}
if(m_i_factor_isSet){
obj->insert("iFactor", QJsonValue(i_factor));
}
if(m_q_factor_isSet){
obj->insert("qFactor", QJsonValue(q_factor));
}
if(m_phase_imbalance_isSet){
obj->insert("phaseImbalance", QJsonValue(phase_imbalance));
}
return obj;
}
qint32
SWGMetisMiSoStreamSettings::getStreamIndex() {
return stream_index;
}
void
SWGMetisMiSoStreamSettings::setStreamIndex(qint32 stream_index) {
this->stream_index = stream_index;
this->m_stream_index_isSet = true;
}
qint32
SWGMetisMiSoStreamSettings::getCenterFrequency() {
return center_frequency;
}
void
SWGMetisMiSoStreamSettings::setCenterFrequency(qint32 center_frequency) {
this->center_frequency = center_frequency;
this->m_center_frequency_isSet = true;
}
qint32
SWGMetisMiSoStreamSettings::getFrequencyShift() {
return frequency_shift;
}
void
SWGMetisMiSoStreamSettings::setFrequencyShift(qint32 frequency_shift) {
this->frequency_shift = frequency_shift;
this->m_frequency_shift_isSet = true;
}
qint32
SWGMetisMiSoStreamSettings::getSampleRate() {
return sample_rate;
}
void
SWGMetisMiSoStreamSettings::setSampleRate(qint32 sample_rate) {
this->sample_rate = sample_rate;
this->m_sample_rate_isSet = true;
}
qint32
SWGMetisMiSoStreamSettings::getLog2Decim() {
return log2_decim;
}
void
SWGMetisMiSoStreamSettings::setLog2Decim(qint32 log2_decim) {
this->log2_decim = log2_decim;
this->m_log2_decim_isSet = true;
}
qint32
SWGMetisMiSoStreamSettings::getFcPos() {
return fc_pos;
}
void
SWGMetisMiSoStreamSettings::setFcPos(qint32 fc_pos) {
this->fc_pos = fc_pos;
this->m_fc_pos_isSet = true;
}
qint32
SWGMetisMiSoStreamSettings::getSampleSizeIndex() {
return sample_size_index;
}
void
SWGMetisMiSoStreamSettings::setSampleSizeIndex(qint32 sample_size_index) {
this->sample_size_index = sample_size_index;
this->m_sample_size_index_isSet = true;
}
qint32
SWGMetisMiSoStreamSettings::getAmplitudeBits() {
return amplitude_bits;
}
void
SWGMetisMiSoStreamSettings::setAmplitudeBits(qint32 amplitude_bits) {
this->amplitude_bits = amplitude_bits;
this->m_amplitude_bits_isSet = true;
}
qint32
SWGMetisMiSoStreamSettings::getAutoCorrOptions() {
return auto_corr_options;
}
void
SWGMetisMiSoStreamSettings::setAutoCorrOptions(qint32 auto_corr_options) {
this->auto_corr_options = auto_corr_options;
this->m_auto_corr_options_isSet = true;
}
qint32
SWGMetisMiSoStreamSettings::getModulation() {
return modulation;
}
void
SWGMetisMiSoStreamSettings::setModulation(qint32 modulation) {
this->modulation = modulation;
this->m_modulation_isSet = true;
}
qint32
SWGMetisMiSoStreamSettings::getModulationTone() {
return modulation_tone;
}
void
SWGMetisMiSoStreamSettings::setModulationTone(qint32 modulation_tone) {
this->modulation_tone = modulation_tone;
this->m_modulation_tone_isSet = true;
}
qint32
SWGMetisMiSoStreamSettings::getAmModulation() {
return am_modulation;
}
void
SWGMetisMiSoStreamSettings::setAmModulation(qint32 am_modulation) {
this->am_modulation = am_modulation;
this->m_am_modulation_isSet = true;
}
qint32
SWGMetisMiSoStreamSettings::getFmDeviation() {
return fm_deviation;
}
void
SWGMetisMiSoStreamSettings::setFmDeviation(qint32 fm_deviation) {
this->fm_deviation = fm_deviation;
this->m_fm_deviation_isSet = true;
}
float
SWGMetisMiSoStreamSettings::getDcFactor() {
return dc_factor;
}
void
SWGMetisMiSoStreamSettings::setDcFactor(float dc_factor) {
this->dc_factor = dc_factor;
this->m_dc_factor_isSet = true;
}
float
SWGMetisMiSoStreamSettings::getIFactor() {
return i_factor;
}
void
SWGMetisMiSoStreamSettings::setIFactor(float i_factor) {
this->i_factor = i_factor;
this->m_i_factor_isSet = true;
}
float
SWGMetisMiSoStreamSettings::getQFactor() {
return q_factor;
}
void
SWGMetisMiSoStreamSettings::setQFactor(float q_factor) {
this->q_factor = q_factor;
this->m_q_factor_isSet = true;
}
float
SWGMetisMiSoStreamSettings::getPhaseImbalance() {
return phase_imbalance;
}
void
SWGMetisMiSoStreamSettings::setPhaseImbalance(float phase_imbalance) {
this->phase_imbalance = phase_imbalance;
this->m_phase_imbalance_isSet = true;
}
bool
SWGMetisMiSoStreamSettings::isSet(){
bool isObjectUpdated = false;
do{
if(m_stream_index_isSet){
isObjectUpdated = true; break;
}
if(m_center_frequency_isSet){
isObjectUpdated = true; break;
}
if(m_frequency_shift_isSet){
isObjectUpdated = true; break;
}
if(m_sample_rate_isSet){
isObjectUpdated = true; break;
}
if(m_log2_decim_isSet){
isObjectUpdated = true; break;
}
if(m_fc_pos_isSet){
isObjectUpdated = true; break;
}
if(m_sample_size_index_isSet){
isObjectUpdated = true; break;
}
if(m_amplitude_bits_isSet){
isObjectUpdated = true; break;
}
if(m_auto_corr_options_isSet){
isObjectUpdated = true; break;
}
if(m_modulation_isSet){
isObjectUpdated = true; break;
}
if(m_modulation_tone_isSet){
isObjectUpdated = true; break;
}
if(m_am_modulation_isSet){
isObjectUpdated = true; break;
}
if(m_fm_deviation_isSet){
isObjectUpdated = true; break;
}
if(m_dc_factor_isSet){
isObjectUpdated = true; break;
}
if(m_i_factor_isSet){
isObjectUpdated = true; break;
}
if(m_q_factor_isSet){
isObjectUpdated = true; break;
}
if(m_phase_imbalance_isSet){
isObjectUpdated = true; break;
}
}while(false);
return isObjectUpdated;
}
}

View File

@ -0,0 +1,154 @@
/**
* SDRangel
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
*
* OpenAPI spec version: 5.9.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/*
* SWGMetisMiSoStreamSettings.h
*
* MetisMiSoStreamSettings
*/
#ifndef SWGMetisMiSoStreamSettings_H_
#define SWGMetisMiSoStreamSettings_H_
#include <QJsonObject>
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGMetisMiSoStreamSettings: public SWGObject {
public:
SWGMetisMiSoStreamSettings();
SWGMetisMiSoStreamSettings(QString* json);
virtual ~SWGMetisMiSoStreamSettings();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGMetisMiSoStreamSettings* fromJson(QString &jsonString) override;
qint32 getStreamIndex();
void setStreamIndex(qint32 stream_index);
qint32 getCenterFrequency();
void setCenterFrequency(qint32 center_frequency);
qint32 getFrequencyShift();
void setFrequencyShift(qint32 frequency_shift);
qint32 getSampleRate();
void setSampleRate(qint32 sample_rate);
qint32 getLog2Decim();
void setLog2Decim(qint32 log2_decim);
qint32 getFcPos();
void setFcPos(qint32 fc_pos);
qint32 getSampleSizeIndex();
void setSampleSizeIndex(qint32 sample_size_index);
qint32 getAmplitudeBits();
void setAmplitudeBits(qint32 amplitude_bits);
qint32 getAutoCorrOptions();
void setAutoCorrOptions(qint32 auto_corr_options);
qint32 getModulation();
void setModulation(qint32 modulation);
qint32 getModulationTone();
void setModulationTone(qint32 modulation_tone);
qint32 getAmModulation();
void setAmModulation(qint32 am_modulation);
qint32 getFmDeviation();
void setFmDeviation(qint32 fm_deviation);
float getDcFactor();
void setDcFactor(float dc_factor);
float getIFactor();
void setIFactor(float i_factor);
float getQFactor();
void setQFactor(float q_factor);
float getPhaseImbalance();
void setPhaseImbalance(float phase_imbalance);
virtual bool isSet() override;
private:
qint32 stream_index;
bool m_stream_index_isSet;
qint32 center_frequency;
bool m_center_frequency_isSet;
qint32 frequency_shift;
bool m_frequency_shift_isSet;
qint32 sample_rate;
bool m_sample_rate_isSet;
qint32 log2_decim;
bool m_log2_decim_isSet;
qint32 fc_pos;
bool m_fc_pos_isSet;
qint32 sample_size_index;
bool m_sample_size_index_isSet;
qint32 amplitude_bits;
bool m_amplitude_bits_isSet;
qint32 auto_corr_options;
bool m_auto_corr_options_isSet;
qint32 modulation;
bool m_modulation_isSet;
qint32 modulation_tone;
bool m_modulation_tone_isSet;
qint32 am_modulation;
bool m_am_modulation_isSet;
qint32 fm_deviation;
bool m_fm_deviation_isSet;
float dc_factor;
bool m_dc_factor_isSet;
float i_factor;
bool m_i_factor_isSet;
float q_factor;
bool m_q_factor_isSet;
float phase_imbalance;
bool m_phase_imbalance_isSet;
};
}
#endif /* SWGMetisMiSoStreamSettings_H_ */

View File

@ -122,6 +122,7 @@
#include "SWGLocalSourceSettings.h"
#include "SWGLocationInformation.h"
#include "SWGLoggingInfo.h"
#include "SWGMetisMISOSettings.h"
#include "SWGNFMDemodReport.h"
#include "SWGNFMDemodSettings.h"
#include "SWGNFMModReport.h"
@ -525,6 +526,9 @@ namespace SWGSDRangel {
if(QString("SWGLoggingInfo").compare(type) == 0) {
return new SWGLoggingInfo();
}
if(QString("SWGMetisMISOSettings").compare(type) == 0) {
return new SWGMetisMISOSettings();
}
if(QString("SWGNFMDemodReport").compare(type) == 0) {
return new SWGNFMDemodReport();
}