From 9bb3a273b38e5da98ae50c647361ec3d2597798e Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 24 Dec 2021 21:06:15 +0100 Subject: [PATCH] Remote input/sink implemented remote control (1) --- plugins/channelrx/remotesink/remotesink.cpp | 31 +++ plugins/channelrx/remotesink/remotesink.h | 1 + .../remotesink/remotesinksettings.cpp | 3 - .../channelrx/remotesink/remotesinksettings.h | 1 - .../channelrx/remotesink/remotesinksink.cpp | 4 - .../remotesource/remotesourcesource.cpp | 2 - .../samplesink/remoteoutput/udpsinkfec.cpp | 4 - .../samplesource/remoteinput/remoteinput.cpp | 135 ++++++++- .../samplesource/remoteinput/remoteinput.h | 42 +++ .../remoteinput/remoteinputbuffer.cpp | 2 - .../remoteinput/remoteinputbuffer.h | 5 +- .../remoteinput/remoteinputgui.cpp | 88 ++++++ .../samplesource/remoteinput/remoteinputgui.h | 10 + .../remoteinput/remoteinputgui.ui | 258 +++++++++++++++++- .../remoteinput/remoteinputudphandler.cpp | 57 +--- .../remoteinput/remoteinputudphandler.h | 6 + sdrbase/channel/remotedatablock.h | 4 - sdrbase/resources/webapi/doc/html2/index.html | 6 +- .../doc/swagger/include/RemoteSink.yaml | 3 + .../api/swagger/include/RemoteSink.yaml | 3 + swagger/sdrangel/code/html2/index.html | 6 +- .../code/qt5/client/SWGRemoteSinkSettings.cpp | 23 ++ .../code/qt5/client/SWGRemoteSinkSettings.h | 6 + 23 files changed, 613 insertions(+), 87 deletions(-) diff --git a/plugins/channelrx/remotesink/remotesink.cpp b/plugins/channelrx/remotesink/remotesink.cpp index cd06ca480..ea593c068 100644 --- a/plugins/channelrx/remotesink/remotesink.cpp +++ b/plugins/channelrx/remotesink/remotesink.cpp @@ -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)); } diff --git a/plugins/channelrx/remotesink/remotesink.h b/plugins/channelrx/remotesink/remotesink.h index 26b3ea8c8..43bf9ad9a 100644 --- a/plugins/channelrx/remotesink/remotesink.h +++ b/plugins/channelrx/remotesink/remotesink.h @@ -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& channelSettingsKeys, const RemoteSinkSettings& settings, bool force); void sendChannelSettings( QList *messageQueues, diff --git a/plugins/channelrx/remotesink/remotesinksettings.cpp b/plugins/channelrx/remotesink/remotesinksettings.cpp index a34ac83bd..2f51645f1 100644 --- a/plugins/channelrx/remotesink/remotesinksettings.cpp +++ b/plugins/channelrx/remotesink/remotesinksettings.cpp @@ -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; } diff --git a/plugins/channelrx/remotesink/remotesinksettings.h b/plugins/channelrx/remotesink/remotesinksettings.h index 30419560c..d6f4adca7 100644 --- a/plugins/channelrx/remotesink/remotesinksettings.h +++ b/plugins/channelrx/remotesink/remotesinksettings.h @@ -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; diff --git a/plugins/channelrx/remotesink/remotesinksink.cpp b/plugins/channelrx/remotesink/remotesinksink.cpp index 1ae7d6e08..7061a336a 100644 --- a/plugins/channelrx/remotesink/remotesinksink.cpp +++ b/plugins/channelrx/remotesink/remotesinksink.cpp @@ -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 diff --git a/plugins/channeltx/remotesource/remotesourcesource.cpp b/plugins/channeltx/remotesource/remotesourcesource.cpp index 662df46ed..90fa4e732 100644 --- a/plugins/channeltx/remotesource/remotesourcesource.cpp +++ b/plugins/channeltx/remotesource/remotesourcesource.cpp @@ -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 diff --git a/plugins/samplesink/remoteoutput/udpsinkfec.cpp b/plugins/samplesink/remoteoutput/udpsinkfec.cpp index 961881c21..2ab96d217 100644 --- a/plugins/samplesink/remoteoutput/udpsinkfec.cpp +++ b/plugins/samplesink/remoteoutput/udpsinkfec.cpp @@ -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 diff --git a/plugins/samplesource/remoteinput/remoteinput.cpp b/plugins/samplesource/remoteinput/remoteinput.cpp index 505866098..09465341b 100644 --- a/plugins/samplesource/remoteinput/remoteinput.cpp +++ b/plugins/samplesource/remoteinput/remoteinput.cpp @@ -21,8 +21,10 @@ #include #include #include +#include #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(); +} diff --git a/plugins/samplesource/remoteinput/remoteinput.h b/plugins/samplesource/remoteinput/remoteinput.h index 96b0cc5ea..314527a14 100644 --- a/plugins/samplesource/remoteinput/remoteinput.h +++ b/plugins/samplesource/remoteinput/remoteinput.h @@ -28,6 +28,7 @@ #include #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& 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 diff --git a/plugins/samplesource/remoteinput/remoteinputbuffer.cpp b/plugins/samplesource/remoteinput/remoteinputbuffer.cpp index 420c4cba9..ad25b7d11 100644 --- a/plugins/samplesource/remoteinput/remoteinputbuffer.cpp +++ b/plugins/samplesource/remoteinput/remoteinputbuffer.cpp @@ -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 diff --git a/plugins/samplesource/remoteinput/remoteinputbuffer.h b/plugins/samplesource/remoteinput/remoteinputbuffer.h index 26ab72db8..13effdba3 100644 --- a/plugins/samplesource/remoteinput/remoteinputbuffer.h +++ b/plugins/samplesource/remoteinput/remoteinputbuffer.h @@ -18,11 +18,14 @@ #ifndef PLUGINS_SAMPLESOURCE_REMOTEINPUT_REMOTEINPUTBUFFER_H_ #define PLUGINS_SAMPLESOURCE_REMOTEINPUT_REMOTEINPUTBUFFER_H_ -#include #include #include + #include + #include "cm256cc/cm256.h" + +#include "channel/remotedatablock.h" #include "util/movingaverage.h" diff --git a/plugins/samplesource/remoteinput/remoteinputgui.cpp b/plugins/samplesource/remoteinput/remoteinputgui.cpp index 18c5486a9..f780cc63e 100644 --- a/plugins/samplesource/remoteinput/remoteinputgui.cpp +++ b/plugins/samplesource/remoteinput/remoteinputgui.cpp @@ -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<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; diff --git a/plugins/samplesource/remoteinput/remoteinputgui.h b/plugins/samplesource/remoteinput/remoteinputgui.h index ab0c31ca4..eeaad908d 100644 --- a/plugins/samplesource/remoteinput/remoteinputgui.h +++ b/plugins/samplesource/remoteinput/remoteinputgui.h @@ -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); diff --git a/plugins/samplesource/remoteinput/remoteinputgui.ui b/plugins/samplesource/remoteinput/remoteinputgui.ui index 75dad94ef..1e8aa6ce4 100644 --- a/plugins/samplesource/remoteinput/remoteinputgui.ui +++ b/plugins/samplesource/remoteinput/remoteinputgui.ui @@ -7,13 +7,13 @@ 0 0 400 - 312 + 480 360 - 270 + 480 @@ -27,7 +27,7 @@ - 3 + 2 2 @@ -162,6 +162,252 @@ + + + + 6 + + + + + Rem dev Fc + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 12 + 50 + false + + + + PointingHandCursor + + + Remote device center ferquency in kHz + + + + + + + kHz + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 3 + + + + + + + Dec + + + + + + + + 55 + 16777215 + + + + Decimation factor + + + + 1 + + + + + 2 + + + + + 4 + + + + + 8 + + + + + 16 + + + + + 32 + + + + + 64 + + + + + + + + + 50 + 0 + + + + Effective channel rate (kS/s) + + + 0000k + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + 0 + + + + Filter chain stages left to right (L: low, C: center, H: high) + + + LLLLLL + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 85 + 0 + + + + Offset frequency with thousands separator (Hz) + + + -9,999,999 Hz + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + 10 + + + + + Pos + + + + + + + Center frequency position + + + 2 + + + 1 + + + Qt::Horizontal + + + + + + + + 24 + 0 + + + + Filter chain hash code + + + 000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + @@ -860,6 +1106,12 @@ QToolButton
gui/buttonswitch.h
+ + ValueDial + QWidget +
gui/valuedial.h
+ 1 +
diff --git a/plugins/samplesource/remoteinput/remoteinputudphandler.cpp b/plugins/samplesource/remoteinput/remoteinputudphandler.cpp index 1bdd14f77..d7e82be9a 100644 --- a/plugins/samplesource/remoteinput/remoteinputudphandler.cpp +++ b/plugins/samplesource/remoteinput/remoteinputudphandler.cpp @@ -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(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(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(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++; diff --git a/plugins/samplesource/remoteinput/remoteinputudphandler.h b/plugins/samplesource/remoteinput/remoteinputudphandler.h index de5423226..b7d13208d 100644 --- a/plugins/samplesource/remoteinput/remoteinputudphandler.h +++ b/plugins/samplesource/remoteinput/remoteinputudphandler.h @@ -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; diff --git a/sdrbase/channel/remotedatablock.h b/sdrbase/channel/remotedatablock.h index 477efd38b..dcda9a8af 100644 --- a/sdrbase/channel/remotedatablock.h +++ b/sdrbase/channel/remotedatablock.h @@ -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; diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 667900348..f193d5cd2 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -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:
- Generated 2021-12-19T12:04:51.409+01:00 + Generated 2021-12-24T20:37:17.750+01:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/RemoteSink.yaml b/sdrbase/resources/webapi/doc/swagger/include/RemoteSink.yaml index 3493cdf8c..66d780579 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/RemoteSink.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/RemoteSink.yaml @@ -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 diff --git a/swagger/sdrangel/api/swagger/include/RemoteSink.yaml b/swagger/sdrangel/api/swagger/include/RemoteSink.yaml index 0a9de6985..d50a338d4 100644 --- a/swagger/sdrangel/api/swagger/include/RemoteSink.yaml +++ b/swagger/sdrangel/api/swagger/include/RemoteSink.yaml @@ -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 diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 667900348..f193d5cd2 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -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:
- Generated 2021-12-19T12:04:51.409+01:00 + Generated 2021-12-24T20:37:17.750+01:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGRemoteSinkSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGRemoteSinkSettings.cpp index 5ecc0e15f..74b83e683 100644 --- a/swagger/sdrangel/code/qt5/client/SWGRemoteSinkSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGRemoteSinkSettings.cpp @@ -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; } diff --git a/swagger/sdrangel/code/qt5/client/SWGRemoteSinkSettings.h b/swagger/sdrangel/code/qt5/client/SWGRemoteSinkSettings.h index b8aa18427..7d93eef58 100644 --- a/swagger/sdrangel/code/qt5/client/SWGRemoteSinkSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGRemoteSinkSettings.h @@ -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;