1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-12-25 04:03:30 -05:00

Remote input/sink implemented remote control (1)

This commit is contained in:
f4exb 2021-12-24 21:06:15 +01:00
parent 247ae2679d
commit 9bb3a273b3
23 changed files with 613 additions and 87 deletions

View File

@ -35,6 +35,7 @@
#include "dsp/hbfilterchainconverter.h"
#include "dsp/devicesamplemimo.h"
#include "dsp/dspdevicesourceengine.h"
#include "dsp/devicesamplesource.h"
#include "device/deviceapi.h"
#include "feature/feature.h"
#include "settings/serializable.h"
@ -54,6 +55,7 @@ RemoteSink::RemoteSink(DeviceAPI *deviceAPI) :
m_basebandSampleRate(0)
{
setObjectName(m_channelId);
updateWithDeviceData();
m_basebandSink = new RemoteSinkBaseband();
m_basebandSink->moveToThread(&m_thread);
@ -130,6 +132,7 @@ bool RemoteSink::handleMessage(const Message& cmd)
m_basebandSampleRate = notif.getSampleRate();
qDebug() << "RemoteSink::handleMessage: DSPSignalNotification: m_basebandSampleRate:" << m_basebandSampleRate;
calculateFrequencyOffset();
updateWithDeviceData(); // Device center frequency and/or sample rate has changed
// Forward to the sink
DSPSignalNotification* msgToBaseband = new DSPSignalNotification(notif); // make a copy
@ -201,6 +204,17 @@ void RemoteSink::applySettings(const RemoteSinkSettings& settings, bool force)
reverseAPIKeys.append("title");
}
if ((m_settings.m_deviceCenterFrequency != settings.m_deviceCenterFrequency) || force)
{
reverseAPIKeys.append("deviceCenterFrequency");
if (m_deviceAPI->getSampleSource()) {
m_deviceAPI->getSampleSource()->setCenterFrequency(settings.m_deviceCenterFrequency);
} else if (m_deviceAPI->getSampleMIMO()) {
m_deviceAPI->getSampleMIMO()->setSourceCenterFrequency(settings.m_deviceCenterFrequency, settings.m_streamIndex);
}
}
if ((m_settings.m_log2Decim != settings.m_log2Decim) || force)
{
reverseAPIKeys.append("log2Decim");
@ -277,6 +291,15 @@ void RemoteSink::calculateFrequencyOffset()
m_frequencyOffset = m_basebandSampleRate * shiftFactor;
}
void RemoteSink::updateWithDeviceData()
{
if (m_deviceAPI->getSampleSource()) {
m_settings.m_deviceCenterFrequency = m_deviceAPI->getSampleSource()->getCenterFrequency();
} else if (m_deviceAPI->getSampleMIMO()) {
m_settings.m_deviceCenterFrequency = m_deviceAPI->getSampleMIMO()->getSourceCenterFrequency(m_settings.m_streamIndex);
}
}
int RemoteSink::webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
@ -334,6 +357,10 @@ void RemoteSink::webapiUpdateChannelSettings(
settings.m_nbTxBytes = response.getRemoteSinkSettings()->getNbTxBytes();
}
if (channelSettingsKeys.contains("deviceCenterFrequency")) {
settings.m_deviceCenterFrequency = response.getRemoteSinkSettings()->getDeviceCenterFrequency();
}
if (channelSettingsKeys.contains("dataAddress")) {
settings.m_dataAddress = *response.getRemoteSinkSettings()->getDataAddress();
}
@ -400,6 +427,7 @@ void RemoteSink::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& re
}
response.getRemoteSinkSettings()->setNbTxBytes(settings.m_nbTxBytes);
response.getRemoteSinkSettings()->setDeviceCenterFrequency(settings.m_deviceCenterFrequency);
response.getRemoteSinkSettings()->setDataPort(settings.m_dataPort);
response.getRemoteSinkSettings()->setRgbColor(settings.m_rgbColor);
@ -508,6 +536,9 @@ void RemoteSink::webapiFormatChannelSettings(
if (channelSettingsKeys.contains("nbTxBytes") || force) {
swgRemoteSinkSettings->setNbTxBytes(settings.m_nbTxBytes);
}
if (channelSettingsKeys.contains("deviceCenterFrequency") || force) {
swgRemoteSinkSettings->setDeviceCenterFrequency(settings.m_deviceCenterFrequency);
}
if (channelSettingsKeys.contains("dataAddress") || force) {
swgRemoteSinkSettings->setDataAddress(new QString(settings.m_dataAddress));
}

View File

@ -130,6 +130,7 @@ private:
void applySettings(const RemoteSinkSettings& settings, bool force = false);
static void validateFilterChainHash(RemoteSinkSettings& settings);
void calculateFrequencyOffset();
void updateWithDeviceData();
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const RemoteSinkSettings& settings, bool force);
void sendChannelSettings(
QList<MessageQueue*> *messageQueues,

View File

@ -39,7 +39,6 @@ void RemoteSinkSettings::resetToDefaults()
m_nbFECBlocks = 0;
m_nbTxBytes = 2;
m_deviceCenterFrequency = 0;
m_deviceSampleRate = 48000;
m_dataAddress = "127.0.0.1";
m_dataPort = 9090;
m_rgbColor = QColor(140, 4, 4).rgb();
@ -74,7 +73,6 @@ QByteArray RemoteSinkSettings::serialize() const
s.writeS32(14, m_streamIndex);
s.writeBlob(15, m_rollupState);
s.writeU64(16, m_deviceCenterFrequency);
s.writeU32(17, m_deviceSampleRate);
return s.final();
}
@ -134,7 +132,6 @@ bool RemoteSinkSettings::deserialize(const QByteArray& data)
d.readS32(14, &m_streamIndex, 0);
d.readBlob(15, &m_rollupState);
d.readU64(16, &m_deviceCenterFrequency, 0);
d.readU32(17, &m_deviceSampleRate, 48000);
return true;
}

