1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-29 19:28:47 -05:00
sdrangel/plugins/channelrx/remotetcpsink/remotetcpsinksink.cpp
2024-02-18 19:57:00 +01:00

690 lines
28 KiB
C++

///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022-2023 Jon Beniston, M7RCE <jon@beniston.com> //
// Copyright (C) 2022 Jiří Pinkava <jiri.pinkava@rossum.ai> //
// //
// 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 <QMutexLocker>
#include <QThread>
#include "channel/channelwebapiutils.h"
#include "dsp/hbfilterchainconverter.h"
#include "device/deviceapi.h"
#include "util/timeutil.h"
#include "maincore.h"
#include "remotetcpsinksink.h"
#include "remotetcpsink.h"
#include "remotetcpsinkbaseband.h"
RemoteTCPSinkSink::RemoteTCPSinkSink() :
m_running(false),
m_messageQueueToGUI(nullptr),
m_messageQueueToChannel(nullptr),
m_channelFrequencyOffset(0),
m_channelSampleRate(48000),
m_linearGain(1.0f),
m_server(nullptr)
{
qDebug("RemoteTCPSinkSink::RemoteTCPSinkSink");
applySettings(m_settings, QStringList(), true);
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
}
RemoteTCPSinkSink::~RemoteTCPSinkSink()
{
stop();
}
void RemoteTCPSinkSink::start()
{
qDebug("RemoteTCPSinkSink::start");
if (m_running) {
return;
}
connect(thread(), SIGNAL(started()), this, SLOT(started()));
connect(thread(), SIGNAL(finished()), this, SLOT(finished()));
m_running = true;
}
void RemoteTCPSinkSink::stop()
{
qDebug("RemoteTCPSinkSink::stop");
m_running = false;
}
void RemoteTCPSinkSink::started()
{
QMutexLocker mutexLocker(&m_mutex);
startServer();
disconnect(thread(), SIGNAL(started()), this, SLOT(started()));
}
void RemoteTCPSinkSink::finished()
{
QMutexLocker mutexLocker(&m_mutex);
stopServer();
disconnect(thread(), SIGNAL(finished()), this, SLOT(finished()));
m_running = false;
}
void RemoteTCPSinkSink::init()
{
}
void RemoteTCPSinkSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
{
QMutexLocker mutexLocker(&m_mutex);
if (m_clients.size() > 0)
{
Complex ci;
int bytes = 0;
for (SampleVector::const_iterator it = begin; it != end; ++it)
{
Complex c(it->real(), it->imag());
c *= m_nco.nextIQ();
if (m_interpolatorDistance < 1.0f) // interpolate
{
while (!m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci))
{
processOneSample(ci);
bytes += 2 * m_settings.m_sampleBits / 8;
m_interpolatorDistanceRemain += m_interpolatorDistance;
}
}
else // decimate
{
if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci))
{
processOneSample(ci);
bytes += 2 * m_settings.m_sampleBits / 8;
m_interpolatorDistanceRemain += m_interpolatorDistance;
}
}
}
if (m_bwDateTime.isValid())
{
QDateTime currentDateTime = QDateTime::currentDateTime();
qint64 msecs = m_bwDateTime.msecsTo(currentDateTime) ;
if (msecs > 1000)
{
float bw = (8*m_bwBytes)/(msecs/1000.0f);
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(RemoteTCPSink::MsgReportBW::create(bw));
}
m_bwDateTime = currentDateTime;
m_bwBytes = bytes;
}
else
{
m_bwBytes += bytes;
}
}
else
{
m_bwDateTime = QDateTime::currentDateTime();
m_bwBytes = bytes;
}
}
}
void RemoteTCPSinkSink::processOneSample(Complex &ci)
{
if (m_settings.m_sampleBits == 8)
{
// Transmit data as per rtl_tcp - Interleaved unsigned 8-bit IQ
quint8 iqBuf[2];
iqBuf[0] = ((int)(ci.real() / SDR_RX_SCALEF * 256.0f * m_linearGain)) + 128;
iqBuf[1] = ((int)(ci.imag() / SDR_RX_SCALEF * 256.0f * m_linearGain)) + 128;
for (auto client : m_clients) {
client->write((const char *)iqBuf, sizeof(iqBuf));
}
}
else if (m_settings.m_sampleBits == 16)
{
// Interleaved little-endian signed 16-bit IQ
quint8 iqBuf[2*2];
qint32 i, q;
i = ((qint32)(ci.real() / SDR_RX_SCALEF * 65536.0f * m_linearGain));
q = ((qint32)(ci.imag() / SDR_RX_SCALEF * 65536.0f * m_linearGain));
iqBuf[1] = (i >> 8) & 0xff;
iqBuf[0] = i & 0xff;
iqBuf[3] = (q >> 8) & 0xff;
iqBuf[2] = q & 0xff;
for (auto client : m_clients) {
client->write((const char *)iqBuf, sizeof(iqBuf));
}
}
else if (m_settings.m_sampleBits == 24)
{
// Interleaved little-endian signed 24-bit IQ
quint8 iqBuf[3*2];
qint32 i, q;
i = ((qint32)(ci.real() * m_linearGain));
q = ((qint32)(ci.imag() * m_linearGain));
iqBuf[2] = (i >> 16) & 0xff;
iqBuf[1] = (i >> 8) & 0xff;
iqBuf[0] = i & 0xff;
iqBuf[5] = (q >> 16) & 0xff;
iqBuf[4] = (q >> 8) & 0xff;
iqBuf[3] = q & 0xff;
for (auto client : m_clients) {
client->write((const char *)iqBuf, sizeof(iqBuf));
}
}
else
{
// Interleaved little-endian signed 32-bit IQ
quint8 iqBuf[4*2];
qint32 i, q;
i = ((qint32)(ci.real() * m_linearGain));
q = ((qint32)(ci.imag() * m_linearGain));
iqBuf[3] = (i >> 24) & 0xff;
iqBuf[2] = (i >> 16) & 0xff;
iqBuf[1] = (i >> 8) & 0xff;
iqBuf[0] = i & 0xff;
iqBuf[7] = (q >> 24) & 0xff;
iqBuf[6] = (q >> 16) & 0xff;
iqBuf[5] = (q >> 8) & 0xff;
iqBuf[4] = q & 0xff;
for (auto client : m_clients) {
client->write((const char *)iqBuf, sizeof(iqBuf));
}
}
}
void RemoteTCPSinkSink::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force)
{
qDebug() << "RemoteTCPSinkSink::applyChannelSettings:"
<< " channelSampleRate: " << channelSampleRate
<< " channelFrequencyOffset: " << channelFrequencyOffset;
if ((m_channelFrequencyOffset != channelFrequencyOffset) ||
(m_channelSampleRate != channelSampleRate) || force)
{
m_nco.setFreq(-channelFrequencyOffset, channelSampleRate);
}
if ((m_channelSampleRate != channelSampleRate) || force)
{
m_interpolator.create(16, channelSampleRate, m_settings.m_channelSampleRate / 2.0);
m_interpolatorDistance = (Real) channelSampleRate / (Real) m_settings.m_channelSampleRate;
m_interpolatorDistanceRemain = m_interpolatorDistance;
}
m_channelSampleRate = channelSampleRate;
m_channelFrequencyOffset = channelFrequencyOffset;
}
void RemoteTCPSinkSink::applySettings(const RemoteTCPSinkSettings& settings, const QStringList& settingsKeys, bool force, bool remoteChange)
{
QMutexLocker mutexLocker(&m_mutex);
qDebug() << "RemoteTCPSinkSink::applySettings:" << settings.getDebugString(settingsKeys, force) << " force: " << force;
if (settingsKeys.contains("gain") || force)
{
m_linearGain = powf(10.0f, settings.m_gain/20.0f);
}
if (settingsKeys.contains("channelSampleRate") || force)
{
m_interpolator.create(16, m_channelSampleRate, settings.m_channelSampleRate / 2.0);
m_interpolatorDistance = (Real) m_channelSampleRate / (Real) settings.m_channelSampleRate;
m_interpolatorDistanceRemain = m_interpolatorDistance;
}
// Do clients need to reconnect to get these updated settings?
bool restart = (settingsKeys.contains("dataAddress") && (m_settings.m_dataAddress != settings.m_dataAddress))
|| (settingsKeys.contains("dataPort") && (m_settings.m_dataPort != settings.m_dataPort))
|| (settingsKeys.contains("sampleBits") && (m_settings.m_sampleBits != settings.m_sampleBits))
|| (settingsKeys.contains("protocol") && (m_settings.m_protocol != settings.m_protocol))
|| ( !remoteChange
&& (settingsKeys.contains("channelSampleRate") && (m_settings.m_channelSampleRate != settings.m_channelSampleRate))
);
if (force) {
m_settings = settings;
} else {
m_settings.applySettings(settingsKeys, settings);
}
if (m_running && restart) {
startServer();
}
}
void RemoteTCPSinkSink::startServer()
{
stopServer();
m_server = new QTcpServer(this);
if (!m_server->listen(QHostAddress(m_settings.m_dataAddress), m_settings.m_dataPort))
{
qCritical() << "RemoteTCPSink failed to listen on" << m_settings.m_dataAddress << "port" << m_settings.m_dataPort;
// FIXME: Report to GUI?
}
else
{
qInfo() << "RemoteTCPSink listening on" << m_settings.m_dataAddress << "port" << m_settings.m_dataPort;
connect(m_server, &QTcpServer::newConnection, this, &RemoteTCPSinkSink::acceptConnection);
}
}
void RemoteTCPSinkSink::stopServer()
{
for (auto client : m_clients)
{
qDebug() << "RemoteTCPSinkSink::stopServer: Closing connection to client";
client->close();
delete client;
}
if (m_clients.size() > 0)
{
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(RemoteTCPSink::MsgReportConnection::create(0));
}
m_clients.clear();
}
if (m_server)
{
qDebug() << "RemoteTCPSinkSink::stopServer: Closing old server";
m_server->close();
delete m_server;
m_server = nullptr;
}
}
RemoteTCPProtocol::Device RemoteTCPSinkSink::getDevice()
{
DeviceAPI *deviceAPI = MainCore::instance()->getDevice(m_deviceIndex);
if (deviceAPI)
{
QString id = deviceAPI->getHardwareId();
QHash<QString, RemoteTCPProtocol::Device> map = {
{"Airspy", RemoteTCPProtocol::AIRSPY},
{"AirspyHF", RemoteTCPProtocol::AIRSPY_HF},
{"AudioInput", RemoteTCPProtocol::AUDIO_INPUT},
{"BladeRF1", RemoteTCPProtocol::BLADE_RF1},
{"BladeRF2", RemoteTCPProtocol::BLADE_RF2},
{"FCDPro", RemoteTCPProtocol::FCD_PRO},
{"FCDProPlus", RemoteTCPProtocol::FCD_PRO_PLUS},
{"FileInput", RemoteTCPProtocol::FILE_INPUT},
{"HackRF", RemoteTCPProtocol::HACK_RF},
{"KiwiSDR", RemoteTCPProtocol::KIWI_SDR},
{"LimeSDR", RemoteTCPProtocol::LIME_SDR},
{"LocalInput", RemoteTCPProtocol::LOCAL_INPUT},
{"Perseus", RemoteTCPProtocol::PERSEUS},
{"PlutoSDR", RemoteTCPProtocol::PLUTO_SDR},
{"RemoteInput", RemoteTCPProtocol::REMOTE_INPUT},
{"RemoteTCPInput", RemoteTCPProtocol::REMOTE_TCP_INPUT},
{"SDRplay1", RemoteTCPProtocol::SDRPLAY_1},
{"SigMFFileInput", RemoteTCPProtocol::SIGMF_FILE_INPUT},
{"SoapySDR", RemoteTCPProtocol::SOAPY_SDR},
{"TestSource", RemoteTCPProtocol::TEST_SOURCE},
{"USRP", RemoteTCPProtocol::USRP},
{"XTRX", RemoteTCPProtocol::XTRX},
};
if (map.contains(id))
{
return map.value(id);
}
else if (id == "SDRplayV3")
{
QString deviceType;
if (ChannelWebAPIUtils::getDeviceReportValue(m_deviceIndex, "deviceType", deviceType))
{
QHash<QString, RemoteTCPProtocol::Device> sdrplayMap = {
{"RSP1", RemoteTCPProtocol::SDRPLAY_V3_RSP1},
{"RSP1A", RemoteTCPProtocol::SDRPLAY_V3_RSP1A},
{"RSP1B", RemoteTCPProtocol::SDRPLAY_V3_RSP1B},
{"RSP2", RemoteTCPProtocol::SDRPLAY_V3_RSP2},
{"RSPduo", RemoteTCPProtocol::SDRPLAY_V3_RSPDUO},
{"RSPdx", RemoteTCPProtocol::SDRPLAY_V3_RSPDX},
};
if (sdrplayMap.contains(deviceType)) {
return sdrplayMap.value(deviceType);
}
qDebug() << "RemoteTCPSinkSink::getDevice: Unknown SDRplayV3 deviceType: " << deviceType;
}
else
{
qDebug() << "RemoteTCPSinkSink::getDevice: Failed to get deviceType for SDRplayV3";
}
}
else if (id == "RTLSDR")
{
QString tunerType;
if (ChannelWebAPIUtils::getDeviceReportValue(m_deviceIndex, "tunerType", tunerType))
{
QHash<QString, RemoteTCPProtocol::Device> rtlsdrMap = {
{"E4000", RemoteTCPProtocol::RTLSDR_E4000},
{"FC0012", RemoteTCPProtocol::RTLSDR_FC0012},
{"FC0013", RemoteTCPProtocol::RTLSDR_FC0013},
{"FC2580", RemoteTCPProtocol::RTLSDR_FC2580},
{"R820T", RemoteTCPProtocol::RTLSDR_R820T},
{"R828D", RemoteTCPProtocol::RTLSDR_R828D},
};
if (rtlsdrMap.contains(tunerType)) {
return rtlsdrMap.value(tunerType);
}
qDebug() << "RemoteTCPSinkSink::getDevice: Unknown RTLSDR tunerType: " << tunerType;
}
else
{
qDebug() << "RemoteTCPSinkSink::getDevice: Failed to get tunerType for RTLSDR";
}
}
}
return RemoteTCPProtocol::UNKNOWN;
}
void RemoteTCPSinkSink::acceptConnection()
{
QMutexLocker mutexLocker(&m_mutex);
QTcpSocket *client = m_server->nextPendingConnection();
if (!client) {
qDebug() << "RemoteTCPSinkSink::acceptConnection: client is nullptr";
return;
}
m_clients.append(client);
connect(client, &QIODevice::readyRead, this, &RemoteTCPSinkSink::processCommand);
connect(client, SIGNAL(disconnected()), this, SLOT(disconnected()));
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
connect(client, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), this, &RemoteTCPSinkSink::errorOccurred);
#else
connect(client, &QAbstractSocket::errorOccurred, this, &RemoteTCPSinkSink::errorOccurred);
#endif
qDebug() << "RemoteTCPSinkSink::acceptConnection: client connected";
if (m_settings.m_protocol == RemoteTCPSinkSettings::RTL0)
{
quint8 metaData[RemoteTCPProtocol::m_rtl0MetaDataSize] = {'R', 'T', 'L', '0'};
RemoteTCPProtocol::encodeUInt32(&metaData[4], getDevice()); // Tuner ID
RemoteTCPProtocol::encodeUInt32(&metaData[8], 1); // Gain stages
client->write((const char *)metaData, sizeof(metaData));
}
else
{
quint8 metaData[RemoteTCPProtocol::m_sdraMetaDataSize] = {'S', 'D', 'R', 'A'};
RemoteTCPProtocol::encodeUInt32(&metaData[4], getDevice());
// Send device/channel settings, so they can be displayed in the remote GUI
double centerFrequency = 0.0;
qint32 ppmCorrection = 0;
quint32 flags = 0;
int biasTeeEnabled = false;
int directSampling = false;
int agc = false;
int dcOffsetRemoval = false;
int iqCorrection = false;
qint32 devSampleRate = 0;
qint32 log2Decim = 0;
qint32 gain[4] = {0, 0, 0, 0};
qint32 rfBW = 0;
ChannelWebAPIUtils::getCenterFrequency(m_deviceIndex, centerFrequency);
ChannelWebAPIUtils::getLOPpmCorrection(m_deviceIndex, ppmCorrection);
ChannelWebAPIUtils::getDevSampleRate(m_deviceIndex, devSampleRate);
ChannelWebAPIUtils::getSoftDecim(m_deviceIndex, log2Decim);
for (int i = 0; i < 4; i++) {
ChannelWebAPIUtils::getGain(m_deviceIndex, i, gain[i]);
}
ChannelWebAPIUtils::getRFBandwidth(m_deviceIndex, rfBW);
ChannelWebAPIUtils::getBiasTee(m_deviceIndex, biasTeeEnabled);
ChannelWebAPIUtils::getDeviceSetting(m_deviceIndex, "noModMode", directSampling);
ChannelWebAPIUtils::getAGC(m_deviceIndex, agc);
ChannelWebAPIUtils::getDCOffsetRemoval(m_deviceIndex, dcOffsetRemoval);
ChannelWebAPIUtils::getIQCorrection(m_deviceIndex, iqCorrection);
flags = (iqCorrection << 4)
| (dcOffsetRemoval << 3)
| (agc << 2)
| (directSampling << 1)
| biasTeeEnabled;
RemoteTCPProtocol::encodeUInt64(&metaData[8], (quint64)centerFrequency);
RemoteTCPProtocol::encodeUInt32(&metaData[16], ppmCorrection);
RemoteTCPProtocol::encodeUInt32(&metaData[20], flags);
RemoteTCPProtocol::encodeUInt32(&metaData[24], devSampleRate);
RemoteTCPProtocol::encodeUInt32(&metaData[28], log2Decim);
RemoteTCPProtocol::encodeInt16(&metaData[32], gain[0]);
RemoteTCPProtocol::encodeInt16(&metaData[34], gain[1]);
RemoteTCPProtocol::encodeInt16(&metaData[36], gain[2]);
RemoteTCPProtocol::encodeInt16(&metaData[38], gain[3]);
RemoteTCPProtocol::encodeUInt32(&metaData[40], rfBW);
RemoteTCPProtocol::encodeInt32(&metaData[44], m_settings.m_inputFrequencyOffset);
RemoteTCPProtocol::encodeUInt32(&metaData[48], m_settings.m_gain);
RemoteTCPProtocol::encodeUInt32(&metaData[52], m_settings.m_channelSampleRate);
RemoteTCPProtocol::encodeUInt32(&metaData[56], m_settings.m_sampleBits);
// Send API port? Not accessible via MainCore
client->write((const char *)metaData, sizeof(metaData));
}
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(RemoteTCPSink::MsgReportConnection::create(m_clients.size()));
}
}
void RemoteTCPSinkSink::disconnected()
{
QMutexLocker mutexLocker(&m_mutex);
qDebug() << "RemoteTCPSinkSink::disconnected";
QTcpSocket *client = (QTcpSocket*)sender();
client->deleteLater();
m_clients.removeAll(client);
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(RemoteTCPSink::MsgReportConnection::create(m_clients.size()));
}
}
void RemoteTCPSinkSink::errorOccurred(QAbstractSocket::SocketError socketError)
{
qDebug() << "RemoteTCPSinkSink::errorOccurred: " << socketError;
/*if (m_msgQueueToFeature)
{
RemoteTCPSinkSink::MsgReportWorker *msg = RemoteTCPSinkSink::MsgReportWorker::create(m_socket.errorString() + " " + socketError);
m_msgQueueToFeature->push(msg);
}*/
}
void RemoteTCPSinkSink::processCommand()
{
QMutexLocker mutexLocker(&m_mutex);
QTcpSocket *client = (QTcpSocket*)sender();
RemoteTCPSinkSettings settings = m_settings;
quint8 cmd[5];
while (client && (client->bytesAvailable() >= (qint64)sizeof(cmd)))
{
int len = client->read((char *)cmd, sizeof(cmd));
if (len == sizeof(cmd))
{
switch (cmd[0])
{
case RemoteTCPProtocol::setCenterFrequency:
{
quint64 centerFrequency = RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set center frequency " << centerFrequency;
ChannelWebAPIUtils::setCenterFrequency(m_deviceIndex, (double)centerFrequency);
break;
}
case RemoteTCPProtocol::setSampleRate:
{
int sampleRate = RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set sample rate " << sampleRate;
ChannelWebAPIUtils::setDevSampleRate(m_deviceIndex, sampleRate);
if (m_settings.m_protocol == RemoteTCPSinkSettings::RTL0)
{
// Match channel sample rate with device sample rate for RTL0 protocol
ChannelWebAPIUtils::setSoftDecim(m_deviceIndex, 0);
settings.m_channelSampleRate = sampleRate;
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(RemoteTCPSink::MsgConfigureRemoteTCPSink::create(settings, {"channelSampleRate"}, false, true));
}
if (m_messageQueueToChannel) {
m_messageQueueToChannel->push(RemoteTCPSink::MsgConfigureRemoteTCPSink::create(settings, {"channelSampleRate"}, false, true));
}
}
break;
}
case RemoteTCPProtocol::setTunerGainMode:
// SDRangel's rtlsdr sample source always has this fixed as 1, so nothing to do
break;
case RemoteTCPProtocol::setTunerGain: // gain is gain in 10th of a dB
{
int gain = RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set gain " << gain;
ChannelWebAPIUtils::setGain(m_deviceIndex, 0, gain);
break;
}
case RemoteTCPProtocol::setFrequencyCorrection:
{
int ppm = RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set LO ppm correction " << ppm;
ChannelWebAPIUtils::setLOPpmCorrection(m_deviceIndex, ppm);
break;
}
case RemoteTCPProtocol::setTunerIFGain:
{
int v = RemoteTCPProtocol::extractUInt32(&cmd[1]);
int gain = (int)(qint16)(v & 0xffff);
int stage = (v >> 16) & 0xffff;
ChannelWebAPIUtils::setGain(m_deviceIndex, stage, gain);
break;
}
case RemoteTCPProtocol::setAGCMode:
{
int agc = RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set AGC " << agc;
ChannelWebAPIUtils::setAGC(m_deviceIndex, agc);
break;
}
case RemoteTCPProtocol::setDirectSampling:
{
int ds = RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set direct sampling " << ds;
ChannelWebAPIUtils::patchDeviceSetting(m_deviceIndex, "noModMode", ds); // RTLSDR only
break;
}
case RemoteTCPProtocol::setBiasTee:
{
int biasTee = RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set bias tee " << biasTee;
ChannelWebAPIUtils::setBiasTee(m_deviceIndex, biasTee);
break;
}
case RemoteTCPProtocol::setTunerBandwidth:
{
int rfBW = RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set tuner bandwidth " << rfBW;
ChannelWebAPIUtils::setRFBandwidth(m_deviceIndex, rfBW);
break;
}
case RemoteTCPProtocol::setDecimation:
{
int dec = RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set decimation " << dec;
ChannelWebAPIUtils::setSoftDecim(m_deviceIndex, dec);
break;
}
case RemoteTCPProtocol::setDCOffsetRemoval:
{
int dc = RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set DC offset removal " << dc;
ChannelWebAPIUtils::setDCOffsetRemoval(m_deviceIndex, dc);
break;
}
case RemoteTCPProtocol::setIQCorrection:
{
int iq = RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set IQ correction " << iq;
ChannelWebAPIUtils::setIQCorrection(m_deviceIndex, iq);
break;
}
case RemoteTCPProtocol::setChannelSampleRate:
{
int channelSampleRate = RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set channel sample rate " << channelSampleRate;
settings.m_channelSampleRate = channelSampleRate;
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(RemoteTCPSink::MsgConfigureRemoteTCPSink::create(settings, {"channelSampleRate"}, false, true));
}
if (m_messageQueueToChannel) {
m_messageQueueToChannel->push(RemoteTCPSink::MsgConfigureRemoteTCPSink::create(settings, {"channelSampleRate"}, false, true));
}
break;
}
case RemoteTCPProtocol::setChannelFreqOffset:
{
int offset = (int)RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set channel input frequency offset " << offset;
settings.m_inputFrequencyOffset = offset;
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(RemoteTCPSink::MsgConfigureRemoteTCPSink::create(settings, {"inputFrequencyOffset"}, false, true));
}
if (m_messageQueueToChannel) {
m_messageQueueToChannel->push(RemoteTCPSink::MsgConfigureRemoteTCPSink::create(settings, {"inputFrequencyOffset"}, false, true));
}
break;
}
case RemoteTCPProtocol::setChannelGain:
{
int gain = (int)RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set channel gain " << gain;
settings.m_gain = gain;
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(RemoteTCPSink::MsgConfigureRemoteTCPSink::create(settings, {"gain"}, false, true));
}
if (m_messageQueueToChannel) {
m_messageQueueToChannel->push(RemoteTCPSink::MsgConfigureRemoteTCPSink::create(settings, {"gain"}, false, true));
}
break;
}
case RemoteTCPProtocol::setSampleBitDepth:
{
int bits = RemoteTCPProtocol::extractUInt32(&cmd[1]);
qDebug() << "RemoteTCPSinkSink::processCommand: set sample bit depth " << bits;
settings.m_sampleBits = bits;
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(RemoteTCPSink::MsgConfigureRemoteTCPSink::create(settings, {"sampleBits"}, false, true));
}
if (m_messageQueueToChannel) {
m_messageQueueToChannel->push(RemoteTCPSink::MsgConfigureRemoteTCPSink::create(settings, {"sampleBits"}, false, true));
}
break;
}
default:
qDebug() << "RemoteTCPSinkSink::processCommand: unknown command " << cmd[0];
break;
}
}
else
{
qDebug() << "RemoteTCPSinkSink::processCommand: read only " << len << " bytes - Expecting " << sizeof(cmd);
}
}
}