View File

@ -34,7 +34,6 @@ struct RemoteSinkSettings
uint16_t m_nbFECBlocks;
uint32_t m_nbTxBytes;
quint64 m_deviceCenterFrequency;
uint32_t m_deviceSampleRate;
QString m_dataAddress;
uint16_t m_dataPort;
quint32 m_rgbColor;

View File

@ -131,8 +131,6 @@ void RemoteSinkSink::feed(const SampleVector::const_iterator& begin, const Sampl
metaData.m_sampleBits = getNbSampleBits();
metaData.m_nbOriginalBlocks = RemoteNbOrginalBlocks;
metaData.m_nbFECBlocks = m_nbBlocksFEC;
metaData.m_deviceCenterFrequency = m_deviceCenterFrequency;
metaData.m_basebandSampleRate = m_basebandSampleRate;
metaData.m_deviceIndex = m_deviceIndex % 256;
metaData.m_channelIndex = m_channelIndex % 256;
metaData.m_tv_sec = nowus / 1000000UL; // tv.tv_sec;
@ -164,8 +162,6 @@ void RemoteSinkSink::feed(const SampleVector::const_iterator& begin, const Sampl
<< ":" << (int) metaData.m_sampleBits
<< "|" << (int) metaData.m_nbOriginalBlocks
<< ":" << (int) metaData.m_nbFECBlocks
<< "|" << metaData.m_deviceCenterFrequency
<< ":" << metaData.m_basebandSampleRate
<< "|" << metaData.m_deviceIndex
<< ":" << metaData.m_channelIndex
<< "|" << metaData.m_tv_sec

View File

@ -218,8 +218,6 @@ void RemoteSourceSource::printMeta(const QString& header, RemoteMetaDataFEC *met
<< ":" << (int) metaData->m_sampleBits
<< ":" << (int) metaData->m_nbOriginalBlocks
<< ":" << (int) metaData->m_nbFECBlocks
<< "|" << metaData->m_deviceCenterFrequency
<< ":" << metaData->m_basebandSampleRate
<< "|" << metaData->m_deviceIndex
<< ":" << metaData->m_channelIndex
<< "|" << metaData->m_tv_sec

View File

@ -120,8 +120,6 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk
metaData.m_sampleBits = getNbSampleBits();
metaData.m_nbOriginalBlocks = RemoteNbOrginalBlocks;
metaData.m_nbFECBlocks = m_nbBlocksFEC;
metaData.m_deviceCenterFrequency = 0; // frequency not set by device
metaData.m_basebandSampleRate = m_sampleRate; // same as sample rate
metaData.m_deviceIndex = m_deviceIndex; // index of device set in the instance
metaData.m_channelIndex = 0; // irrelavant
metaData.m_tv_sec = nowus / 1000000UL; // tv.tv_sec;
@ -153,8 +151,6 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk
<< ":" << (int) metaData.m_sampleBits
<< "|" << (int) metaData.m_nbOriginalBlocks
<< ":" << (int) metaData.m_nbFECBlocks
<< "|" << metaData.m_deviceCenterFrequency
<< ":" << metaData.m_basebandSampleRate
<< "|" << metaData.m_deviceIndex
<< ":" << metaData.m_channelIndex
<< "|" << metaData.m_tv_sec

View File

@ -21,8 +21,10 @@
#include <QDebug>
#include <QNetworkReply>
#include <QBuffer>
#include <QJsonParseError>
#include "SWGDeviceSettings.h"
#include "SWGChannelSettings.h"
#include "SWGDeviceState.h"
#include "SWGDeviceReport.h"
#include "SWGRemoteInputReport.h"
@ -40,6 +42,7 @@ MESSAGE_CLASS_DEFINITION(RemoteInput::MsgConfigureRemoteInputTiming, Message)
MESSAGE_CLASS_DEFINITION(RemoteInput::MsgReportRemoteInputAcquisition, Message)
MESSAGE_CLASS_DEFINITION(RemoteInput::MsgReportRemoteInputStreamData, Message)
MESSAGE_CLASS_DEFINITION(RemoteInput::MsgReportRemoteInputStreamTiming, Message)
MESSAGE_CLASS_DEFINITION(RemoteInput::MsgConfigureRemoteChannel, Message)
MESSAGE_CLASS_DEFINITION(RemoteInput::MsgStartStop, Message)
RemoteInput::RemoteInput(DeviceAPI *deviceAPI) :
@ -54,6 +57,7 @@ RemoteInput::RemoteInput(DeviceAPI *deviceAPI) :
m_sampleFifo.setSize(m_sampleRate * 8);
m_remoteInputUDPHandler = new RemoteInputUDPHandler(&m_sampleFifo, m_deviceAPI);
m_remoteInputUDPHandler->setMessageQueueToInput(&m_inputMessageQueue);
connect(m_remoteInputUDPHandler, SIGNAL(metaChanged()), this, SLOT(handleMetaChanged()));
m_deviceAPI->setNbSourceStreams(1);
@ -63,6 +67,7 @@ RemoteInput::RemoteInput(DeviceAPI *deviceAPI) :
RemoteInput::~RemoteInput()
{
disconnect(m_remoteInputUDPHandler, SIGNAL(metaChanged()), this, SLOT(handleMetaChanged()));
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
delete m_networkManager;
stop();
@ -200,6 +205,13 @@ bool RemoteInput::handleMessage(const Message& message)
MsgConfigureRemoteInput& conf = (MsgConfigureRemoteInput&) message;
applySettings(conf.getSettings(), conf.getForce());
return true;
}
else if (MsgConfigureRemoteChannel::match(message))
{
qDebug() << "RemoteInput::handleMessage:" << message.getIdentifier();
MsgConfigureRemoteChannel& conf = (MsgConfigureRemoteChannel&) message;
applyRemoteChannelSettings(conf.getSettings());
return true;
}
else
{
@ -248,10 +260,10 @@ void RemoteInput::applySettings(const RemoteInputSettings& settings, bool force)
settings.m_iqCorrection ? "true" : "false");
}
if ((m_settings.m_dataAddress != settings.m_dataAddress) ||
(m_settings.m_dataPort != settings.m_dataPort) ||
(m_settings.m_multicastAddress != settings.m_multicastAddress) ||
(m_settings.m_multicastJoin != settings.m_multicastJoin) || force)
if ((m_settings.m_dataAddress != settings.m_dataAddress) ||
(m_settings.m_dataPort != settings.m_dataPort) ||
(m_settings.m_multicastAddress != settings.m_multicastAddress) ||
(m_settings.m_multicastJoin != settings.m_multicastJoin) || force)
{
m_remoteInputUDPHandler->configureUDPLink(settings.m_dataAddress, settings.m_dataPort, settings.m_multicastAddress, settings.m_multicastJoin);
m_remoteInputUDPHandler->getRemoteAddress(remoteAddress);
@ -272,13 +284,70 @@ void RemoteInput::applySettings(const RemoteInputSettings& settings, bool force)
m_remoteAddress = remoteAddress;
qDebug() << "RemoteInput::applySettings: "
<< " m_dataAddress: " << m_settings.m_dataAddress
<< " m_dataPort: " << m_settings.m_dataPort
<< " m_multicastAddress: " << m_settings.m_multicastAddress
<< " m_multicastJoin: " << m_settings.m_multicastJoin
<< " m_apiAddress: " << m_settings.m_apiAddress
<< " m_apiPort: " << m_settings.m_apiPort
<< " m_remoteAddress: " << m_remoteAddress;
<< " m_dataAddress: " << m_settings.m_dataAddress
<< " m_dataPort: " << m_settings.m_dataPort
<< " m_multicastAddress: " << m_settings.m_multicastAddress
<< " m_multicastJoin: " << m_settings.m_multicastJoin
<< " m_apiAddress: " << m_settings.m_apiAddress
<< " m_apiPort: " << m_settings.m_apiPort
<< " m_remoteAddress: " << m_remoteAddress;
}
void RemoteInput::applyRemoteChannelSettings(const RemoteChannelSettings& settings)
{
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();;
swgChannelSettings->setOriginatorChannelIndex(0);
swgChannelSettings->setOriginatorDeviceSetIndex(m_deviceAPI->getDeviceSetIndex());
swgChannelSettings->setChannelType(new QString("RemoteSink"));
swgChannelSettings->setRemoteSinkSettings(new SWGSDRangel::SWGRemoteSinkSettings());
SWGSDRangel::SWGRemoteSinkSettings *swgRemoteSinkSettings = swgChannelSettings->getRemoteSinkSettings();
bool hasChanged = false;
if (settings.m_deviceCenterFrequency != m_remoteChannelSettings.m_deviceCenterFrequency)
{
swgRemoteSinkSettings->setDeviceCenterFrequency(settings.m_deviceCenterFrequency);
hasChanged = true;
}
if (settings.m_log2Decim != m_remoteChannelSettings.m_log2Decim)
{
swgRemoteSinkSettings->setLog2Decim(settings.m_log2Decim);
hasChanged = true;
}
if (settings.m_filterChainHash != m_remoteChannelSettings.m_filterChainHash)
{
swgRemoteSinkSettings->setFilterChainHash(settings.m_filterChainHash);
hasChanged = true;
}
if (hasChanged)
{
QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
.arg(m_settings.m_apiAddress)
.arg(m_settings.m_apiPort)
.arg(m_currentMeta.m_deviceIndex)
.arg(m_currentMeta.m_channelIndex);
m_networkRequest.setUrl(QUrl(channelSettingsURL));
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QBuffer *buffer = new QBuffer();
buffer->open((QBuffer::ReadWrite));
buffer->write(swgChannelSettings->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);
}
m_remoteChannelSettings = settings;
qDebug() << "RemoteInput::applyRemoteChannelSettings: "
<< " m_deviceCenterFrequency: " << m_remoteChannelSettings.m_deviceCenterFrequency
<< " m_deviceSampleRate: " << m_remoteChannelSettings.m_deviceSampleRate
<< " m_log2Decim: " << m_remoteChannelSettings.m_log2Decim
<< " m_filterChainHash: " << m_remoteChannelSettings.m_filterChainHash;
}
int RemoteInput::webapiRunGet(
@ -534,7 +603,51 @@ void RemoteInput::networkManagerFinished(QNetworkReply *reply)
QString answer = reply->readAll();
answer.chop(1); // remove last \n
qDebug("RemoteInput::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
QByteArray jsonBytes(answer.toStdString().c_str());
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(jsonBytes, &error);
if (error.error == QJsonParseError::NoError)
{
if (doc.object().contains("RemoteSinkSettings")) {
analyzeRemoteChannelSettingsReply(doc.object());
}
}
}
reply->deleteLater();
}
void RemoteInput::analyzeRemoteChannelSettingsReply(const QJsonObject& jsonObject)
{
QJsonObject settings = jsonObject["RemoteSinkSettings"].toObject();
m_remoteChannelSettings.m_deviceCenterFrequency = settings["deviceCenterFrequency"].toInt();
m_remoteChannelSettings.m_deviceSampleRate = settings["deviceSampleRate"].toInt();
m_remoteChannelSettings.m_log2Decim = settings["log2Decim"].toInt();
m_remoteChannelSettings.m_filterChainHash = settings["filterChainHash"].toInt();
if (m_guiMessageQueue) // forward to GUI if any
{
MsgConfigureRemoteChannel *msg = MsgConfigureRemoteChannel::create(m_remoteChannelSettings);
m_guiMessageQueue->push(msg);
}
}
void RemoteInput::getRemoteChannelSettings()
{
QString getSettingsURL= QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
.arg(m_settings.m_apiAddress)
.arg(m_settings.m_apiPort)
.arg(m_currentMeta.m_deviceIndex)
.arg(m_currentMeta.m_channelIndex);
m_networkRequest.setUrl(QUrl(getSettingsURL));
m_networkManager->get(m_networkRequest);
}
void RemoteInput::handleMetaChanged()
{
m_currentMeta = m_remoteInputUDPHandler->getCurrentMeta();
getRemoteChannelSettings();
}

View File

@ -28,6 +28,7 @@
#include <QNetworkRequest>
#include "dsp/devicesamplesource.h"
#include "channel/remotedatablock.h"
#include "remoteinputsettings.h"
@ -39,6 +40,21 @@ class RemoteInputUDPHandler;
class RemoteInput : public DeviceSampleSource {
Q_OBJECT
public:
struct RemoteChannelSettings
{
uint64_t m_deviceCenterFrequency;
uint32_t m_deviceSampleRate;
uint32_t m_log2Decim;
uint32_t m_filterChainHash;
RemoteChannelSettings() :
m_deviceCenterFrequency(0),
m_deviceSampleRate(1),
m_log2Decim(0),
m_filterChainHash(0)
{}
};
class MsgConfigureRemoteInput : public Message {
MESSAGE_CLASS_DECLARATION
@ -125,6 +141,26 @@ public:
{ }
};
class MsgConfigureRemoteChannel : public Message {
MESSAGE_CLASS_DECLARATION
public:
const RemoteChannelSettings& getSettings() const { return m_settings; }
static MsgConfigureRemoteChannel* create(const RemoteChannelSettings& settings)
{
return new MsgConfigureRemoteChannel(settings);
}
protected:
RemoteChannelSettings m_settings;
MsgConfigureRemoteChannel(const RemoteChannelSettings& settings) :
Message(),
m_settings(settings)
{ }
};
class MsgReportRemoteInputStreamTiming : public Message {
MESSAGE_CLASS_DECLARATION
@ -307,7 +343,9 @@ private:
int m_sampleRate;
QMutex m_mutex;
RemoteInputSettings m_settings;
RemoteChannelSettings m_remoteChannelSettings;
RemoteInputUDPHandler* m_remoteInputUDPHandler;
RemoteMetaDataFEC m_currentMeta;
QString m_remoteAddress;
QString m_deviceDescription;
std::time_t m_startingTimeStamp;
@ -315,12 +353,16 @@ private:
QNetworkRequest m_networkRequest;
void applySettings(const RemoteInputSettings& settings, bool force = false);
void applyRemoteChannelSettings(const RemoteChannelSettings& settings);
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
void webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const RemoteInputSettings& settings, bool force);
void webapiReverseSendStartStop(bool start);
void getRemoteChannelSettings();
void analyzeRemoteChannelSettingsReply(const QJsonObject& jsonObject);
private slots:
void networkManagerFinished(QNetworkReply *reply);
void handleMetaChanged();
};
#endif // INCLUDE_REMOTEINPUT_H

View File

@ -415,8 +415,6 @@ void RemoteInputBuffer::printMeta(const QString& header, RemoteMetaDataFEC *meta
<< ":" << (int) metaData->m_sampleBits
<< ":" << (int) metaData->m_nbOriginalBlocks
<< ":" << (int) metaData->m_nbFECBlocks
<< "|" << metaData->m_deviceCenterFrequency
<< ":" << metaData->m_basebandSampleRate
<< "|" << metaData->m_deviceIndex
<< ":" << metaData->m_channelIndex
<< "|" << metaData->m_tv_sec

View File

@ -18,11 +18,14 @@
#ifndef PLUGINS_SAMPLESOURCE_REMOTEINPUT_REMOTEINPUTBUFFER_H_
#define PLUGINS_SAMPLESOURCE_REMOTEINPUT_REMOTEINPUTBUFFER_H_
#include <channel/remotedatablock.h>
#include <QString>
#include <QDebug>
#include <cstdlib>
#include "cm256cc/cm256.h"
#include "channel/remotedatablock.h"
#include "util/movingaverage.h"

View File

@ -37,6 +37,7 @@
#include "gui/basicdevicesettingsdialog.h"
#include "dsp/dspengine.h"
#include "dsp/dspcommands.h"
#include "dsp/hbfilterchainconverter.h"
#include "mainwindow.h"
#include "util/simpleserializer.h"
#include "device/deviceapi.h"
@ -76,6 +77,9 @@ RemoteInputGui::RemoteInputGui(DeviceUISet *deviceUISet, QWidget* parent) :
m_startingTimeStampms = 0;
ui->setupUi(this);
ui->remoteDeviceFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->remoteDeviceFrequency->setValueRange(8, 0, 99999999);
CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop);
connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &)));
@ -160,6 +164,16 @@ bool RemoteInputGui::handleMessage(const Message& message)
blockApplySettings(false);
return true;
}
else if (RemoteInput::MsgConfigureRemoteChannel::match(message))
{
qDebug("RemoteInputGui::handleMessage: RemoteInput::MsgConfigureRemoteChannel");
const RemoteInput::MsgConfigureRemoteChannel& cfg = (RemoteInput::MsgConfigureRemoteChannel&) message;
m_remoteChannelSettings = cfg.getSettings();
blockApplySettings(true);
displayRemoteSettings();
blockApplySettings(false);
return true;
}
else if (RemoteInput::MsgReportRemoteInputAcquisition::match(message))
{
m_acquisition = ((RemoteInput::MsgReportRemoteInputAcquisition&)message).getAcquisition();
@ -286,12 +300,86 @@ void RemoteInputGui::displaySettings()
blockApplySettings(false);
}
void RemoteInputGui::displayRemoteSettings()
{
blockApplySettings(true);
ui->remoteDeviceFrequency->setValue(m_remoteChannelSettings.m_deviceCenterFrequency/1000);
ui->decimationFactor->setCurrentIndex(m_remoteChannelSettings.m_log2Decim);
applyDecimation();
blockApplySettings(false);
}
void RemoteInputGui::displayRemoteShift()
{
int basebandSampleRate = m_streamSampleRate * (1<<m_remoteChannelSettings.m_log2Decim);
int shift = m_remoteShiftFrequencyFactor * basebandSampleRate;
QLocale loc;
ui->offsetFrequencyText->setText(tr("%1 Hz").arg(loc.toString(shift)));
}
void RemoteInputGui::applyDecimation()
{
uint32_t maxHash = 1;
for (uint32_t i = 0; i < m_remoteChannelSettings.m_log2Decim; i++) {
maxHash *= 3;
}
ui->position->setMaximum(maxHash-1);
ui->position->setValue(m_remoteChannelSettings.m_filterChainHash);
m_remoteChannelSettings.m_filterChainHash = ui->position->value();
applyPosition();
}
void RemoteInputGui::applyPosition()
{
ui->filterChainIndex->setText(tr("%1").arg(m_remoteChannelSettings.m_filterChainHash));
QString s;
m_remoteShiftFrequencyFactor = HBFilterChainConverter::convertToString(
m_remoteChannelSettings.m_log2Decim,
m_remoteChannelSettings.m_filterChainHash, s)
;
ui->filterChainText->setText(s);
displayRemoteShift();
applyRemoteSettings();
}
void RemoteInputGui::applyRemoteSettings()
{
if (m_doApplySettings)
{
qDebug() << "RemoteInputGui::applyRemoteSettings";
RemoteInput::MsgConfigureRemoteChannel* message =
RemoteInput::MsgConfigureRemoteChannel::create(m_remoteChannelSettings);
m_sampleSource->getInputMessageQueue()->push(message);
}
}
void RemoteInputGui::sendSettings()
{
if(!m_updateTimer.isActive())
m_updateTimer.start(100);
}
void RemoteInputGui::on_remoteDeviceFrequency_changed(quint64 value)
{
m_remoteChannelSettings.m_deviceCenterFrequency = value * 1000;
applyRemoteSettings();
}
void RemoteInputGui::on_decimationFactor_currentIndexChanged(int index)
{
m_remoteChannelSettings.m_log2Decim = index;
applyDecimation();
}
void RemoteInputGui::on_position_valueChanged(int value)
{
m_remoteChannelSettings.m_filterChainHash = value;
applyPosition();
}
void RemoteInputGui::on_apiApplyButton_clicked(bool checked)
{
(void) checked;

View File

@ -55,6 +55,8 @@ private:
DeviceUISet* m_deviceUISet;
RemoteInputSettings m_settings; //!< current settings
RemoteInput::RemoteChannelSettings m_remoteChannelSettings;
double m_remoteShiftFrequencyFactor; //!< Remote channel frequency shift factor
RemoteInput* m_sampleSource;
bool m_acquisition;
int m_streamSampleRate; //!< Sample rate of received stream
@ -103,6 +105,8 @@ private:
void blockApplySettings(bool block);
void displaySettings();
void displayRemoteSettings();
void displayRemoteShift();
void displayTime();
void sendSettings();
void updateWithAcquisition();
@ -110,11 +114,17 @@ private:
void updateSampleRateAndFrequency();
void displayEventCounts();
void displayEventTimer();
void applyDecimation();
void applyPosition();
void applyRemoteSettings();
void analyzeApiReply(const QJsonObject& jsonObject);
bool handleMessage(const Message& message);
private slots:
void handleInputMessages();
void on_remoteDeviceFrequency_changed(quint64 value);
void on_decimationFactor_currentIndexChanged(int index);
void on_position_valueChanged(int value);
void on_apiApplyButton_clicked(bool checked);
void on_dataApplyButton_clicked(bool checked);
void on_dcOffset_toggled(bool checked);

View File

@ -7,13 +7,13 @@
<x>0</x>
<y>0</y>
<width>400</width>
<height>312</height>
<height>480</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>360</width>
<height>270</height>
<height>480</height>
</size>
</property>
<property name="font">
@ -27,7 +27,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>3</number>
<number>2</number>
</property>
<property name="leftMargin">
<number>2</number>
@ -162,6 +162,252 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="remoteDevFreqLayout">
<property name="spacing">
<number>6</number>
</property>
<item>
<widget class="QLabel" name="remoteFrequencyLabel">
<property name="text">
<string>Rem dev Fc</string>
</property>
</widget>
</item>
<item>
<widget class="ValueDial" name="remoteDeviceFrequency" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>16</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Mono</family>
<pointsize>12</pointsize>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="toolTip">
<string>Remote device center ferquency in kHz</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="remoteDeviceFreqUnits">
<property name="text">
<string>kHz</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<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>
<layout class="QVBoxLayout" name="remoteChDecimationLayer">
<property name="spacing">
<number>3</number>
</property>
<item>
<layout class="QHBoxLayout" name="decimationStageLayer">
<item>
<widget class="QLabel" name="decimationLabel">
<property name="text">
<string>Dec</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="decimationFactor">
<property name="maximumSize">
<size>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Decimation factor</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>4</string>
</property>
</item>
<item>
<property name="text">
<string>8</string>
</property>
</item>
<item>
<property name="text">
<string>16</string>
</property>
</item>
<item>
<property name="text">
<string>32</string>
</property>
</item>
<item>
<property name="text">
<string>64</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="channelRateText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Effective channel rate (kS/s)</string>
</property>
<property name="text">
<string>0000k</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="filterChainText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Filter chain stages left to right (L: low, C: center, H: high) </string>
</property>
<property name="text">
<string>LLLLLL</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_8">
<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="offsetFrequencyText">
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Offset frequency with thousands separator (Hz)</string>
</property>
<property name="text">
<string>-9,999,999 Hz</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="decimationShiftLayer">
<property name="rightMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="positionLabel">
<property name="text">
<string>Pos</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="position">
<property name="toolTip">
<string>Center frequency position</string>
</property>
<property name="maximum">
<number>2</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="filterChainIndex">
<property name="minimumSize">
<size>
<width>24</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Filter chain hash code</string>
</property>
<property name="text">
<string>000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="gridLayout_corr">
<item>
@ -860,6 +1106,12 @@
<extends>QToolButton</extends>
<header>gui/buttonswitch.h</header>
</customwidget>
<customwidget>
<class>ValueDial</class>
<extends>QWidget</extends>
<header>gui/valuedial.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>

View File

@ -324,6 +324,13 @@ void RemoteInputUDPHandler::tick()
}
const RemoteMetaDataFEC& metaData = m_remoteInputBuffer.getCurrentMeta();
if (!(m_currentMeta == metaData))
{
m_currentMeta = metaData;
emit metaChanged();
}
m_readLength = m_readLengthSamples * (metaData.m_sampleBytes & 0xF) * 2;
if (metaData.m_sampleBits == SDR_RX_SAMP_SZ) // no conversion
@ -409,56 +416,6 @@ void RemoteInputUDPHandler::tick()
qWarning("RemoteInputUDPHandler::tick: unexpected sample size in stream: %d bits", (int) metaData.m_sampleBits);
}
// if ((metaData.m_sampleBits == 16) && (SDR_RX_SAMP_SZ == 24)) // 16 -> 24 bits
// {
// if (m_readLengthSamples > (int) m_converterBufferNbSamples)
// {
// if (m_converterBuffer) { delete[] m_converterBuffer; }
// m_converterBuffer = new int32_t[m_readLengthSamples*2];
// }
// uint8_t *buf = m_remoteInputBuffer.readData(m_readLength);
// for (int is = 0; is < m_readLengthSamples; is++)
// {
// m_converterBuffer[2*is] = ((int16_t*)buf)[2*is]; // I
// m_converterBuffer[2*is]<<=8;
// m_converterBuffer[2*is+1] = ((int16_t*)buf)[2*is+1]; // Q
// m_converterBuffer[2*is+1]<<=8;
// }
// m_sampleFifo->write(reinterpret_cast<quint8*>(m_converterBuffer), m_readLengthSamples*sizeof(Sample));
// }
// else if ((metaData.m_sampleBits == 24) && (SDR_RX_SAMP_SZ == 16)) // 24 -> 16 bits
// {
// if (m_readLengthSamples > (int) m_converterBufferNbSamples)
// {
// if (m_converterBuffer) { delete[] m_converterBuffer; }
// m_converterBuffer = new int32_t[m_readLengthSamples];
// }
// uint8_t *buf = m_remoteInputBuffer.readData(m_readLength);
// for (int is = 0; is < m_readLengthSamples; is++)
// {
// m_converterBuffer[is] = ((int32_t *)buf)[2*is+1]>>8; // Q -> MSB
// m_converterBuffer[is] <<=16;
// m_converterBuffer[is] += ((int32_t *)buf)[2*is]>>8; // I -> LSB
// }
// m_sampleFifo->write(reinterpret_cast<quint8*>(m_converterBuffer), m_readLengthSamples*sizeof(Sample));
// }
// else if ((metaData.m_sampleBits == 16) || (metaData.m_sampleBits == 24)) // same sample size and valid size
// {
// // read samples directly feeding the SampleFifo (no callback)
// m_sampleFifo->write(reinterpret_cast<quint8*>(m_remoteInputBuffer.readData(m_readLength)), m_readLength);
// m_samplesCount += m_readLengthSamples;
// }
// else // invalid size
// {
// qWarning("RemoteInputUDPHandler::tick: unexpected sample size in stream: %d bits", (int) metaData.m_sampleBits);
// }
if (m_tickCount < m_rateDivider)
{
m_tickCount++;

View File

@ -74,9 +74,14 @@ public:
uint64_t getTVmSec() const { return m_tv_msec; }
int getMinNbBlocks() { return m_remoteInputBuffer.getMinNbBlocks(); }
int getMaxNbRecovery() { return m_remoteInputBuffer.getMaxNbRecovery(); }
const RemoteMetaDataFEC& getCurrentMeta() const { return m_currentMeta; }
public slots:
void dataReadyRead();
signals:
void metaChanged();
private:
class MsgUDPAddressAndPort : public Message {
MESSAGE_CLASS_DECLARATION
@ -113,6 +118,7 @@ private:
bool m_running;
uint32_t m_rateDivider;
RemoteInputBuffer m_remoteInputBuffer;
RemoteMetaDataFEC m_currentMeta;
QUdpSocket *m_dataSocket;
QHostAddress m_dataAddress;
QHostAddress m_remoteAddress;

View File

@ -44,8 +44,6 @@ struct RemoteMetaDataFEC
uint8_t m_sampleBits; //!< 14 number of effective bits per sample (deprecated)
uint8_t m_nbOriginalBlocks; //!< 15 number of blocks with original (protected) data
uint8_t m_nbFECBlocks; //!< 16 number of blocks carrying FEC
uint64_t m_deviceCenterFrequency; //!< 24 device center frequency in Hz
uint32_t m_basebandSampleRate; //!< 28 basebabd sample rate in Hz
uint8_t m_deviceIndex; //!< 29 index of device set in instance
uint8_t m_channelIndex; //!< 30 index of channel in device set
@ -72,8 +70,6 @@ struct RemoteMetaDataFEC
m_sampleBits = 0;
m_nbOriginalBlocks = 0;
m_nbFECBlocks = 0;
m_deviceCenterFrequency = 0;
m_basebandSampleRate = 1;
m_deviceIndex = 0;
m_channelIndex = 0;
m_tv_sec = 0;

View File

@ -9911,6 +9911,10 @@ margin-bottom: 20px;
"type" : "integer",
"description" : "Number of bytes in a transmited I or Q sample\n * 1\n * 2\n * 4\n"
},
"deviceCenterFrequency" : {
"type" : "integer",
"description" : "Device center frequency in kHz"
},
"dataAddress" : {
"type" : "string",
"description" : "Receiving USB data address"
@ -51630,7 +51634,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2021-12-19T12:04:51.409+01:00
Generated 2021-12-24T20:37:17.750+01:00
</div>
</div>
</div>

View File

@ -11,6 +11,9 @@ RemoteSinkSettings:
* 1
* 2
* 4
deviceCenterFrequency:
type: integer
description: Device center frequency in kHz
dataAddress:
description: "Receiving USB data address"
type: string

View File

@ -11,6 +11,9 @@ RemoteSinkSettings:
* 1
* 2
* 4
deviceCenterFrequency:
type: integer
description: Device center frequency in kHz
dataAddress:
description: "Receiving USB data address"
type: string

View File

@ -9911,6 +9911,10 @@ margin-bottom: 20px;
"type" : "integer",
"description" : "Number of bytes in a transmited I or Q sample\n * 1\n * 2\n * 4\n"
},
"deviceCenterFrequency" : {
"type" : "integer",
"description" : "Device center frequency in kHz"
},
"dataAddress" : {
"type" : "string",
"description" : "Receiving USB data address"
@ -51630,7 +51634,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2021-12-19T12:04:51.409+01:00
Generated 2021-12-24T20:37:17.750+01:00
</div>
</div>
</div>

View File

@ -32,6 +32,8 @@ SWGRemoteSinkSettings::SWGRemoteSinkSettings() {
m_nb_fec_blocks_isSet = false;
nb_tx_bytes = 0;
m_nb_tx_bytes_isSet = false;
device_center_frequency = 0;
m_device_center_frequency_isSet = false;
data_address = nullptr;
m_data_address_isSet = false;
data_port = 0;
@ -70,6 +72,8 @@ SWGRemoteSinkSettings::init() {
m_nb_fec_blocks_isSet = false;
nb_tx_bytes = 0;
m_nb_tx_bytes_isSet = false;
device_center_frequency = 0;
m_device_center_frequency_isSet = false;
data_address = new QString("");
m_data_address_isSet = false;
data_port = 0;
@ -102,6 +106,7 @@ void
SWGRemoteSinkSettings::cleanup() {
if(data_address != nullptr) {
delete data_address;
}
@ -140,6 +145,8 @@ SWGRemoteSinkSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&nb_tx_bytes, pJson["nbTxBytes"], "qint32", "");
::SWGSDRangel::setValue(&device_center_frequency, pJson["deviceCenterFrequency"], "qint32", "");
::SWGSDRangel::setValue(&data_address, pJson["dataAddress"], "QString", "QString");
::SWGSDRangel::setValue(&data_port, pJson["dataPort"], "qint32", "");
@ -188,6 +195,9 @@ SWGRemoteSinkSettings::asJsonObject() {
if(m_nb_tx_bytes_isSet){
obj->insert("nbTxBytes", QJsonValue(nb_tx_bytes));
}
if(m_device_center_frequency_isSet){
obj->insert("deviceCenterFrequency", QJsonValue(device_center_frequency));
}
if(data_address != nullptr && *data_address != QString("")){
toJsonValue(QString("dataAddress"), data_address, obj, QString("QString"));
}
@ -251,6 +261,16 @@ SWGRemoteSinkSettings::setNbTxBytes(qint32 nb_tx_bytes) {
this->m_nb_tx_bytes_isSet = true;
}
qint32
SWGRemoteSinkSettings::getDeviceCenterFrequency() {
return device_center_frequency;
}
void
SWGRemoteSinkSettings::setDeviceCenterFrequency(qint32 device_center_frequency) {
this->device_center_frequency = device_center_frequency;
this->m_device_center_frequency_isSet = true;
}
QString*
SWGRemoteSinkSettings::getDataAddress() {
return data_address;
@ -392,6 +412,9 @@ SWGRemoteSinkSettings::isSet(){
if(m_nb_tx_bytes_isSet){
isObjectUpdated = true; break;
}
if(m_device_center_frequency_isSet){
isObjectUpdated = true; break;
}
if(data_address && *data_address != QString("")){
isObjectUpdated = true; break;
}

View File

@ -49,6 +49,9 @@ public:
qint32 getNbTxBytes();
void setNbTxBytes(qint32 nb_tx_bytes);
qint32 getDeviceCenterFrequency();
void setDeviceCenterFrequency(qint32 device_center_frequency);
QString* getDataAddress();
void setDataAddress(QString* data_address);
@ -98,6 +101,9 @@ private:
qint32 nb_tx_bytes;
bool m_nb_tx_bytes_isSet;
qint32 device_center_frequency;
bool m_device_center_frequency_isSet;
QString* data_address;
bool m_data_address_isSet;