diff --git a/doc/img/RadioClock_plugin.png b/doc/img/RadioClock_plugin.png new file mode 100644 index 000000000..08e1a9a0c Binary files /dev/null and b/doc/img/RadioClock_plugin.png differ diff --git a/plugins/channelrx/CMakeLists.txt b/plugins/channelrx/CMakeLists.txt index 89c024963..e8f1c1d9f 100644 --- a/plugins/channelrx/CMakeLists.txt +++ b/plugins/channelrx/CMakeLists.txt @@ -19,6 +19,7 @@ add_subdirectory(demodvorsc) add_subdirectory(demodpacket) add_subdirectory(demodais) add_subdirectory(noisefigure) +add_subdirectory(radioclock) if(DAB_FOUND AND ZLIB_FOUND AND FAAD_FOUND) add_subdirectory(demoddab) diff --git a/plugins/channelrx/radioclock/CMakeLists.txt b/plugins/channelrx/radioclock/CMakeLists.txt new file mode 100644 index 000000000..dece62173 --- /dev/null +++ b/plugins/channelrx/radioclock/CMakeLists.txt @@ -0,0 +1,58 @@ +project(radioclock) + +set(radioclock_SOURCES + radioclock.cpp + radioclocksettings.cpp + radioclockbaseband.cpp + radioclocksink.cpp + radioclockplugin.cpp + radioclockwebapiadapter.cpp +) + +set(radioclock_HEADERS + radioclock.h + radioclocksettings.h + radioclockbaseband.h + radioclocksink.h + radioclockplugin.h + radioclockwebapiadapter.h +) + +include_directories( + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client +) + +if(NOT SERVER_MODE) + set(radioclock_SOURCES + ${radioclock_SOURCES} + radioclockgui.cpp + radioclockgui.ui + ) + set(radioclock_HEADERS + ${radioclock_HEADERS} + radioclockgui.h + ) + + set(TARGET_NAME radioclock) + set(TARGET_LIB "Qt5::Widgets") + set(TARGET_LIB_GUI "sdrgui") + set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) +else() + set(TARGET_NAME radioclocksrv) + set(TARGET_LIB "") + set(TARGET_LIB_GUI "") + set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR}) +endif() + +add_library(${TARGET_NAME} SHARED + ${radioclock_SOURCES} +) + +target_link_libraries(${TARGET_NAME} + Qt5::Core + ${TARGET_LIB} + sdrbase + ${TARGET_LIB_GUI} +) + +install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER}) diff --git a/plugins/channelrx/radioclock/radioclock.cpp b/plugins/channelrx/radioclock/radioclock.cpp new file mode 100644 index 000000000..b719ef668 --- /dev/null +++ b/plugins/channelrx/radioclock/radioclock.cpp @@ -0,0 +1,475 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015-2018 Edouard Griffiths, F4EXB. // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "radioclock.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "SWGChannelSettings.h" +#include "SWGChannelReport.h" + +#include "dsp/dspengine.h" +#include "dsp/dspcommands.h" +#include "device/deviceapi.h" +#include "feature/feature.h" +#include "util/db.h" +#include "maincore.h" +#include "radioclocksink.h" + +MESSAGE_CLASS_DEFINITION(RadioClock::MsgConfigureRadioClock, Message) +MESSAGE_CLASS_DEFINITION(RadioClock::MsgDateTime, Message) +MESSAGE_CLASS_DEFINITION(RadioClock::MsgStatus, Message) + +const char * const RadioClock::m_channelIdURI = "sdrangel.channel.radioclock"; +const char * const RadioClock::m_channelId = "RadioClock"; + +RadioClock::RadioClock(DeviceAPI *deviceAPI) : + ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSink), + m_deviceAPI(deviceAPI), + m_basebandSampleRate(0) +{ + setObjectName(m_channelId); + + m_basebandSink = new RadioClockBaseband(this); + m_basebandSink->setMessageQueueToChannel(getInputMessageQueue()); + m_basebandSink->setChannel(this); + m_basebandSink->moveToThread(&m_thread); + + applySettings(m_settings, true); + + m_deviceAPI->addChannelSink(this); + m_deviceAPI->addChannelSinkAPI(this); + + m_networkManager = new QNetworkAccessManager(); + connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); +} + +RadioClock::~RadioClock() +{ + qDebug("RadioClock::~RadioClock"); + disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); + delete m_networkManager; + m_deviceAPI->removeChannelSinkAPI(this); + m_deviceAPI->removeChannelSink(this); + + if (m_basebandSink->isRunning()) { + stop(); + } + + delete m_basebandSink; +} + +uint32_t RadioClock::getNumberOfDeviceStreams() const +{ + return m_deviceAPI->getNbSourceStreams(); +} + +void RadioClock::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst) +{ + (void) firstOfBurst; + m_basebandSink->feed(begin, end); +} + +void RadioClock::start() +{ + qDebug("RadioClock::start"); + + m_basebandSink->reset(); + m_basebandSink->startWork(); + m_thread.start(); + + DSPSignalNotification *dspMsg = new DSPSignalNotification(m_basebandSampleRate, m_centerFrequency); + m_basebandSink->getInputMessageQueue()->push(dspMsg); + + RadioClockBaseband::MsgConfigureRadioClockBaseband *msg = RadioClockBaseband::MsgConfigureRadioClockBaseband::create(m_settings, true); + m_basebandSink->getInputMessageQueue()->push(msg); +} + +void RadioClock::stop() +{ + qDebug("RadioClock::stop"); + m_basebandSink->stopWork(); + m_thread.quit(); + m_thread.wait(); +} + +bool RadioClock::handleMessage(const Message& cmd) +{ + if (MsgConfigureRadioClock::match(cmd)) + { + MsgConfigureRadioClock& cfg = (MsgConfigureRadioClock&) cmd; + qDebug() << "RadioClock::handleMessage: MsgConfigureRadioClock"; + applySettings(cfg.getSettings(), cfg.getForce()); + + return true; + } + else if (DSPSignalNotification::match(cmd)) + { + DSPSignalNotification& notif = (DSPSignalNotification&) cmd; + m_basebandSampleRate = notif.getSampleRate(); + m_centerFrequency = notif.getCenterFrequency(); + // Forward to the sink + DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy + qDebug() << "RadioClock::handleMessage: DSPSignalNotification"; + m_basebandSink->getInputMessageQueue()->push(rep); + + return true; + } + else if (MsgDateTime::match(cmd)) + { + MsgDateTime& report = (MsgDateTime&)cmd; + // Save time for web report + m_dateTime = report.getDateTime(); + // Forward to GUI + if (getMessageQueueToGUI()) + { + getMessageQueueToGUI()->push(new MsgDateTime(report)); + } + + return true; + } + else if (MsgStatus::match(cmd)) + { + // Forward to GUI + MsgStatus& report = (MsgStatus&)cmd; + if (getMessageQueueToGUI()) + { + getMessageQueueToGUI()->push(new MsgStatus(report)); + } + + return true; + } + else + { + return false; + } +} + +ScopeVis *RadioClock::getScopeSink() +{ + return m_basebandSink->getScopeSink(); +} + +void RadioClock::applySettings(const RadioClockSettings& settings, bool force) +{ + qDebug() << "RadioClock::applySettings:" + << " m_streamIndex: " << settings.m_streamIndex + << " m_useReverseAPI: " << settings.m_useReverseAPI + << " m_reverseAPIAddress: " << settings.m_reverseAPIAddress + << " m_reverseAPIPort: " << settings.m_reverseAPIPort + << " m_reverseAPIDeviceIndex: " << settings.m_reverseAPIDeviceIndex + << " m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex + << " force: " << force; + + QList reverseAPIKeys; + + if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) { + reverseAPIKeys.append("inputFrequencyOffset"); + } + if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) { + reverseAPIKeys.append("rfBandwidth"); + } + if ((settings.m_threshold != m_settings.m_threshold) || force) { + reverseAPIKeys.append("threshold"); + } + if ((settings.m_modulation != m_settings.m_modulation) || force) { + reverseAPIKeys.append("modulation"); + } + if ((settings.m_timezone != m_settings.m_timezone) || force) { + reverseAPIKeys.append("timezone"); + } + if (m_settings.m_streamIndex != settings.m_streamIndex) + { + if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only + { + m_deviceAPI->removeChannelSinkAPI(this); + m_deviceAPI->removeChannelSink(this, m_settings.m_streamIndex); + m_deviceAPI->addChannelSink(this, settings.m_streamIndex); + m_deviceAPI->addChannelSinkAPI(this); + } + + reverseAPIKeys.append("streamIndex"); + } + + RadioClockBaseband::MsgConfigureRadioClockBaseband *msg = RadioClockBaseband::MsgConfigureRadioClockBaseband::create(settings, force); + m_basebandSink->getInputMessageQueue()->push(msg); + + if (settings.m_useReverseAPI) + { + bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) || + (m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) || + (m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) || + (m_settings.m_reverseAPIDeviceIndex != settings.m_reverseAPIDeviceIndex) || + (m_settings.m_reverseAPIChannelIndex != settings.m_reverseAPIChannelIndex); + webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); + } + + m_settings = settings; +} + +QByteArray RadioClock::serialize() const +{ + return m_settings.serialize(); +} + +bool RadioClock::deserialize(const QByteArray& data) +{ + if (m_settings.deserialize(data)) + { + MsgConfigureRadioClock *msg = MsgConfigureRadioClock::create(m_settings, true); + m_inputMessageQueue.push(msg); + return true; + } + else + { + m_settings.resetToDefaults(); + MsgConfigureRadioClock *msg = MsgConfigureRadioClock::create(m_settings, true); + m_inputMessageQueue.push(msg); + return false; + } +} + +int RadioClock::webapiSettingsGet( + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setRadioClockSettings(new SWGSDRangel::SWGRadioClockSettings()); + response.getRadioClockSettings()->init(); + webapiFormatChannelSettings(response, m_settings); + return 200; +} + +int RadioClock::webapiSettingsPutPatch( + bool force, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + RadioClockSettings settings = m_settings; + webapiUpdateChannelSettings(settings, channelSettingsKeys, response); + + MsgConfigureRadioClock *msg = MsgConfigureRadioClock::create(settings, force); + m_inputMessageQueue.push(msg); + + qDebug("RadioClock::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue); + if (m_guiMessageQueue) // forward to GUI if any + { + MsgConfigureRadioClock *msgToGUI = MsgConfigureRadioClock::create(settings, force); + m_guiMessageQueue->push(msgToGUI); + } + + webapiFormatChannelSettings(response, settings); + + return 200; +} + +void RadioClock::webapiUpdateChannelSettings( + RadioClockSettings& settings, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response) +{ + if (channelSettingsKeys.contains("inputFrequencyOffset")) { + settings.m_inputFrequencyOffset = response.getRadioClockSettings()->getInputFrequencyOffset(); + } + if (channelSettingsKeys.contains("rfBandwidth")) { + settings.m_rfBandwidth = response.getRadioClockSettings()->getRfBandwidth(); + } + if (channelSettingsKeys.contains("threshold")) { + settings.m_threshold = response.getRadioClockSettings()->getThreshold(); + } + if (channelSettingsKeys.contains("modulation")) { + settings.m_modulation = (RadioClockSettings::Modulation)response.getRadioClockSettings()->getModulation(); + } + if (channelSettingsKeys.contains("timezone")) { + settings.m_timezone = (RadioClockSettings::DisplayTZ)response.getRadioClockSettings()->getTimezone(); + } + if (channelSettingsKeys.contains("rgbColor")) { + settings.m_rgbColor = response.getRadioClockSettings()->getRgbColor(); + } + if (channelSettingsKeys.contains("title")) { + settings.m_title = *response.getRadioClockSettings()->getTitle(); + } + if (channelSettingsKeys.contains("streamIndex")) { + settings.m_streamIndex = response.getRadioClockSettings()->getStreamIndex(); + } + if (channelSettingsKeys.contains("useReverseAPI")) { + settings.m_useReverseAPI = response.getRadioClockSettings()->getUseReverseApi() != 0; + } + if (channelSettingsKeys.contains("reverseAPIAddress")) { + settings.m_reverseAPIAddress = *response.getRadioClockSettings()->getReverseApiAddress(); + } + if (channelSettingsKeys.contains("reverseAPIPort")) { + settings.m_reverseAPIPort = response.getRadioClockSettings()->getReverseApiPort(); + } + if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) { + settings.m_reverseAPIDeviceIndex = response.getRadioClockSettings()->getReverseApiDeviceIndex(); + } + if (channelSettingsKeys.contains("reverseAPIChannelIndex")) { + settings.m_reverseAPIChannelIndex = response.getRadioClockSettings()->getReverseApiChannelIndex(); + } +} + +void RadioClock::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const RadioClockSettings& settings) +{ + response.getRadioClockSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset); + response.getRadioClockSettings()->setRfBandwidth(settings.m_rfBandwidth); + response.getRadioClockSettings()->setThreshold(settings.m_threshold); + response.getRadioClockSettings()->setModulation((int)settings.m_modulation); + response.getRadioClockSettings()->setTimezone((int)settings.m_timezone); + + response.getRadioClockSettings()->setRgbColor(settings.m_rgbColor); + if (response.getRadioClockSettings()->getTitle()) { + *response.getRadioClockSettings()->getTitle() = settings.m_title; + } else { + response.getRadioClockSettings()->setTitle(new QString(settings.m_title)); + } + + response.getRadioClockSettings()->setStreamIndex(settings.m_streamIndex); + response.getRadioClockSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); + + if (response.getRadioClockSettings()->getReverseApiAddress()) { + *response.getRadioClockSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress; + } else { + response.getRadioClockSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress)); + } + + response.getRadioClockSettings()->setReverseApiPort(settings.m_reverseAPIPort); + response.getRadioClockSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex); + response.getRadioClockSettings()->setReverseApiChannelIndex(settings.m_reverseAPIChannelIndex); +} + +void RadioClock::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) +{ + double magsqAvg, magsqPeak; + int nbMagsqSamples; + getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples); + + response.getRadioClockReport()->setChannelPowerDb(CalcDb::dbPower(magsqAvg)); + response.getRadioClockReport()->setChannelSampleRate(RADIOCLOCK_CHANNEL_SAMPLE_RATE); + response.getRadioClockReport()->setDate(new QString(m_dateTime.date().toString())); + response.getRadioClockReport()->setTime(new QString(m_dateTime.time().toString())); +} + +void RadioClock::webapiReverseSendSettings(QList& channelSettingsKeys, const RadioClockSettings& settings, bool force) +{ + SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); + webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force); + + QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") + .arg(settings.m_reverseAPIAddress) + .arg(settings.m_reverseAPIPort) + .arg(settings.m_reverseAPIDeviceIndex) + .arg(settings.m_reverseAPIChannelIndex); + 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); + + delete swgChannelSettings; +} + +int RadioClock::webapiReportGet( + SWGSDRangel::SWGChannelReport& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setRadioClockReport(new SWGSDRangel::SWGRadioClockReport()); + response.getRadioClockReport()->init(); + webapiFormatChannelReport(response); + return 200; +} + +void RadioClock::webapiFormatChannelSettings( + QList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const RadioClockSettings& settings, + bool force +) +{ + swgChannelSettings->setDirection(0); // Single sink (Rx) + swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); + swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); + swgChannelSettings->setChannelType(new QString("RadioClock")); + swgChannelSettings->setRadioClockSettings(new SWGSDRangel::SWGRadioClockSettings()); + SWGSDRangel::SWGRadioClockSettings *swgRadioClockSettings = swgChannelSettings->getRadioClockSettings(); + + // transfer data that has been modified. When force is on transfer all data except reverse API data + + if (channelSettingsKeys.contains("inputFrequencyOffset") || force) { + swgRadioClockSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset); + } + if (channelSettingsKeys.contains("rfBandwidth") || force) { + swgRadioClockSettings->setRfBandwidth(settings.m_rfBandwidth); + } + if (channelSettingsKeys.contains("threshold") || force) { + swgRadioClockSettings->setThreshold(settings.m_threshold); + } + if (channelSettingsKeys.contains("modulation") || force) { + swgRadioClockSettings->setModulation(settings.m_modulation); + } + if (channelSettingsKeys.contains("timezone") || force) { + swgRadioClockSettings->setTimezone(settings.m_timezone); + } + if (channelSettingsKeys.contains("rgbColor") || force) { + swgRadioClockSettings->setRgbColor(settings.m_rgbColor); + } + if (channelSettingsKeys.contains("title") || force) { + swgRadioClockSettings->setTitle(new QString(settings.m_title)); + } + if (channelSettingsKeys.contains("streamIndex") || force) { + swgRadioClockSettings->setStreamIndex(settings.m_streamIndex); + } +} + +void RadioClock::networkManagerFinished(QNetworkReply *reply) +{ + QNetworkReply::NetworkError replyError = reply->error(); + + if (replyError) + { + qWarning() << "RadioClock::networkManagerFinished:" + << " error(" << (int) replyError + << "): " << replyError + << ": " << reply->errorString(); + } + else + { + QString answer = reply->readAll(); + answer.chop(1); // remove last \n + qDebug("RadioClock::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); + } + + reply->deleteLater(); +} diff --git a/plugins/channelrx/radioclock/radioclock.h b/plugins/channelrx/radioclock/radioclock.h new file mode 100644 index 000000000..051f64936 --- /dev/null +++ b/plugins/channelrx/radioclock/radioclock.h @@ -0,0 +1,199 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015-2018 Edouard Griffiths, F4EXB. // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOCLOCK_H +#define INCLUDE_RADIOCLOCK_H + +#include + +#include +#include +#include + +#include "dsp/basebandsamplesink.h" +#include "channel/channelapi.h" +#include "util/message.h" + +#include "radioclockbaseband.h" +#include "radioclocksettings.h" + +class QNetworkAccessManager; +class QNetworkReply; +class QThread; +class DeviceAPI; +class ScopeVis; + +class RadioClock : public BasebandSampleSink, public ChannelAPI { + Q_OBJECT +public: + class MsgConfigureRadioClock : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const RadioClockSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureRadioClock* create(const RadioClockSettings& settings, bool force) + { + return new MsgConfigureRadioClock(settings, force); + } + + private: + RadioClockSettings m_settings; + bool m_force; + + MsgConfigureRadioClock(const RadioClockSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + class MsgDateTime : public Message { + MESSAGE_CLASS_DECLARATION + + public: + QDateTime getDateTime() const { return m_dateTime; } + + static MsgDateTime* create(QDateTime dateTime) + { + return new MsgDateTime(dateTime); + } + + private: + QDateTime m_dateTime; + + MsgDateTime(QDateTime dateTime) : + Message(), + m_dateTime(dateTime) + { + } + }; + + class MsgStatus : public Message { + MESSAGE_CLASS_DECLARATION + + public: + QString getStatus() const { return m_status; } + + static MsgStatus* create(QString status) + { + return new MsgStatus(status); + } + + private: + QString m_status; + + MsgStatus(QString status) : + Message(), + m_status(status) + { + } + }; + + RadioClock(DeviceAPI *deviceAPI); + virtual ~RadioClock(); + virtual void destroy() { delete this; } + + using BasebandSampleSink::feed; + virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po); + virtual void start(); + virtual void stop(); + virtual bool handleMessage(const Message& cmd); + + virtual void getIdentifier(QString& id) { id = objectName(); } + virtual const QString& getURI() const { return getName(); } + virtual void getTitle(QString& title) { title = m_settings.m_title; } + virtual qint64 getCenterFrequency() const { return 0; } + + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); + + virtual int getNbSinkStreams() const { return 1; } + virtual int getNbSourceStreams() const { return 0; } + + virtual qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const + { + (void) streamIndex; + (void) sinkElseSource; + return 0; + } + + virtual int webapiSettingsGet( + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage); + + virtual int webapiReportGet( + SWGSDRangel::SWGChannelReport& response, + QString& errorMessage); + + static void webapiFormatChannelSettings( + SWGSDRangel::SWGChannelSettings& response, + const RadioClockSettings& settings); + + static void webapiUpdateChannelSettings( + RadioClockSettings& settings, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response); + + ScopeVis *getScopeSink(); + double getMagSq() const { return m_basebandSink->getMagSq(); } + + void getMagSqLevels(double& avg, double& peak, int& nbSamples) { + m_basebandSink->getMagSqLevels(avg, peak, nbSamples); + } + + uint32_t getNumberOfDeviceStreams() const; + + static const char * const m_channelIdURI; + static const char * const m_channelId; + +private: + DeviceAPI *m_deviceAPI; + QThread m_thread; + RadioClockBaseband* m_basebandSink; + RadioClockSettings m_settings; + int m_basebandSampleRate; //!< stored from device message used when starting baseband sink + qint64 m_centerFrequency; + QDateTime m_dateTime; //!< Received data and time + + QNetworkAccessManager *m_networkManager; + QNetworkRequest m_networkRequest; + + void applySettings(const RadioClockSettings& settings, bool force = false); + void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); + void webapiReverseSendSettings(QList& channelSettingsKeys, const RadioClockSettings& settings, bool force); + void webapiFormatChannelSettings( + QList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings *swgChannelSettings, + const RadioClockSettings& settings, + bool force + ); + +private slots: + void networkManagerFinished(QNetworkReply *reply); + +}; + +#endif // INCLUDE_RADIOCLOCK_H diff --git a/plugins/channelrx/radioclock/radioclockbaseband.cpp b/plugins/channelrx/radioclock/radioclockbaseband.cpp new file mode 100644 index 000000000..5fefc5691 --- /dev/null +++ b/plugins/channelrx/radioclock/radioclockbaseband.cpp @@ -0,0 +1,176 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "dsp/dspengine.h" +#include "dsp/dspcommands.h" +#include "dsp/downchannelizer.h" + +#include "radioclockbaseband.h" + +MESSAGE_CLASS_DEFINITION(RadioClockBaseband::MsgConfigureRadioClockBaseband, Message) + +RadioClockBaseband::RadioClockBaseband(RadioClock *radioClock) : + m_sink(radioClock), + m_running(false), + m_mutex(QMutex::Recursive) +{ + qDebug("RadioClockBaseband::RadioClockBaseband"); + + m_sink.setScopeSink(&m_scopeSink); + m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(48000)); + m_channelizer = new DownChannelizer(&m_sink); +} + +RadioClockBaseband::~RadioClockBaseband() +{ + m_inputMessageQueue.clear(); + + delete m_channelizer; +} + +void RadioClockBaseband::reset() +{ + QMutexLocker mutexLocker(&m_mutex); + m_inputMessageQueue.clear(); + m_sampleFifo.reset(); +} + +void RadioClockBaseband::startWork() +{ + QMutexLocker mutexLocker(&m_mutex); + QObject::connect( + &m_sampleFifo, + &SampleSinkFifo::dataReady, + this, + &RadioClockBaseband::handleData, + Qt::QueuedConnection + ); + connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + m_running = true; +} + +void RadioClockBaseband::stopWork() +{ + QMutexLocker mutexLocker(&m_mutex); + disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + QObject::disconnect( + &m_sampleFifo, + &SampleSinkFifo::dataReady, + this, + &RadioClockBaseband::handleData + ); + m_running = false; +} + +void RadioClockBaseband::setChannel(ChannelAPI *channel) +{ + m_sink.setChannel(channel); +} + +void RadioClockBaseband::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end) +{ + m_sampleFifo.write(begin, end); +} + +void RadioClockBaseband::handleData() +{ + QMutexLocker mutexLocker(&m_mutex); + + while ((m_sampleFifo.fill() > 0) && (m_inputMessageQueue.size() == 0)) + { + SampleVector::iterator part1begin; + SampleVector::iterator part1end; + SampleVector::iterator part2begin; + SampleVector::iterator part2end; + + std::size_t count = m_sampleFifo.readBegin(m_sampleFifo.fill(), &part1begin, &part1end, &part2begin, &part2end); + + // first part of FIFO data + if (part1begin != part1end) { + m_channelizer->feed(part1begin, part1end); + } + + // second part of FIFO data (used when block wraps around) + if(part2begin != part2end) { + m_channelizer->feed(part2begin, part2end); + } + + m_sampleFifo.readCommit((unsigned int) count); + } +} + +void RadioClockBaseband::handleInputMessages() +{ + Message* message; + + while ((message = m_inputMessageQueue.pop()) != nullptr) + { + if (handleMessage(*message)) { + delete message; + } + } +} + +bool RadioClockBaseband::handleMessage(const Message& cmd) +{ + if (MsgConfigureRadioClockBaseband::match(cmd)) + { + QMutexLocker mutexLocker(&m_mutex); + MsgConfigureRadioClockBaseband& cfg = (MsgConfigureRadioClockBaseband&) cmd; + qDebug() << "RadioClockBaseband::handleMessage: MsgConfigureRadioClockBaseband"; + + applySettings(cfg.getSettings(), cfg.getForce()); + + return true; + } + else if (DSPSignalNotification::match(cmd)) + { + QMutexLocker mutexLocker(&m_mutex); + DSPSignalNotification& notif = (DSPSignalNotification&) cmd; + qDebug() << "RadioClockBaseband::handleMessage: DSPSignalNotification: basebandSampleRate: " << notif.getSampleRate(); + setBasebandSampleRate(notif.getSampleRate()); + m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(notif.getSampleRate())); + + return true; + } + else + { + return false; + } +} + +void RadioClockBaseband::applySettings(const RadioClockSettings& settings, bool force) +{ + if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) + { + m_channelizer->setChannelization(RADIOCLOCK_CHANNEL_SAMPLE_RATE, settings.m_inputFrequencyOffset); + m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset()); + } + + m_sink.applySettings(settings, force); + + m_settings = settings; +} + +void RadioClockBaseband::setBasebandSampleRate(int sampleRate) +{ + m_channelizer->setBasebandSampleRate(sampleRate); + m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset()); +} diff --git a/plugins/channelrx/radioclock/radioclockbaseband.h b/plugins/channelrx/radioclock/radioclockbaseband.h new file mode 100644 index 000000000..e728e25d4 --- /dev/null +++ b/plugins/channelrx/radioclock/radioclockbaseband.h @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOCLOCKBASEBAND_H +#define INCLUDE_RADIOCLOCKBASEBAND_H + +#include +#include + +#include "dsp/samplesinkfifo.h" +#include "dsp/scopevis.h" +#include "util/message.h" +#include "util/messagequeue.h" + +#include "radioclocksink.h" + +class DownChannelizer; +class ChannelAPI; +class RadioClock; +class ScopeVis; + +class RadioClockBaseband : public QObject +{ + Q_OBJECT +public: + class MsgConfigureRadioClockBaseband : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const RadioClockSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureRadioClockBaseband* create(const RadioClockSettings& settings, bool force) + { + return new MsgConfigureRadioClockBaseband(settings, force); + } + + private: + RadioClockSettings m_settings; + bool m_force; + + MsgConfigureRadioClockBaseband(const RadioClockSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + RadioClockBaseband(RadioClock *radioClock); + ~RadioClockBaseband(); + void reset(); + void startWork(); + void stopWork(); + void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end); + MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication + void getMagSqLevels(double& avg, double& peak, int& nbSamples) { + m_sink.getMagSqLevels(avg, peak, nbSamples); + } + void setMessageQueueToChannel(MessageQueue *messageQueue) { m_sink.setMessageQueueToChannel(messageQueue); } + void setBasebandSampleRate(int sampleRate); + ScopeVis *getScopeSink() { return &m_scopeSink; } + void setChannel(ChannelAPI *channel); + double getMagSq() const { return m_sink.getMagSq(); } + bool isRunning() const { return m_running; } + +private: + SampleSinkFifo m_sampleFifo; + DownChannelizer *m_channelizer; + RadioClockSink m_sink; + MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication + RadioClockSettings m_settings; + ScopeVis m_scopeSink; + bool m_running; + QMutex m_mutex; + + bool handleMessage(const Message& cmd); + void applySettings(const RadioClockSettings& settings, bool force = false); + +private slots: + void handleInputMessages(); + void handleData(); //!< Handle data when samples have to be processed +}; + +#endif // INCLUDE_RADIOCLOCKBASEBAND_H diff --git a/plugins/channelrx/radioclock/radioclockgui.cpp b/plugins/channelrx/radioclock/radioclockgui.cpp new file mode 100644 index 000000000..cf90cd51f --- /dev/null +++ b/plugins/channelrx/radioclock/radioclockgui.cpp @@ -0,0 +1,388 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include "radioclockgui.h" + +#include "device/deviceuiset.h" +#include "dsp/dspengine.h" +#include "dsp/dspcommands.h" +#include "ui_radioclockgui.h" +#include "plugin/pluginapi.h" +#include "util/simpleserializer.h" +#include "util/db.h" +#include "gui/basicchannelsettingsdialog.h" +#include "gui/devicestreamselectiondialog.h" +#include "dsp/dspengine.h" +#include "dsp/glscopesettings.h" +#include "gui/crightclickenabler.h" +#include "maincore.h" + +#include "radioclock.h" +#include "radioclocksink.h" + +RadioClockGUI* RadioClockGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) +{ + RadioClockGUI* gui = new RadioClockGUI(pluginAPI, deviceUISet, rxChannel); + return gui; +} + +void RadioClockGUI::destroy() +{ + delete this; +} + +void RadioClockGUI::resetToDefaults() +{ + m_settings.resetToDefaults(); + displaySettings(); + applySettings(true); +} + +QByteArray RadioClockGUI::serialize() const +{ + return m_settings.serialize(); +} + +bool RadioClockGUI::deserialize(const QByteArray& data) +{ + if(m_settings.deserialize(data)) { + displaySettings(); + applySettings(true); + return true; + } else { + resetToDefaults(); + return false; + } +} + +void RadioClockGUI::displayDateTime() +{ + QDateTime dateTime = m_dateTime; + if (m_settings.m_timezone == RadioClockSettings::UTC) { + dateTime = dateTime.toUTC(); + } else if (m_settings.m_timezone == RadioClockSettings::LOCAL) { + dateTime = dateTime.toLocalTime(); + } + ui->date->setText(dateTime.date().toString()); + ui->time->setText(dateTime.time().toString()); +} + +bool RadioClockGUI::handleMessage(const Message& message) +{ + if (RadioClock::MsgConfigureRadioClock::match(message)) + { + qDebug("RadioClockGUI::handleMessage: RadioClock::MsgConfigureRadioClock"); + const RadioClock::MsgConfigureRadioClock& cfg = (RadioClock::MsgConfigureRadioClock&) message; + m_settings = cfg.getSettings(); + blockApplySettings(true); + displaySettings(); + blockApplySettings(false); + return true; + } + else if (RadioClock::MsgDateTime::match(message)) + { + RadioClock::MsgDateTime& report = (RadioClock::MsgDateTime&) message; + m_dateTime = report.getDateTime(); + displayDateTime(); + return true; + } + else if (RadioClock::MsgStatus::match(message)) + { + RadioClock::MsgStatus& report = (RadioClock::MsgStatus&) message; + ui->status->setText(report.getStatus()); + return true; + } + + return false; +} + +void RadioClockGUI::handleInputMessages() +{ + Message* message; + + while ((message = getInputMessageQueue()->pop()) != 0) + { + if (handleMessage(*message)) + { + delete message; + } + } +} + +void RadioClockGUI::channelMarkerChangedByCursor() +{ + ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); + m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency(); + applySettings(); +} + +void RadioClockGUI::channelMarkerHighlightedByCursor() +{ + setHighlighted(m_channelMarker.getHighlighted()); +} + +void RadioClockGUI::on_deltaFrequency_changed(qint64 value) +{ + m_channelMarker.setCenterFrequency(value); + m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency(); + applySettings(); +} + +void RadioClockGUI::on_rfBW_valueChanged(int value) +{ + ui->rfBWText->setText(QString("%1 Hz").arg(value)); + m_channelMarker.setBandwidth(value); + m_settings.m_rfBandwidth = value; + applySettings(); +} + +void RadioClockGUI::on_threshold_valueChanged(int value) +{ + ui->thresholdText->setText(QString("%1 dB").arg(value)); + m_settings.m_threshold = value; + applySettings(); +} + +void RadioClockGUI::on_modulation_currentIndexChanged(int index) +{ + m_settings.m_modulation = (RadioClockSettings::Modulation)index; + applySettings(); +} + +void RadioClockGUI::on_timezone_currentIndexChanged(int index) +{ + m_settings.m_timezone = (RadioClockSettings::DisplayTZ)index; + displayDateTime(); + applySettings(); +} + +void RadioClockGUI::on_channel1_currentIndexChanged(int index) +{ + m_settings.m_scopeCh1 = index; + applySettings(); +} + +void RadioClockGUI::on_channel2_currentIndexChanged(int index) +{ + m_settings.m_scopeCh2 = index; + applySettings(); +} + +void RadioClockGUI::onWidgetRolled(QWidget* widget, bool rollDown) +{ + (void) widget; + (void) rollDown; +} + +void RadioClockGUI::onMenuDialogCalled(const QPoint &p) +{ + if (m_contextMenuType == ContextMenuChannelSettings) + { + BasicChannelSettingsDialog dialog(&m_channelMarker, this); + dialog.setUseReverseAPI(m_settings.m_useReverseAPI); + dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); + dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); + dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex); + dialog.setReverseAPIChannelIndex(m_settings.m_reverseAPIChannelIndex); + dialog.move(p); + dialog.exec(); + + m_settings.m_rgbColor = m_channelMarker.getColor().rgb(); + m_settings.m_title = m_channelMarker.getTitle(); + m_settings.m_useReverseAPI = dialog.useReverseAPI(); + m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); + m_settings.m_reverseAPIPort = dialog.getReverseAPIPort(); + m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex(); + m_settings.m_reverseAPIChannelIndex = dialog.getReverseAPIChannelIndex(); + + setWindowTitle(m_settings.m_title); + setTitleColor(m_settings.m_rgbColor); + + applySettings(); + } + else if ((m_contextMenuType == ContextMenuStreamSettings) && (m_deviceUISet->m_deviceMIMOEngine)) + { + DeviceStreamSelectionDialog dialog(this); + dialog.setNumberOfStreams(m_radioClock->getNumberOfDeviceStreams()); + dialog.setStreamIndex(m_settings.m_streamIndex); + dialog.move(p); + dialog.exec(); + + m_settings.m_streamIndex = dialog.getSelectedStreamIndex(); + m_channelMarker.clearStreamIndexes(); + m_channelMarker.addStreamIndex(m_settings.m_streamIndex); + displayStreamIndex(); + applySettings(); + } + + resetContextMenuType(); +} + +RadioClockGUI::RadioClockGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent) : + ChannelGUI(parent), + ui(new Ui::RadioClockGUI), + m_pluginAPI(pluginAPI), + m_deviceUISet(deviceUISet), + m_channelMarker(this), + m_doApplySettings(true), + m_tickCount(0) +{ + ui->setupUi(this); + + setAttribute(Qt::WA_DeleteOnClose, true); + connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); + + m_radioClock = reinterpret_cast(rxChannel); + m_radioClock->setMessageQueueToGUI(getInputMessageQueue()); + + connect(&MainCore::instance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms + + m_scopeVis = m_radioClock->getScopeSink(); + m_scopeVis->setGLScope(ui->glScope); + m_scopeVis->setNbStreams(1); + m_scopeVis->setLiveRate(1000); + ui->glScope->connectTimer(MainCore::instance()->getMasterTimer()); + ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope); + + ui->status->setText("Looking for minute marker"); + + ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03))); + ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); + ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999); + ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenAndBlue); + + m_channelMarker.blockSignals(true); + m_channelMarker.setColor(Qt::yellow); + m_channelMarker.setBandwidth(m_settings.m_rfBandwidth); + m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset); + m_channelMarker.setTitle("Radio Clock"); + m_channelMarker.blockSignals(false); + m_channelMarker.setVisible(true); // activate signal on the last setting only + + setTitleColor(m_channelMarker.getColor()); + m_settings.setChannelMarker(&m_channelMarker); + m_settings.setScopeGUI(ui->scopeGUI); + + m_deviceUISet->addChannelMarker(&m_channelMarker); + m_deviceUISet->addRollupWidget(this); + + connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor())); + connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor())); + connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + + ui->scopeContainer->setVisible(false); + + displaySettings(); + applySettings(true); +} + +RadioClockGUI::~RadioClockGUI() +{ + delete ui; +} + +void RadioClockGUI::blockApplySettings(bool block) +{ + m_doApplySettings = !block; +} + +void RadioClockGUI::applySettings(bool force) +{ + if (m_doApplySettings) + { + RadioClock::MsgConfigureRadioClock* message = RadioClock::MsgConfigureRadioClock::create( m_settings, force); + m_radioClock->getInputMessageQueue()->push(message); + } +} + +void RadioClockGUI::displaySettings() +{ + m_channelMarker.blockSignals(true); + m_channelMarker.setBandwidth(m_settings.m_rfBandwidth); + m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset); + m_channelMarker.setTitle(m_settings.m_title); + m_channelMarker.blockSignals(false); + m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only + + setTitleColor(m_settings.m_rgbColor); + setWindowTitle(m_channelMarker.getTitle()); + + blockApplySettings(true); + + ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); + + ui->rfBWText->setText(QString("%1 Hz").arg((int)m_settings.m_rfBandwidth)); + ui->rfBW->setValue(m_settings.m_rfBandwidth); + + ui->thresholdText->setText(QString("%1 dB").arg(m_settings.m_threshold)); + ui->threshold->setValue(m_settings.m_threshold); + + ui->modulation->setCurrentIndex((int)m_settings.m_modulation); + ui->timezone->setCurrentIndex((int)m_settings.m_timezone); + + displayStreamIndex(); + + ui->channel1->setCurrentIndex(m_settings.m_scopeCh1); + ui->channel2->setCurrentIndex(m_settings.m_scopeCh2); + + blockApplySettings(false); +} + +void RadioClockGUI::displayStreamIndex() +{ + if (m_deviceUISet->m_deviceMIMOEngine) { + setStreamIndicator(tr("%1").arg(m_settings.m_streamIndex)); + } else { + setStreamIndicator("S"); // single channel indicator + } +} + +void RadioClockGUI::leaveEvent(QEvent*) +{ + m_channelMarker.setHighlighted(false); +} + +void RadioClockGUI::enterEvent(QEvent*) +{ + m_channelMarker.setHighlighted(true); +} + +void RadioClockGUI::tick() +{ + double magsqAvg, magsqPeak; + int nbMagsqSamples; + m_radioClock->getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples); + double powDbAvg = CalcDb::dbPower(magsqAvg); + double powDbPeak = CalcDb::dbPower(magsqPeak); + + ui->channelPowerMeter->levelChanged( + (100.0f + powDbAvg) / 100.0f, + (100.0f + powDbPeak) / 100.0f, + nbMagsqSamples); + + if (m_tickCount % 4 == 0) { + ui->channelPower->setText(QString::number(powDbAvg, 'f', 1)); + } + + m_tickCount++; +} diff --git a/plugins/channelrx/radioclock/radioclockgui.h b/plugins/channelrx/radioclock/radioclockgui.h new file mode 100644 index 000000000..940c64e05 --- /dev/null +++ b/plugins/channelrx/radioclock/radioclockgui.h @@ -0,0 +1,100 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOCLOCKGUI_H +#define INCLUDE_RADIOCLOCKGUI_H + +#include "channel/channelgui.h" +#include "dsp/channelmarker.h" +#include "util/messagequeue.h" + +#include "radioclocksettings.h" +#include "radioclock.h" + +class PluginAPI; +class DeviceUISet; +class BasebandSampleSink; +class ScopeVis; +class ScopeVisXY; +class RadioClock; +class RadioClockGUI; + +namespace Ui { + class RadioClockGUI; +} +class RadioClockGUI; + +class RadioClockGUI : public ChannelGUI { + Q_OBJECT + +public: + static RadioClockGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel); + virtual void destroy(); + + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + +public slots: + void channelMarkerChangedByCursor(); + void channelMarkerHighlightedByCursor(); + +private: + Ui::RadioClockGUI* ui; + PluginAPI* m_pluginAPI; + DeviceUISet* m_deviceUISet; + ChannelMarker m_channelMarker; + RadioClockSettings m_settings; + bool m_doApplySettings; + ScopeVis* m_scopeVis; + + RadioClock* m_radioClock; + uint32_t m_tickCount; + MessageQueue m_inputMessageQueue; + + QDateTime m_dateTime; + + explicit RadioClockGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0); + virtual ~RadioClockGUI(); + + void blockApplySettings(bool block); + void applySettings(bool force = false); + void displaySettings(); + void displayStreamIndex(); + bool handleMessage(const Message& message); + void displayDateTime(); + + void leaveEvent(QEvent*); + void enterEvent(QEvent*); + +private slots: + void on_deltaFrequency_changed(qint64 value); + void on_rfBW_valueChanged(int index); + void on_threshold_valueChanged(int value); + void on_modulation_currentIndexChanged(int index); + void on_timezone_currentIndexChanged(int index); + void on_channel1_currentIndexChanged(int index); + void on_channel2_currentIndexChanged(int index); + void onWidgetRolled(QWidget* widget, bool rollDown); + void onMenuDialogCalled(const QPoint& p); + void handleInputMessages(); + void tick(); +}; + +#endif // INCLUDE_RADIOCLOCKGUI_H diff --git a/plugins/channelrx/radioclock/radioclockgui.ui b/plugins/channelrx/radioclock/radioclockgui.ui new file mode 100644 index 000000000..636d66bfc --- /dev/null +++ b/plugins/channelrx/radioclock/radioclockgui.ui @@ -0,0 +1,788 @@ + + + RadioClockGUI + + + + 0 + 0 + 399 + 600 + + + + + 0 + 0 + + + + + 352 + 0 + + + + + Liberation Sans + 9 + + + + Qt::StrongFocus + + + Radio Clock + + + Radio Clock + + + + + 0 + 0 + 390 + 151 + + + + + 350 + 0 + + + + Settings + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + 2 + + + + + + 16 + 0 + + + + Df + + + + + + + + 0 + 0 + + + + + 32 + 16 + + + + + Liberation Mono + 12 + + + + PointingHandCursor + + + Qt::StrongFocus + + + Demod shift frequency from center in Hz + + + + + + + Hz + + + + + + + Qt::Vertical + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Channel power + + + Qt::RightToLeft + + + 0.0 + + + + + + + dB + + + + + + + + + + + + + dB + + + + + + + + 0 + 0 + + + + + 0 + 24 + + + + + Liberation Mono + 8 + + + + Level meter (dB) top trace: average, bottom trace: instantaneous peak, tip: peak hold + + + + + + + + + Qt::Horizontal + + + + + + + + + BW + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + RF bandwidth + + + 1 + + + 100 + + + 1 + + + 100 + + + Qt::Horizontal + + + + + + + + 30 + 0 + + + + 100 Hz + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + + + TH + + + + + + + + 24 + 24 + + + + Data threshold in dB below average carrier level + + + 1 + + + 20 + + + 1 + + + 1 + + + 1 + + + + + + + 20 dB + + + + + + + + + Qt::Horizontal + + + + + + + + + Modulation + + + + + + + + 80 + 0 + + + + Modulation of the radio clock transmission + + + + MSF + + + + + DCF77 + + + + + TDF + + + + + + + + Display Timezone + + + + + + + + 100 + 0 + + + + Timezone to display the received time in + + + + Broadcast + + + + + Local + + + + + UTC + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + + + 0 + 160 + 391 + 61 + + + + Clock + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + + Date + + + + + + + + 70 + 0 + + + + Date + + + + + + true + + + + + + + Time + + + + + + + + 0 + 0 + + + + + 40 + 0 + + + + Time + + + + + + true + + + + + + + + + Qt::Horizontal + + + + + + + + + Status + + + + + + + + 100 + 0 + + + + Demodulator status + + + + + + true + + + + + + + + + + + 20 + 250 + 351 + 341 + + + + Waveforms + + + + 2 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + + Real + + + + + + + + 0 + 0 + + + + Signal to feed to scope as stream 0 real data + + + + I + + + + + Mag Sq + + + + + Mag Sq LPF + + + + + Threshold + + + + + FM demod LPF + + + + + Data + + + + + Sample + + + + + Got minute marker + + + + + + + + + 0 + 0 + + + + Imag + + + + + + + + 0 + 0 + + + + Signal to feed to scope as stream 0 imag data + + + + Q + + + + + Mag Sq + + + + + Mag Sq LPF + + + + + Threshold + + + + + FM Demod LPF + + + + + Data + + + + + Sample + + + + + Got minute marker + + + + + + + + + + + 200 + 250 + + + + + Liberation Mono + 8 + + + + + + + + + + + + + RollupWidget + QWidget +
gui/rollupwidget.h
+ 1 +
+ + ValueDialZ + QWidget +
gui/valuedialz.h
+ 1 +
+ + LevelMeterSignalDB + QWidget +
gui/levelmeter.h
+ 1 +
+ + GLScope + QWidget +
gui/glscope.h
+ 1 +
+ + GLScopeGUI + QWidget +
gui/glscopegui.h
+ 1 +
+
+ + deltaFrequency + rfBW + threshold + modulation + timezone + date + time + channel1 + channel2 + + + + + +
diff --git a/plugins/channelrx/radioclock/radioclockplugin.cpp b/plugins/channelrx/radioclock/radioclockplugin.cpp new file mode 100644 index 000000000..117ea5a79 --- /dev/null +++ b/plugins/channelrx/radioclock/radioclockplugin.cpp @@ -0,0 +1,92 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include "plugin/pluginapi.h" + +#ifndef SERVER_MODE +#include "radioclockgui.h" +#endif +#include "radioclock.h" +#include "radioclockwebapiadapter.h" +#include "radioclockplugin.h" + +const PluginDescriptor RadioClockPlugin::m_pluginDescriptor = { + RadioClock::m_channelId, + QStringLiteral("Radio Clock"), + QStringLiteral("6.14.1"), + QStringLiteral("(c) Jon Beniston, M7RCE"), + QStringLiteral("https://github.com/f4exb/sdrangel"), + true, + QStringLiteral("https://github.com/f4exb/sdrangel") +}; + +RadioClockPlugin::RadioClockPlugin(QObject* parent) : + QObject(parent), + m_pluginAPI(0) +{ +} + +const PluginDescriptor& RadioClockPlugin::getPluginDescriptor() const +{ + return m_pluginDescriptor; +} + +void RadioClockPlugin::initPlugin(PluginAPI* pluginAPI) +{ + m_pluginAPI = pluginAPI; + + m_pluginAPI->registerRxChannel(RadioClock::m_channelIdURI, RadioClock::m_channelId, this); +} + +void RadioClockPlugin::createRxChannel(DeviceAPI *deviceAPI, BasebandSampleSink **bs, ChannelAPI **cs) const +{ + if (bs || cs) + { + RadioClock *instance = new RadioClock(deviceAPI); + + if (bs) { + *bs = instance; + } + + if (cs) { + *cs = instance; + } + } +} + +#ifdef SERVER_MODE +ChannelGUI* RadioClockPlugin::createRxChannelGUI( + DeviceUISet *deviceUISet, + BasebandSampleSink *rxChannel) const +{ + (void) deviceUISet; + (void) rxChannel; + return 0; +} +#else +ChannelGUI* RadioClockPlugin::createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) const +{ + return RadioClockGUI::create(m_pluginAPI, deviceUISet, rxChannel); +} +#endif + +ChannelWebAPIAdapter* RadioClockPlugin::createChannelWebAPIAdapter() const +{ + return new RadioClockWebAPIAdapter(); +} diff --git a/plugins/channelrx/radioclock/radioclockplugin.h b/plugins/channelrx/radioclock/radioclockplugin.h new file mode 100644 index 000000000..ca8818572 --- /dev/null +++ b/plugins/channelrx/radioclock/radioclockplugin.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOCLOCKPLUGIN_H +#define INCLUDE_RADIOCLOCKPLUGIN_H + +#include +#include "plugin/plugininterface.h" + +class DeviceUISet; +class BasebandSampleSink; + +class RadioClockPlugin : public QObject, PluginInterface { + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID "sdrangel.channel.radioclock") + +public: + explicit RadioClockPlugin(QObject* parent = NULL); + + const PluginDescriptor& getPluginDescriptor() const; + void initPlugin(PluginAPI* pluginAPI); + + virtual void createRxChannel(DeviceAPI *deviceAPI, BasebandSampleSink **bs, ChannelAPI **cs) const; + virtual ChannelGUI* createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) const; + virtual ChannelWebAPIAdapter* createChannelWebAPIAdapter() const; + +private: + static const PluginDescriptor m_pluginDescriptor; + + PluginAPI* m_pluginAPI; +}; + +#endif // INCLUDE_RADIOCLOCKPLUGIN_H diff --git a/plugins/channelrx/radioclock/radioclocksettings.cpp b/plugins/channelrx/radioclock/radioclocksettings.cpp new file mode 100644 index 000000000..604f1a079 --- /dev/null +++ b/plugins/channelrx/radioclock/radioclocksettings.cpp @@ -0,0 +1,137 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 Edouard Griffiths, F4EXB. // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "dsp/dspengine.h" +#include "util/simpleserializer.h" +#include "settings/serializable.h" +#include "radioclocksettings.h" + +RadioClockSettings::RadioClockSettings() : + m_channelMarker(0), + m_scopeGUI(0) +{ + resetToDefaults(); +} + +void RadioClockSettings::resetToDefaults() +{ + m_inputFrequencyOffset = 0; + m_rfBandwidth = 50.0f; + m_threshold = 5; + m_modulation = MSF; + m_timezone = BROADCAST; + m_scopeCh1 = 2; + m_scopeCh2 = 3; + m_rgbColor = QColor(102, 0, 0).rgb(); + m_title = "Radio Clock"; + m_streamIndex = 0; + m_useReverseAPI = false; + m_reverseAPIAddress = "127.0.0.1"; + m_reverseAPIPort = 8888; + m_reverseAPIDeviceIndex = 0; + m_reverseAPIChannelIndex = 0; +} + +QByteArray RadioClockSettings::serialize() const +{ + SimpleSerializer s(1); + + s.writeS32(1, m_inputFrequencyOffset); + s.writeFloat(2, m_rfBandwidth); + s.writeFloat(4, m_threshold); + s.writeS32(5, (int)m_modulation); + s.writeS32(6, (int)m_timezone); + s.writeS32(10, m_scopeCh1); + s.writeS32(11, m_scopeCh2); + s.writeU32(12, m_rgbColor); + s.writeString(13, m_title); + if (m_channelMarker) { + s.writeBlob(14, m_channelMarker->serialize()); + } + s.writeS32(15, m_streamIndex); + s.writeBool(16, m_useReverseAPI); + s.writeString(17, m_reverseAPIAddress); + s.writeU32(18, m_reverseAPIPort); + s.writeU32(19, m_reverseAPIDeviceIndex); + s.writeU32(20, m_reverseAPIChannelIndex); + s.writeBlob(21, m_scopeGUI->serialize()); + + return s.final(); +} + +bool RadioClockSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if(!d.isValid()) + { + resetToDefaults(); + return false; + } + + if(d.getVersion() == 1) + { + QByteArray bytetmp; + uint32_t utmp; + QString strtmp; + + d.readS32(1, &m_inputFrequencyOffset, 0); + d.readFloat(2, &m_rfBandwidth, 50.0f); + d.readFloat(4, &m_threshold, 30); + d.readS32(5, (int *)&m_modulation, DCF77); + d.readS32(6, (int *)&m_timezone, BROADCAST); + d.readS32(10, &m_scopeCh1, 2); + d.readS32(11, &m_scopeCh2, 3); + d.readU32(12, &m_rgbColor, QColor(102, 0, 0).rgb()); + d.readString(13, &m_title, "Radio Clock"); + d.readBlob(14, &bytetmp); + if (m_channelMarker) { + m_channelMarker->deserialize(bytetmp); + } + d.readS32(15, &m_streamIndex, 0); + d.readBool(16, &m_useReverseAPI, false); + d.readString(17, &m_reverseAPIAddress, "127.0.0.1"); + d.readU32(18, &utmp, 0); + if ((utmp > 1023) && (utmp < 65535)) { + m_reverseAPIPort = utmp; + } else { + m_reverseAPIPort = 8888; + } + d.readU32(19, &utmp, 0); + m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp; + d.readU32(20, &utmp, 0); + m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp; + + if (m_scopeGUI) + { + d.readBlob(21, &bytetmp); + m_scopeGUI->deserialize(bytetmp); + } + + return true; + } + else + { + resetToDefaults(); + return false; + } +} + + diff --git a/plugins/channelrx/radioclock/radioclocksettings.h b/plugins/channelrx/radioclock/radioclocksettings.h new file mode 100644 index 000000000..df1765af5 --- /dev/null +++ b/plugins/channelrx/radioclock/radioclocksettings.h @@ -0,0 +1,66 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 Edouard Griffiths, F4EXB. // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOCLOCKSETTINGS_H +#define INCLUDE_RADIOCLOCKSETTINGS_H + +#include +#include + +#include "dsp/dsptypes.h" + +class Serializable; + +struct RadioClockSettings +{ + qint32 m_inputFrequencyOffset; + Real m_rfBandwidth; + Real m_threshold; //!< For MSF and DCF in dB + enum Modulation { + MSF, + DCF77, + TDF + } m_modulation; + enum DisplayTZ { + BROADCAST, + LOCAL, + UTC + } m_timezone; + int m_scopeCh1; + int m_scopeCh2; + + quint32 m_rgbColor; + QString m_title; + Serializable *m_channelMarker; + int m_streamIndex; //!< MIMO channel. Not relevant when connected to SI (single Rx). + bool m_useReverseAPI; + QString m_reverseAPIAddress; + uint16_t m_reverseAPIPort; + uint16_t m_reverseAPIDeviceIndex; + uint16_t m_reverseAPIChannelIndex; + Serializable *m_scopeGUI; + + RadioClockSettings(); + void resetToDefaults(); + void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; } + void setScopeGUI(Serializable *scopeGUI) { m_scopeGUI = scopeGUI; } + QByteArray serialize() const; + bool deserialize(const QByteArray& data); +}; + +#endif /* INCLUDE_RADIOCLOCKSETTINGS_H */ diff --git a/plugins/channelrx/radioclock/radioclocksink.cpp b/plugins/channelrx/radioclock/radioclocksink.cpp new file mode 100644 index 000000000..f3ee2f023 --- /dev/null +++ b/plugins/channelrx/radioclock/radioclocksink.cpp @@ -0,0 +1,714 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include + +#include "dsp/dspengine.h" +#include "dsp/scopevis.h" +#include "util/db.h" +#include "maincore.h" + +#include "radioclock.h" +#include "radioclocksink.h" + +RadioClockSink::RadioClockSink(RadioClock *radioClock) : + m_scopeSink(nullptr), + m_radioClock(radioClock), + m_channelSampleRate(RADIOCLOCK_CHANNEL_SAMPLE_RATE), + m_channelFrequencyOffset(0), + m_magsq(0.0), + m_magsqSum(0.0), + m_magsqPeak(0.0), + m_magsqCount(0), + m_messageQueueToChannel(nullptr), + m_data(0), + m_prevData(0), + m_sample(0), + m_lowCount(0), + m_highCount(0), + m_periodCount(0), + m_gotMinuteMarker(false), + m_second(0), + m_zeroCount(0) +{ + m_phaseDiscri.setFMScaling(RADIOCLOCK_CHANNEL_SAMPLE_RATE / (2.0f * 20.0/M_PI)); + applySettings(m_settings, true); + applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true); +} + +RadioClockSink::~RadioClockSink() +{ +} + +void RadioClockSink::setScopeSink(ScopeVis* scopeSink) +{ + m_scopeSink = scopeSink; +} + +void RadioClockSink::sampleToScope(Complex sample) +{ + if (m_scopeSink) + { + Real r = std::real(sample) * SDR_RX_SCALEF; + Real i = std::imag(sample) * SDR_RX_SCALEF; + SampleVector m_sampleBuffer1; + m_sampleBuffer1.push_back(Sample(r, i)); + std::vector vbegin; + vbegin.push_back(m_sampleBuffer1.begin()); + m_scopeSink->feed(vbegin, m_sampleBuffer1.end() - m_sampleBuffer1.begin()); + m_sampleBuffer1.clear(); + } +} + +void RadioClockSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end) +{ + Complex ci; + + 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); + m_interpolatorDistanceRemain += m_interpolatorDistance; + } + } + else // decimate + { + if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci)) + { + processOneSample(ci); + m_interpolatorDistanceRemain += m_interpolatorDistance; + } + } + } +} + +// Extract binary-coded decimal from time code - LSB first +int RadioClockSink::bcd(int firstBit, int lastBit) +{ + const int vals[] = {1, 2, 4, 8, 10, 20, 40, 80}; + int idx = 0; + int val = 0; + for (int i = firstBit; i <= lastBit; i++) + { + if (m_timeCode[i]) { + val += vals[idx]; + } + idx++; + } + return val; +} + +// Extract binary-coded decimal from time code - MSB first +int RadioClockSink::bcdMSB(int firstBit, int lastBit) +{ + const int vals[] = {1, 2, 4, 8, 10, 20, 40, 80}; + int idx = 0; + int val = 0; + for (int i = lastBit; i >= firstBit; i--) + { + if (m_timeCode[i]) { + val += vals[idx]; + } + idx++; + } + return val; +} + +// XOR bits together for parity check +int RadioClockSink::xorBits(int firstBit, int lastBit) +{ + int x = 0; + for (int i = firstBit; i <= lastBit; i++) + { + x ^= m_timeCode[i]; + } + return x; +} + +bool RadioClockSink::evenParity(int firstBit, int lastBit, int parityBit) +{ + return xorBits(firstBit, lastBit) == parityBit; +} + +bool RadioClockSink::oddParity(int firstBit, int lastBit, int parityBit) +{ + return xorBits(firstBit, lastBit) != parityBit; +} + +// German DCF77 +// https://en.wikipedia.org/wiki/DCF77 +void RadioClockSink::dcf77() +{ + // DCF77 reduces carrier by -16.5dB + m_threshold = m_thresholdMovingAverage.asDouble() * m_linearThreshold; // xdB below average + m_data = m_magsq > m_threshold; + + // Look for minute marker - 59th second carrier is held high + if ((m_data == 0) && (m_prevData == 1)) + { + if ( (m_highCount <= RADIOCLOCK_CHANNEL_SAMPLE_RATE * 2) + && (m_highCount >= RADIOCLOCK_CHANNEL_SAMPLE_RATE * 1.6) + && (m_lowCount <= RADIOCLOCK_CHANNEL_SAMPLE_RATE * 0.3) + && (m_lowCount >= RADIOCLOCK_CHANNEL_SAMPLE_RATE * 0.1) + ) + { + qDebug() << "RadioClockSink::dcf77 - Minute marker: (low " << m_lowCount << " high " << m_highCount << ") prev period " << m_periodCount; + if (getMessageQueueToChannel() && !m_gotMinuteMarker) { + getMessageQueueToChannel()->push(RadioClock::MsgStatus::create("Got minute marker")); + } + m_periodCount = 0; + m_second = 0; + m_gotMinuteMarker = true; + m_secondMarkers = 1; + } + + m_lowCount = 0; + } + else if ((m_data == 1) && (m_prevData == 0)) + { + m_highCount = 0; + } + else if (m_data == 1) + { + m_highCount++; + } + else if (m_data == 0) + { + m_lowCount++; + } + + m_sample = false; + if (m_gotMinuteMarker) + { + m_periodCount++; + if (m_periodCount == 50) + { + // Check we get second marker + m_secondMarkers += m_data == 0; + // If we see too many 1s instead of 0s, assume we've lost the signal + if ((m_second > 10) && (m_secondMarkers / m_second < 0.7)) + { + qDebug() << "RadioClockSink::dcf77 - Lost lock: " << m_secondMarkers << m_second; + m_gotMinuteMarker = false; + if (getMessageQueueToChannel()) { + getMessageQueueToChannel()->push(RadioClock::MsgStatus::create("Looking for minute marker")); + } + } + m_sample = true; + } + else if (m_periodCount == 150) + { + // Get data for timecode + m_timeCode[m_second] = !m_data; // No carrier = 1, carrier = 0 + m_sample = true; + } + else if (m_periodCount == 950) + { + if (m_second == 59) + { + // Decode timecode to a time and date + int minute = bcd(21, 27); + int hour = bcd(29, 34); + int day = bcd(36, 41); + int month = bcd(45, 49); + int year = 2000 + bcd(50, 57); + + QString parityError; + if (!evenParity(21, 27, m_timeCode[28])) { + parityError = "Minute parity error"; + } + if (!evenParity(29, 34, m_timeCode[35])) { + parityError = "Hour parity error"; + } + if (!evenParity(36, 57, m_timeCode[58])) { + parityError= "Data parity error"; + } + + if (parityError.isEmpty()) + { + // Bit 17 indicates CEST rather than CET + m_dateTime = QDateTime(QDate(year, month, day), QTime(hour, minute), Qt::OffsetFromUTC, m_timeCode[17] ? 2*3600 : 3600); + if (getMessageQueueToChannel()) { + getMessageQueueToChannel()->push(RadioClock::MsgStatus::create("OK")); + } + } + else + { + m_dateTime = m_dateTime.addSecs(1); + if (getMessageQueueToChannel()) { + getMessageQueueToChannel()->push(RadioClock::MsgStatus::create(parityError)); + } + } + m_second = 0; + } + else + { + m_second++; + m_dateTime = m_dateTime.addSecs(1); + } + + if (getMessageQueueToChannel()) + { + RadioClock::MsgDateTime *msg = RadioClock::MsgDateTime::create(m_dateTime); + getMessageQueueToChannel()->push(msg); + } + } + else if (m_periodCount == 1000) + { + m_periodCount = 0; + } + } + m_prevData = m_data; +} + +// French TDF 162kHz +// https://en.wikipedia.org/wiki/TDF_time_signal +// Uses phase modulation, rather than OOK +void RadioClockSink::tdf(Complex &ci) +{ + // FM demodulation + double magsqRaw; + Real deviation; + Real fmDemod = m_phaseDiscri.phaseDiscriminatorDelta(ci, magsqRaw, deviation); + + // Filter + m_fmDemodMovingAverage(fmDemod); + + // Ternary encoding + Real avg = m_fmDemodMovingAverage.asDouble(); + if (avg >= 0.5) { + m_data = 1; + } else if (avg <= -0.5) { + m_data = -1; + } else { + m_data = 0; + } + + // Look for minute marker - 59th second is not phase modulated + if ((m_data == 1) && (m_prevData == 0)) + { + if ( (m_zeroCount <= RADIOCLOCK_CHANNEL_SAMPLE_RATE * 2) + && (m_zeroCount >= RADIOCLOCK_CHANNEL_SAMPLE_RATE * 1) + ) + { + qDebug() << "RadioClockSink::tdf - Minute marker: (zero " << m_zeroCount << ") prev period " << m_periodCount; + if (getMessageQueueToChannel() && !m_gotMinuteMarker) { + getMessageQueueToChannel()->push(RadioClock::MsgStatus::create("Got minute marker")); + } + m_periodCount = 0; + m_second = 0; + m_gotMinuteMarker = true; + m_secondMarkers = 1; + } + } + else if ((m_data == 0) && (m_prevData != 0)) + { + m_zeroCount = 0; + } + else if (m_data == 0) + { + m_zeroCount++; + } + + m_sample = false; + if (m_gotMinuteMarker) + { + m_periodCount++; + if (m_periodCount == 12) + { + m_bits[0] = m_data; + m_sample = true; + } + else if (m_periodCount == 12+50) + { + m_bits[1] = m_data; + m_sample = true; + } + else if (m_periodCount == 12+100) + { + m_bits[2] = m_data; + m_sample = true; + } + else if (m_periodCount == 12+150) + { + m_bits[3] = m_data; + m_sample = true; + + // Check we got second marker + m_secondMarkers += ((m_bits[0] == 1) && (m_bits[1] == -1)); + // If too many second markers are missing, assume we've lost the signal + if ((m_second > 10) && (m_secondMarkers / m_second < 0.7)) + { + qDebug() << "RadioClockSink::tdf - Lost lock: " << m_secondMarkers << m_second; + m_gotMinuteMarker = false; + if (getMessageQueueToChannel()) { + getMessageQueueToChannel()->push(RadioClock::MsgStatus::create("Looking for minute marker")); + } + } + + // No phase modulation from 50ms to 150ms is 0, pos then neg is 1 + if ((m_bits[2] == 0) && (m_bits[3] == 0)) { + m_timeCode[m_second] = 0; + } else if ((m_bits[2] == 1) && (m_bits[3] == -1)) { + m_timeCode[m_second] = 1; + } else { + //qDebug() << "Unexpected modulation " << m_second; + } + } + else if (m_periodCount == 950) + { + if (m_second == 59) + { + // Decode timecode to time and date + int minute = bcd(21, 27); + int hour = bcd(29, 34); + int day = bcd(36, 41); + int month = bcd(45, 49); + int year = 2000 + bcd(50, 57); + + QString parityError; + if (!evenParity(21, 27, m_timeCode[28])) { + parityError = "Minute parity error"; + } + if (!evenParity(29, 34, m_timeCode[35])) { + parityError = "Hour parity error"; + } + if (!evenParity(36, 57, m_timeCode[58])) { + parityError= "Data parity error"; + } + + if (parityError.isEmpty()) + { + // Bit 17 indicates CEST rather than CET + m_dateTime = QDateTime(QDate(year, month, day), QTime(hour, minute), Qt::OffsetFromUTC, m_timeCode[17] ? 2*3600 : 3600); + if (getMessageQueueToChannel()) { + getMessageQueueToChannel()->push(RadioClock::MsgStatus::create("OK")); + } + } + else + { + m_dateTime = m_dateTime.addSecs(1); + if (getMessageQueueToChannel()) { + getMessageQueueToChannel()->push(RadioClock::MsgStatus::create(parityError)); + } + } + m_second = 0; + } + else + { + m_second++; + m_dateTime = m_dateTime.addSecs(1); + } + + if (getMessageQueueToChannel()) + { + RadioClock::MsgDateTime *msg = RadioClock::MsgDateTime::create(m_dateTime); + getMessageQueueToChannel()->push(msg); + } + } + else if (m_periodCount == 1000) + { + m_periodCount = 0; + } + } + m_prevData = m_data; +} + +// UK MSF 60kHz +// https://www.npl.co.uk/products-services/time-frequency/msf-radio-time-signal/msf_time_date_code +void RadioClockSink::msf60() +{ + m_threshold = m_thresholdMovingAverage.asDouble() * m_linearThreshold; // xdB below average + m_data = m_magsq > m_threshold; + + // Look for minute marker - 500ms low, then 500ms high + if ((m_data == 0) && (m_prevData == 1)) + { + if ( (m_highCount <= RADIOCLOCK_CHANNEL_SAMPLE_RATE * 0.6) + && (m_highCount >= RADIOCLOCK_CHANNEL_SAMPLE_RATE * 0.4) + && (m_lowCount <= RADIOCLOCK_CHANNEL_SAMPLE_RATE * 0.6) + && (m_lowCount >= RADIOCLOCK_CHANNEL_SAMPLE_RATE * 0.4) + ) + { + qDebug() << "RadioClockSink::msf60 - Minute marker: (low " << m_lowCount << " high " << m_highCount << ") prev period " << m_periodCount; + if (getMessageQueueToChannel() && !m_gotMinuteMarker) { + getMessageQueueToChannel()->push(RadioClock::MsgStatus::create("Got minute marker")); + } + m_periodCount = 0; + m_second = 1; + m_gotMinuteMarker = true; + m_secondMarkers = 1; + } + m_lowCount = 0; + } + else if ((m_data == 1) && (m_prevData == 0)) + { + m_highCount = 0; + } + else if (m_data == 1) + { + m_highCount++; + } + else if (m_data == 0) + { + m_lowCount++; + } + + m_sample = false; + if (m_gotMinuteMarker) + { + m_periodCount++; + if (m_periodCount == 50) + { + // Check we get second marker + m_secondMarkers += m_data == 0; + // If we see too many 1s instead of 0s, assume we've lost the signal + if ((m_second > 10) && (m_secondMarkers / m_second < 0.7)) + { + qDebug() << "RadioClockSink::msf60 - Lost lock: " << m_secondMarkers << m_second; + m_gotMinuteMarker = false; + if (getMessageQueueToChannel()) { + getMessageQueueToChannel()->push(RadioClock::MsgStatus::create("Looking for minute marker")); + } + } + m_sample = true; + } + else if (m_periodCount == 150) + { + // Get data bit A for timecode + m_timeCode[m_second] = !m_data; // No carrier = 1, carrier = 0 + m_sample = true; + } + else if (m_periodCount == 250) + { + // Get data bit B for timecode + m_timeCodeB[m_second] = !m_data; + m_sample = true; + } + else if (m_periodCount == 950) + { + if (m_second == 59) + { + // Decode timecode to time and date + int minute = bcdMSB(45, 51); + int hour = bcdMSB(39, 44); + int day = bcdMSB(30, 35); + //int dayOfWeek = bcdMSB(36, 38); + int month = bcdMSB(25, 29); + int year = 2000 + bcdMSB(17, 24); + + QString parityError; + if (!oddParity(39, 51, m_timeCodeB[57])) { + parityError = "Hour/minute parity error"; + } + if (!oddParity(25, 35, m_timeCodeB[55])) { + parityError= "Day/month parity error"; + } + if (!oddParity(17, 24, m_timeCodeB[54])) { + parityError = "Hour/minute parity error"; + } + + if (parityError.isEmpty()) + { + // Bit 58B indicates BST rather than GMT + m_dateTime = QDateTime(QDate(year, month, day), QTime(hour, minute), Qt::OffsetFromUTC, m_timeCodeB[58] ? 1*3600 : 0); + if (getMessageQueueToChannel()) { + getMessageQueueToChannel()->push(RadioClock::MsgStatus::create("OK")); + } + } + else + { + m_dateTime = m_dateTime.addSecs(1); + if (getMessageQueueToChannel()) { + getMessageQueueToChannel()->push(RadioClock::MsgStatus::create(parityError)); + } + } + m_second = 0; + } + else + { + m_second++; + m_dateTime = m_dateTime.addSecs(1); + } + + if (getMessageQueueToChannel()) + { + RadioClock::MsgDateTime *msg = RadioClock::MsgDateTime::create(m_dateTime); + getMessageQueueToChannel()->push(msg); + } + } + else if (m_periodCount == 1000) + { + m_periodCount = 0; + } + } + + m_prevData = m_data; +} + +void RadioClockSink::processOneSample(Complex &ci) +{ + Complex ca; + + // Calculate average and peak levels for level meter + Real re = ci.real() / SDR_RX_SCALEF; + Real im = ci.imag() / SDR_RX_SCALEF; + Real magsq = re*re + im*im; + m_movingAverage(magsq); + m_thresholdMovingAverage(magsq); + m_magsq = m_movingAverage.asDouble(); + m_magsqSum += magsq; + if (magsq > m_magsqPeak) + { + m_magsqPeak = magsq; + } + m_magsqCount++; + + // Demodulate + if (m_settings.m_modulation == RadioClockSettings::DCF77) { + dcf77(); + } else if (m_settings.m_modulation == RadioClockSettings::TDF) { + tdf(ci); + } else { + msf60(); + } + + // Select signals to feed to scope + Complex scopeSample; + switch (m_settings.m_scopeCh1) + { + case 0: + scopeSample.real(ci.real() / SDR_RX_SCALEF); + break; + case 1: + scopeSample.real(magsq * 1e6); + break; + case 2: + scopeSample.real(m_magsq * 1e6); + break; + case 3: + scopeSample.real(m_threshold * 1e6); + break; + case 4: + scopeSample.real(m_fmDemodMovingAverage.asDouble()); + break; + case 5: + scopeSample.real(m_data); + break; + case 6: + scopeSample.real(m_sample); + break; + case 7: + scopeSample.real(m_gotMinuteMarker); + break; + } + switch (m_settings.m_scopeCh2) + { + case 0: + scopeSample.imag(ci.imag() / SDR_RX_SCALEF); + break; + case 1: + scopeSample.imag(magsq * 1e6); + break; + case 2: + scopeSample.imag(m_magsq * 1e6); + break; + case 3: + scopeSample.imag(m_threshold * 1e6); + break; + case 4: + scopeSample.imag(m_fmDemodMovingAverage.asDouble()); + break; + case 5: + scopeSample.imag(m_data); + break; + case 6: + scopeSample.imag(m_sample); + break; + case 7: + scopeSample.imag(m_gotMinuteMarker); + break; + } + sampleToScope(scopeSample); +} + +void RadioClockSink::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force) +{ + qDebug() << "RadioClockSink::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_rfBandwidth / 2.2); + m_interpolatorDistance = (Real) channelSampleRate / (Real) RADIOCLOCK_CHANNEL_SAMPLE_RATE; + m_interpolatorDistanceRemain = m_interpolatorDistance; + } + + m_channelSampleRate = channelSampleRate; + m_channelFrequencyOffset = channelFrequencyOffset; +} + +void RadioClockSink::applySettings(const RadioClockSettings& settings, bool force) +{ + qDebug() << "RadioClockSink::applySettings:" + << " m_rfBandwidth: " << settings.m_rfBandwidth + << " m_threshold: " << settings.m_threshold + << " m_modulation: " << settings.m_modulation + << " force: " << force; + + if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) + { + m_interpolator.create(16, m_channelSampleRate, settings.m_rfBandwidth / 2.2); + m_interpolatorDistance = (Real) m_channelSampleRate / (Real) RADIOCLOCK_CHANNEL_SAMPLE_RATE; + m_interpolatorDistanceRemain = m_interpolatorDistance; + } + + if ((settings.m_threshold != m_settings.m_threshold) || force) + { + m_linearThreshold = CalcDb::powerFromdB(-settings.m_threshold); + } + + if ((settings.m_modulation != m_settings.m_modulation) || force) + { + m_gotMinuteMarker = false; + m_lowCount = 0; + m_highCount = 0; + m_zeroCount = 0; + m_second = 0; + if (getMessageQueueToChannel()) { + getMessageQueueToChannel()->push(RadioClock::MsgStatus::create("Looking for minute marker")); + } + } + + m_settings = settings; +} diff --git a/plugins/channelrx/radioclock/radioclocksink.h b/plugins/channelrx/radioclock/radioclocksink.h new file mode 100644 index 000000000..9f7eb76e8 --- /dev/null +++ b/plugins/channelrx/radioclock/radioclocksink.h @@ -0,0 +1,158 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOCLOCKSINK_H +#define INCLUDE_RADIOCLOCKSINK_H + +#include +#include + +#include "dsp/channelsamplesink.h" +#include "dsp/phasediscri.h" +#include "dsp/nco.h" +#include "dsp/interpolator.h" +#include "dsp/firfilter.h" +#include "dsp/fftfactory.h" +#include "dsp/fftengine.h" +#include "dsp/fftwindow.h" +#include "util/movingaverage.h" +#include "util/doublebufferfifo.h" +#include "util/messagequeue.h" + +#include "radioclocksettings.h" + +#include +#include +#include + +#define RADIOCLOCK_CHANNEL_SAMPLE_RATE 1000 + +class ChannelAPI; +class RadioClock; +class ScopeVis; + +class RadioClockSink : public ChannelSampleSink { +public: + RadioClockSink(RadioClock *radioClock); + ~RadioClockSink(); + + virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end); + + void setScopeSink(ScopeVis* scopeSink); + void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false); + void applySettings(const RadioClockSettings& settings, bool force = false); + void setMessageQueueToChannel(MessageQueue *messageQueue) { m_messageQueueToChannel = messageQueue; } + void setChannel(ChannelAPI *channel) { m_channel = channel; } + + double getMagSq() const { return m_magsq; } + + void getMagSqLevels(double& avg, double& peak, int& nbSamples) + { + if (m_magsqCount > 0) + { + m_magsq = m_magsqSum / m_magsqCount; + m_magSqLevelStore.m_magsq = m_magsq; + m_magSqLevelStore.m_magsqPeak = m_magsqPeak; + } + + avg = m_magSqLevelStore.m_magsq; + peak = m_magSqLevelStore.m_magsqPeak; + nbSamples = m_magsqCount == 0 ? 1 : m_magsqCount; + + m_magsqSum = 0.0f; + m_magsqPeak = 0.0f; + m_magsqCount = 0; + } + + +private: + struct MagSqLevelsStore + { + MagSqLevelsStore() : + m_magsq(1e-12), + m_magsqPeak(1e-12) + {} + double m_magsq; + double m_magsqPeak; + }; + + ScopeVis* m_scopeSink; // Scope GUI to display debug waveforms + RadioClock *m_radioClock; + RadioClockSettings m_settings; + ChannelAPI *m_channel; + int m_channelSampleRate; + int m_channelFrequencyOffset; + + NCO m_nco; + Interpolator m_interpolator; + Real m_interpolatorDistance; + Real m_interpolatorDistanceRemain; + + double m_magsq; + double m_magsqSum; + double m_magsqPeak; + int m_magsqCount; + MagSqLevelsStore m_magSqLevelStore; + + MessageQueue *m_messageQueueToChannel; + + MovingAverageUtil m_movingAverage; //!< Moving average has sharpest step response of LPFs + + MovingAverageUtil m_thresholdMovingAverage; // Average over 1 second + + int m_data; //!< Demod data before clocking + int m_prevData; //!< Previous value of m_data + int m_sample; //!< For scope, indicates when data is sampled + + int m_lowCount; //!< Number of consecutive 0 samples + int m_highCount; //!< Number of consecutive 1 samples + int m_periodCount; //!< Counts from 1-RADIOCLOCK_CHANNEL_SAMPLE_RATE + bool m_gotMinuteMarker; //!< Minute marker has been seen + int m_second; //!< Which second we are in + int m_timeCode[61]; //!< Timecode from data in each second + QDateTime m_dateTime; //!< Decoded date and time + + int m_secondMarkers; //!< Counts number of second markers that have been seen + + Real m_threshold; //!< Current threshold for display on scope + Real m_linearThreshold; //!< settings.m_threshold as a linear value rather than dB + + // MSF demod state + int m_timeCodeB[61]; + + // TDF demod state + PhaseDiscriminators m_phaseDiscri; // FM demodulator + int m_zeroCount; + MovingAverageUtil m_fmDemodMovingAverage; + int m_bits[4]; + + void processOneSample(Complex &ci); + MessageQueue *getMessageQueueToChannel() { return m_messageQueueToChannel; } + void sampleToScope(Complex sample); + int bcd(int firstBit, int lastBit); + int bcdMSB(int firstBit, int lastBit); + int xorBits(int firstBit, int lastBit); + bool evenParity(int firstBit, int lastBit, int parityBit); + bool oddParity(int firstBit, int lastBit, int parityBit); + + void dcf77(); + void tdf(Complex &ci); + void msf60(); +}; + +#endif // INCLUDE_RADIOCLOCKSINK_H diff --git a/plugins/channelrx/radioclock/radioclockwebapiadapter.cpp b/plugins/channelrx/radioclock/radioclockwebapiadapter.cpp new file mode 100644 index 000000000..b6677e18d --- /dev/null +++ b/plugins/channelrx/radioclock/radioclockwebapiadapter.cpp @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB. // +// Copyright (C) 2021 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "SWGChannelSettings.h" +#include "radioclock.h" +#include "radioclockwebapiadapter.h" + +RadioClockWebAPIAdapter::RadioClockWebAPIAdapter() +{} + +RadioClockWebAPIAdapter::~RadioClockWebAPIAdapter() +{} + +int RadioClockWebAPIAdapter::webapiSettingsGet( + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage) +{ + (void) errorMessage; + response.setRadioClockSettings(new SWGSDRangel::SWGRadioClockSettings()); + response.getRadioClockSettings()->init(); + RadioClock::webapiFormatChannelSettings(response, m_settings); + + return 200; +} + +int RadioClockWebAPIAdapter::webapiSettingsPutPatch( + bool force, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage) +{ + (void) force; + (void) errorMessage; + RadioClock::webapiUpdateChannelSettings(m_settings, channelSettingsKeys, response); + + return 200; +} diff --git a/plugins/channelrx/radioclock/radioclockwebapiadapter.h b/plugins/channelrx/radioclock/radioclockwebapiadapter.h new file mode 100644 index 000000000..1206078d9 --- /dev/null +++ b/plugins/channelrx/radioclock/radioclockwebapiadapter.h @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019 Edouard Griffiths, F4EXB. // +// Copyright (C) 2020 Jon Beniston, M7RCE // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_RADIOCLOCK_WEBAPIADAPTER_H +#define INCLUDE_RADIOCLOCK_WEBAPIADAPTER_H + +#include "channel/channelwebapiadapter.h" +#include "radioclocksettings.h" + +/** + * Standalone API adapter only for the settings + */ +class RadioClockWebAPIAdapter : public ChannelWebAPIAdapter { +public: + RadioClockWebAPIAdapter(); + virtual ~RadioClockWebAPIAdapter(); + + virtual QByteArray serialize() const { return m_settings.serialize(); } + virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); } + + virtual int webapiSettingsGet( + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage); + + virtual int webapiSettingsPutPatch( + bool force, + const QStringList& channelSettingsKeys, + SWGSDRangel::SWGChannelSettings& response, + QString& errorMessage); + +private: + RadioClockSettings m_settings; +}; + +#endif // INCLUDE_RADIOCLOCK_WEBAPIADAPTER_H diff --git a/plugins/channelrx/radioclock/readme.md b/plugins/channelrx/radioclock/readme.md new file mode 100644 index 000000000..535aa268d --- /dev/null +++ b/plugins/channelrx/radioclock/readme.md @@ -0,0 +1,77 @@ +

Radio clock plugin

+ +

Introduction

+ +This plugin can be used to receive the time and date as broadcast on Low Frequency (LF) by various transmitters that are tied to atomic clocks: + +* [MSF](https://en.wikipedia.org/wiki/Time_from_NPL_(MSF)) - UK - 60kHz +* [DCF77](https://en.wikipedia.org/wiki/DCF77) - Germany - 77.5kHz +* [TDF](https://en.wikipedia.org/wiki/TDF_time_signal) - France - 162kHz + +If you'd like other transmitters to be supported (such as WWVB), please upload a .sdriq file to SDRangel's [github issue tracker](https://github.com/f4exb/sdrangel/issues). + +Typically, it will take two minutes before the time is able to be displayed (up to one minute to find the minute marker, then another minute to receive the timecode). + +Although the atomic clocks used to transmit the timecode are extremely accurate, propagation, SDR data transfer and demodulation delays limit accuracy of the displayed time to around 1 second. + +

Interface

+ +![Radio clock plugin GUI](../../../doc/img/Radio_clock_plugin.png) + +

1: Frequency shift from center frequency of reception

+ +Use the wheels to adjust the frequency shift in Hz from the center frequency of reception. Left click on a digit sets the cursor position at this digit. Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position. Wheels are moved with the mousewheel while pointing at the wheel or by selecting the wheel with the left mouse click and using the keyboard arrows. Pressing shift simultaneously moves digit by 5 and pressing control moves it by 2. + +

2: Channel power

+ +Average total power in dB relative to a +/- 1.0 amplitude signal received in the pass band. + +

3: Level meter in dB

+ + - top bar (green): average value + - bottom bar (blue green): instantaneous peak value + - tip vertical bar (bright green): peak hold value + +

4: BW - RF Bandwidth

+ +This specifies the bandwidth of a LPF that is applied to the input signal to limit the RF bandwidth. + +

5: TH - Threshold

+ +For MSF and DCF77, specifies the threshold in dB below the average carrier power level that determines a binary 0 or 1. + +

6: Modulation

+ +Specifies the modulation and timecode encoding used: + +* MSF - OOK (On-off keying) +* DCF77 - OOK (On-off keying) +* TDF - PM (Phase modulation) + +

7: Display Timezone

+ +Specifies the timezone used to display the received time. This can be: + +* Broadcast - the time is displayed as broadcast (which is typically the timezone of the country the signal is broadcast from, adjusted for summer time). +* Local - the time is converted to the local time (as determined by your operating system's timezone). +* UTC - the time is converted to Coordinated Universal Time. + +

8: Date

+ +Displays the decoded date. + +

9: Time

+ +Displays the decoded time, adjusted for the timezone set by (7). + +

10: Status

+ +Displays the demodulator status. This can be: + +* Looking for minute marker - Indicated at startup or after signal lost, while looking for the minute marker. +* Got minute marker - Indicated after finding the minute marker and waiting for the first timecode to be received. +* OK - Indicates timecodes are being received. + +The date and time fields are only valid when the status indicates OK. + +If while in the OK state several second markers are missed, the status will return to Acquiring Signal. diff --git a/sdrbase/webapi/webapirequestmapper.cpp b/sdrbase/webapi/webapirequestmapper.cpp index a0cb5fce2..38a2f131a 100644 --- a/sdrbase/webapi/webapirequestmapper.cpp +++ b/sdrbase/webapi/webapirequestmapper.cpp @@ -3961,6 +3961,11 @@ bool WebAPIRequestMapper::getChannelSettings( channelSettings->setPacketModSettings(new SWGSDRangel::SWGPacketModSettings()); channelSettings->getPacketModSettings()->fromJsonObject(settingsJsonObject); } + else if (channelSettingsKey == "RadioClockSettings") + { + channelSettings->setRadioClockSettings(new SWGSDRangel::SWGRadioClockSettings()); + channelSettings->getRadioClockSettings()->fromJsonObject(settingsJsonObject); + } else if (channelSettingsKey == "RemoteSinkSettings") { channelSettings->setRemoteSinkSettings(new SWGSDRangel::SWGRemoteSinkSettings()); diff --git a/sdrbase/webapi/webapiutils.cpp b/sdrbase/webapi/webapiutils.cpp index 6e87ce597..bfe6d8c68 100644 --- a/sdrbase/webapi/webapiutils.cpp +++ b/sdrbase/webapi/webapiutils.cpp @@ -56,6 +56,7 @@ const QMap WebAPIUtils::m_channelURIToSettingsKey = { {"sdrangel.channel.packetdemod", "PacketDemodSettings"}, {"sdrangel.channeltx.modpacket", "PacketModSettings"}, {"sdrangel.channeltx.mod802.15.4", "IEEE_802_15_4_ModSettings"}, + {"sdrangel.channel.radioclock", "RadioClockSettings"}, {"sdrangel.demod.remotesink", "RemoteSinkSettings"}, {"sdrangel.channeltx.remotesource", "RemoteSourceSettings"}, {"sdrangel.channeltx.modssb", "SSBModSettings"}, @@ -153,6 +154,7 @@ const QMap WebAPIUtils::m_channelTypeToSettingsKey = { {"PacketMod", "PacketModSettings"}, {"LocalSink", "LocalSinkSettings"}, {"LocalSource", "LocalSourceSettings"}, + {"RadioClock", "RadioClockSettings"}, {"RemoteSink", "RemoteSinkSettings"}, {"RemoteSource", "RemoteSourceSettings"}, {"SSBMod", "SSBModSettings"}, diff --git a/swagger/sdrangel/api/swagger/include/ChannelReport.yaml b/swagger/sdrangel/api/swagger/include/ChannelReport.yaml index 35ba64e62..eb4917333 100644 --- a/swagger/sdrangel/api/swagger/include/ChannelReport.yaml +++ b/swagger/sdrangel/api/swagger/include/ChannelReport.yaml @@ -53,6 +53,8 @@ ChannelReport: $ref: "http://swgserver:8081/api/swagger/include/NoiseFigure.yaml#/NoiseFigureReport" SSBDemodReport: $ref: "http://swgserver:8081/api/swagger/include/SSBDemod.yaml#/SSBDemodReport" + RadioClockReport: + $ref: "http://swgserver:8081/api/swagger/include/RadioClock.yaml#/RadioClockReport" RemoteSourceReport: $ref: "http://swgserver:8081/api/swagger/include/RemoteSource.yaml#/RemoteSourceReport" PacketModReport: diff --git a/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml b/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml index 5c3861299..6ad687ace 100644 --- a/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml +++ b/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml @@ -79,6 +79,8 @@ ChannelSettings: $ref: "http://swgserver:8081/api/swagger/include/PacketDemod.yaml#/PacketDemodSettings" PacketModSettings: $ref: "http://swgserver:8081/api/swagger/include/PacketMod.yaml#/PacketModSettings" + RadioClockSettings: + $ref: "http://swgserver:8081/api/swagger/include/RadioClock.yaml#/RadioClockSettings" RemoteSinkSettings: $ref: "http://swgserver:8081/api/swagger/include/RemoteSink.yaml#/RemoteSinkSettings" RemoteSourceSettings: diff --git a/swagger/sdrangel/api/swagger/include/RadioClock.yaml b/swagger/sdrangel/api/swagger/include/RadioClock.yaml new file mode 100644 index 000000000..3bb5e9618 --- /dev/null +++ b/swagger/sdrangel/api/swagger/include/RadioClock.yaml @@ -0,0 +1,52 @@ +RadioClockSettings: + description: RadioClock + properties: + inputFrequencyOffset: + description: channel center frequency shift from baseband center in Hz + type: integer + format: int64 + rfBandwidth: + description: channel RF bandwidth in Hz + type: number + format: float + threshold: + type: number + format: float + modulation: + description: 0 - MSF, 1 - DCF77, 2 - TDF + type: integer + timezone: + description: 0 - Broadcast, 1 - Local, 2 - UTC + type: integer + rgbColor: + type: integer + title: + type: string + streamIndex: + description: MIMO channel. Not relevant when connected to SI (single Rx). + type: integer + useReverseAPI: + description: Synchronize with reverse API (1 for yes, 0 for no) + type: integer + reverseAPIAddress: + type: string + reverseAPIPort: + type: integer + reverseAPIDeviceIndex: + type: integer + reverseAPIChannelIndex: + type: integer + +RadioClockReport: + description: RadioClock + properties: + channelPowerDB: + description: power received in channel (dB) + type: number + format: float + channelSampleRate: + type: integer + date: + type: string + time: + type: string diff --git a/swagger/sdrangel/code/qt5/client/SWGChannelReport.cpp b/swagger/sdrangel/code/qt5/client/SWGChannelReport.cpp index b4021c8c1..316764c58 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChannelReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGChannelReport.cpp @@ -74,6 +74,8 @@ SWGChannelReport::SWGChannelReport() { m_noise_figure_report_isSet = false; ssb_demod_report = nullptr; m_ssb_demod_report_isSet = false; + radio_clock_report = nullptr; + m_radio_clock_report_isSet = false; remote_source_report = nullptr; m_remote_source_report_isSet = false; packet_mod_report = nullptr; @@ -148,6 +150,8 @@ SWGChannelReport::init() { m_noise_figure_report_isSet = false; ssb_demod_report = new SWGSSBDemodReport(); m_ssb_demod_report_isSet = false; + radio_clock_report = new SWGRadioClockReport(); + m_radio_clock_report_isSet = false; remote_source_report = new SWGRemoteSourceReport(); m_remote_source_report_isSet = false; packet_mod_report = new SWGPacketModReport(); @@ -239,6 +243,9 @@ SWGChannelReport::cleanup() { if(ssb_demod_report != nullptr) { delete ssb_demod_report; } + if(radio_clock_report != nullptr) { + delete radio_clock_report; + } if(remote_source_report != nullptr) { delete remote_source_report; } @@ -328,6 +335,8 @@ SWGChannelReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&ssb_demod_report, pJson["SSBDemodReport"], "SWGSSBDemodReport", "SWGSSBDemodReport"); + ::SWGSDRangel::setValue(&radio_clock_report, pJson["RadioClockReport"], "SWGRadioClockReport", "SWGRadioClockReport"); + ::SWGSDRangel::setValue(&remote_source_report, pJson["RemoteSourceReport"], "SWGRemoteSourceReport", "SWGRemoteSourceReport"); ::SWGSDRangel::setValue(&packet_mod_report, pJson["PacketModReport"], "SWGPacketModReport", "SWGPacketModReport"); @@ -433,6 +442,9 @@ SWGChannelReport::asJsonObject() { if((ssb_demod_report != nullptr) && (ssb_demod_report->isSet())){ toJsonValue(QString("SSBDemodReport"), ssb_demod_report, obj, QString("SWGSSBDemodReport")); } + if((radio_clock_report != nullptr) && (radio_clock_report->isSet())){ + toJsonValue(QString("RadioClockReport"), radio_clock_report, obj, QString("SWGRadioClockReport")); + } if((remote_source_report != nullptr) && (remote_source_report->isSet())){ toJsonValue(QString("RemoteSourceReport"), remote_source_report, obj, QString("SWGRemoteSourceReport")); } @@ -697,6 +709,16 @@ SWGChannelReport::setSsbDemodReport(SWGSSBDemodReport* ssb_demod_report) { this->m_ssb_demod_report_isSet = true; } +SWGRadioClockReport* +SWGChannelReport::getRadioClockReport() { + return radio_clock_report; +} +void +SWGChannelReport::setRadioClockReport(SWGRadioClockReport* radio_clock_report) { + this->radio_clock_report = radio_clock_report; + this->m_radio_clock_report_isSet = true; +} + SWGRemoteSourceReport* SWGChannelReport::getRemoteSourceReport() { return remote_source_report; @@ -871,6 +893,9 @@ SWGChannelReport::isSet(){ if(ssb_demod_report && ssb_demod_report->isSet()){ isObjectUpdated = true; break; } + if(radio_clock_report && radio_clock_report->isSet()){ + isObjectUpdated = true; break; + } if(remote_source_report && remote_source_report->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGChannelReport.h b/swagger/sdrangel/code/qt5/client/SWGChannelReport.h index ba3fddb2d..06a5be0d9 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChannelReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGChannelReport.h @@ -43,6 +43,7 @@ #include "SWGNFMModReport.h" #include "SWGNoiseFigureReport.h" #include "SWGPacketModReport.h" +#include "SWGRadioClockReport.h" #include "SWGRemoteSourceReport.h" #include "SWGSSBDemodReport.h" #include "SWGSSBModReport.h" @@ -142,6 +143,9 @@ public: SWGSSBDemodReport* getSsbDemodReport(); void setSsbDemodReport(SWGSSBDemodReport* ssb_demod_report); + SWGRadioClockReport* getRadioClockReport(); + void setRadioClockReport(SWGRadioClockReport* radio_clock_report); + SWGRemoteSourceReport* getRemoteSourceReport(); void setRemoteSourceReport(SWGRemoteSourceReport* remote_source_report); @@ -245,6 +249,9 @@ private: SWGSSBDemodReport* ssb_demod_report; bool m_ssb_demod_report_isSet; + SWGRadioClockReport* radio_clock_report; + bool m_radio_clock_report_isSet; + SWGRemoteSourceReport* remote_source_report; bool m_remote_source_report_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp index 54175c4d9..1cc987963 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp @@ -98,6 +98,8 @@ SWGChannelSettings::SWGChannelSettings() { m_packet_demod_settings_isSet = false; packet_mod_settings = nullptr; m_packet_mod_settings_isSet = false; + radio_clock_settings = nullptr; + m_radio_clock_settings_isSet = false; remote_sink_settings = nullptr; m_remote_sink_settings_isSet = false; remote_source_settings = nullptr; @@ -198,6 +200,8 @@ SWGChannelSettings::init() { m_packet_demod_settings_isSet = false; packet_mod_settings = new SWGPacketModSettings(); m_packet_mod_settings_isSet = false; + radio_clock_settings = new SWGRadioClockSettings(); + m_radio_clock_settings_isSet = false; remote_sink_settings = new SWGRemoteSinkSettings(); m_remote_sink_settings_isSet = false; remote_source_settings = new SWGRemoteSourceSettings(); @@ -323,6 +327,9 @@ SWGChannelSettings::cleanup() { if(packet_mod_settings != nullptr) { delete packet_mod_settings; } + if(radio_clock_settings != nullptr) { + delete radio_clock_settings; + } if(remote_sink_settings != nullptr) { delete remote_sink_settings; } @@ -439,6 +446,8 @@ SWGChannelSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&packet_mod_settings, pJson["PacketModSettings"], "SWGPacketModSettings", "SWGPacketModSettings"); + ::SWGSDRangel::setValue(&radio_clock_settings, pJson["RadioClockSettings"], "SWGRadioClockSettings", "SWGRadioClockSettings"); + ::SWGSDRangel::setValue(&remote_sink_settings, pJson["RemoteSinkSettings"], "SWGRemoteSinkSettings", "SWGRemoteSinkSettings"); ::SWGSDRangel::setValue(&remote_source_settings, pJson["RemoteSourceSettings"], "SWGRemoteSourceSettings", "SWGRemoteSourceSettings"); @@ -582,6 +591,9 @@ SWGChannelSettings::asJsonObject() { if((packet_mod_settings != nullptr) && (packet_mod_settings->isSet())){ toJsonValue(QString("PacketModSettings"), packet_mod_settings, obj, QString("SWGPacketModSettings")); } + if((radio_clock_settings != nullptr) && (radio_clock_settings->isSet())){ + toJsonValue(QString("RadioClockSettings"), radio_clock_settings, obj, QString("SWGRadioClockSettings")); + } if((remote_sink_settings != nullptr) && (remote_sink_settings->isSet())){ toJsonValue(QString("RemoteSinkSettings"), remote_sink_settings, obj, QString("SWGRemoteSinkSettings")); } @@ -969,6 +981,16 @@ SWGChannelSettings::setPacketModSettings(SWGPacketModSettings* packet_mod_settin this->m_packet_mod_settings_isSet = true; } +SWGRadioClockSettings* +SWGChannelSettings::getRadioClockSettings() { + return radio_clock_settings; +} +void +SWGChannelSettings::setRadioClockSettings(SWGRadioClockSettings* radio_clock_settings) { + this->radio_clock_settings = radio_clock_settings; + this->m_radio_clock_settings_isSet = true; +} + SWGRemoteSinkSettings* SWGChannelSettings::getRemoteSinkSettings() { return remote_sink_settings; @@ -1189,6 +1211,9 @@ SWGChannelSettings::isSet(){ if(packet_mod_settings && packet_mod_settings->isSet()){ isObjectUpdated = true; break; } + if(radio_clock_settings && radio_clock_settings->isSet()){ + isObjectUpdated = true; break; + } if(remote_sink_settings && remote_sink_settings->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h index c5a22be7e..3d0438b73 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h @@ -53,6 +53,7 @@ #include "SWGNoiseFigureSettings.h" #include "SWGPacketDemodSettings.h" #include "SWGPacketModSettings.h" +#include "SWGRadioClockSettings.h" #include "SWGRemoteSinkSettings.h" #include "SWGRemoteSourceSettings.h" #include "SWGSSBDemodSettings.h" @@ -189,6 +190,9 @@ public: SWGPacketModSettings* getPacketModSettings(); void setPacketModSettings(SWGPacketModSettings* packet_mod_settings); + SWGRadioClockSettings* getRadioClockSettings(); + void setRadioClockSettings(SWGRadioClockSettings* radio_clock_settings); + SWGRemoteSinkSettings* getRemoteSinkSettings(); void setRemoteSinkSettings(SWGRemoteSinkSettings* remote_sink_settings); @@ -331,6 +335,9 @@ private: SWGPacketModSettings* packet_mod_settings; bool m_packet_mod_settings_isSet; + SWGRadioClockSettings* radio_clock_settings; + bool m_radio_clock_settings_isSet; + SWGRemoteSinkSettings* remote_sink_settings; bool m_remote_sink_settings_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h index 6a17cf2e8..fa36daafc 100644 --- a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h +++ b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h @@ -1,6 +1,6 @@ /** * SDRangel - * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- * * OpenAPI spec version: 6.0.0 * Contact: f4exb06@gmail.com @@ -201,6 +201,8 @@ #include "SWGPresets.h" #include "SWGRDSReport.h" #include "SWGRDSReport_altFrequencies.h" +#include "SWGRadioClockReport.h" +#include "SWGRadioClockSettings.h" #include "SWGRange.h" #include "SWGRangeFloat.h" #include "SWGRemoteInputReport.h" @@ -277,1296 +279,786 @@ namespace SWGSDRangel { inline void* create(QString type) { if(QString("SWGADSBDemodReport").compare(type) == 0) { - SWGADSBDemodReport *obj = new SWGADSBDemodReport(); - obj->init(); - return obj; + return new SWGADSBDemodReport(); } if(QString("SWGADSBDemodSettings").compare(type) == 0) { - SWGADSBDemodSettings *obj = new SWGADSBDemodSettings(); - obj->init(); - return obj; + return new SWGADSBDemodSettings(); } if(QString("SWGAFCActions").compare(type) == 0) { - SWGAFCActions *obj = new SWGAFCActions(); - obj->init(); - return obj; + return new SWGAFCActions(); } if(QString("SWGAFCReport").compare(type) == 0) { - SWGAFCReport *obj = new SWGAFCReport(); - obj->init(); - return obj; + return new SWGAFCReport(); } if(QString("SWGAFCSettings").compare(type) == 0) { - SWGAFCSettings *obj = new SWGAFCSettings(); - obj->init(); - return obj; + return new SWGAFCSettings(); } if(QString("SWGAISDemodReport").compare(type) == 0) { - SWGAISDemodReport *obj = new SWGAISDemodReport(); - obj->init(); - return obj; + return new SWGAISDemodReport(); } if(QString("SWGAISDemodSettings").compare(type) == 0) { - SWGAISDemodSettings *obj = new SWGAISDemodSettings(); - obj->init(); - return obj; + return new SWGAISDemodSettings(); } if(QString("SWGAISModActions").compare(type) == 0) { - SWGAISModActions *obj = new SWGAISModActions(); - obj->init(); - return obj; + return new SWGAISModActions(); } if(QString("SWGAISModActions_tx").compare(type) == 0) { - SWGAISModActions_tx *obj = new SWGAISModActions_tx(); - obj->init(); - return obj; + return new SWGAISModActions_tx(); } if(QString("SWGAISModReport").compare(type) == 0) { - SWGAISModReport *obj = new SWGAISModReport(); - obj->init(); - return obj; + return new SWGAISModReport(); } if(QString("SWGAISModSettings").compare(type) == 0) { - SWGAISModSettings *obj = new SWGAISModSettings(); - obj->init(); - return obj; + return new SWGAISModSettings(); } if(QString("SWGAISSettings").compare(type) == 0) { - SWGAISSettings *obj = new SWGAISSettings(); - obj->init(); - return obj; + return new SWGAISSettings(); } if(QString("SWGAMBEDevice").compare(type) == 0) { - SWGAMBEDevice *obj = new SWGAMBEDevice(); - obj->init(); - return obj; + return new SWGAMBEDevice(); } if(QString("SWGAMBEDevices").compare(type) == 0) { - SWGAMBEDevices *obj = new SWGAMBEDevices(); - obj->init(); - return obj; + return new SWGAMBEDevices(); } if(QString("SWGAMDemodReport").compare(type) == 0) { - SWGAMDemodReport *obj = new SWGAMDemodReport(); - obj->init(); - return obj; + return new SWGAMDemodReport(); } if(QString("SWGAMDemodSettings").compare(type) == 0) { - SWGAMDemodSettings *obj = new SWGAMDemodSettings(); - obj->init(); - return obj; + return new SWGAMDemodSettings(); } if(QString("SWGAMModReport").compare(type) == 0) { - SWGAMModReport *obj = new SWGAMModReport(); - obj->init(); - return obj; + return new SWGAMModReport(); } if(QString("SWGAMModSettings").compare(type) == 0) { - SWGAMModSettings *obj = new SWGAMModSettings(); - obj->init(); - return obj; + return new SWGAMModSettings(); } if(QString("SWGAPRSSettings").compare(type) == 0) { - SWGAPRSSettings *obj = new SWGAPRSSettings(); - obj->init(); - return obj; + return new SWGAPRSSettings(); } if(QString("SWGAPTDemodActions").compare(type) == 0) { - SWGAPTDemodActions *obj = new SWGAPTDemodActions(); - obj->init(); - return obj; + return new SWGAPTDemodActions(); } if(QString("SWGAPTDemodActions_aos").compare(type) == 0) { - SWGAPTDemodActions_aos *obj = new SWGAPTDemodActions_aos(); - obj->init(); - return obj; + return new SWGAPTDemodActions_aos(); } if(QString("SWGAPTDemodActions_los").compare(type) == 0) { - SWGAPTDemodActions_los *obj = new SWGAPTDemodActions_los(); - obj->init(); - return obj; + return new SWGAPTDemodActions_los(); } if(QString("SWGAPTDemodSettings").compare(type) == 0) { - SWGAPTDemodSettings *obj = new SWGAPTDemodSettings(); - obj->init(); - return obj; + return new SWGAPTDemodSettings(); } if(QString("SWGATVDemodSettings").compare(type) == 0) { - SWGATVDemodSettings *obj = new SWGATVDemodSettings(); - obj->init(); - return obj; + return new SWGATVDemodSettings(); } if(QString("SWGATVModReport").compare(type) == 0) { - SWGATVModReport *obj = new SWGATVModReport(); - obj->init(); - return obj; + return new SWGATVModReport(); } if(QString("SWGATVModSettings").compare(type) == 0) { - SWGATVModSettings *obj = new SWGATVModSettings(); - obj->init(); - return obj; + return new SWGATVModSettings(); } if(QString("SWGAirspyHFReport").compare(type) == 0) { - SWGAirspyHFReport *obj = new SWGAirspyHFReport(); - obj->init(); - return obj; + return new SWGAirspyHFReport(); } if(QString("SWGAirspyHFSettings").compare(type) == 0) { - SWGAirspyHFSettings *obj = new SWGAirspyHFSettings(); - obj->init(); - return obj; + return new SWGAirspyHFSettings(); } if(QString("SWGAirspyReport").compare(type) == 0) { - SWGAirspyReport *obj = new SWGAirspyReport(); - obj->init(); - return obj; + return new SWGAirspyReport(); } if(QString("SWGAirspySettings").compare(type) == 0) { - SWGAirspySettings *obj = new SWGAirspySettings(); - obj->init(); - return obj; + return new SWGAirspySettings(); } if(QString("SWGAntennaToolsSettings").compare(type) == 0) { - SWGAntennaToolsSettings *obj = new SWGAntennaToolsSettings(); - obj->init(); - return obj; + return new SWGAntennaToolsSettings(); } if(QString("SWGArgInfo").compare(type) == 0) { - SWGArgInfo *obj = new SWGArgInfo(); - obj->init(); - return obj; + return new SWGArgInfo(); } if(QString("SWGArgValue").compare(type) == 0) { - SWGArgValue *obj = new SWGArgValue(); - obj->init(); - return obj; + return new SWGArgValue(); } if(QString("SWGAudioDevices").compare(type) == 0) { - SWGAudioDevices *obj = new SWGAudioDevices(); - obj->init(); - return obj; + return new SWGAudioDevices(); } if(QString("SWGAudioInputDevice").compare(type) == 0) { - SWGAudioInputDevice *obj = new SWGAudioInputDevice(); - obj->init(); - return obj; + return new SWGAudioInputDevice(); } if(QString("SWGAudioInputSettings").compare(type) == 0) { - SWGAudioInputSettings *obj = new SWGAudioInputSettings(); - obj->init(); - return obj; + return new SWGAudioInputSettings(); } if(QString("SWGAudioOutputDevice").compare(type) == 0) { - SWGAudioOutputDevice *obj = new SWGAudioOutputDevice(); - obj->init(); - return obj; + return new SWGAudioOutputDevice(); } if(QString("SWGAudioOutputSettings").compare(type) == 0) { - SWGAudioOutputSettings *obj = new SWGAudioOutputSettings(); - obj->init(); - return obj; + return new SWGAudioOutputSettings(); } if(QString("SWGBFMDemodReport").compare(type) == 0) { - SWGBFMDemodReport *obj = new SWGBFMDemodReport(); - obj->init(); - return obj; + return new SWGBFMDemodReport(); } if(QString("SWGBFMDemodSettings").compare(type) == 0) { - SWGBFMDemodSettings *obj = new SWGBFMDemodSettings(); - obj->init(); - return obj; + return new SWGBFMDemodSettings(); } if(QString("SWGBandwidth").compare(type) == 0) { - SWGBandwidth *obj = new SWGBandwidth(); - obj->init(); - return obj; + return new SWGBandwidth(); } if(QString("SWGBeamSteeringCWModSettings").compare(type) == 0) { - SWGBeamSteeringCWModSettings *obj = new SWGBeamSteeringCWModSettings(); - obj->init(); - return obj; + return new SWGBeamSteeringCWModSettings(); } if(QString("SWGBladeRF1InputSettings").compare(type) == 0) { - SWGBladeRF1InputSettings *obj = new SWGBladeRF1InputSettings(); - obj->init(); - return obj; + return new SWGBladeRF1InputSettings(); } if(QString("SWGBladeRF1OutputSettings").compare(type) == 0) { - SWGBladeRF1OutputSettings *obj = new SWGBladeRF1OutputSettings(); - obj->init(); - return obj; + return new SWGBladeRF1OutputSettings(); } if(QString("SWGBladeRF2InputReport").compare(type) == 0) { - SWGBladeRF2InputReport *obj = new SWGBladeRF2InputReport(); - obj->init(); - return obj; + return new SWGBladeRF2InputReport(); } if(QString("SWGBladeRF2InputSettings").compare(type) == 0) { - SWGBladeRF2InputSettings *obj = new SWGBladeRF2InputSettings(); - obj->init(); - return obj; + return new SWGBladeRF2InputSettings(); } if(QString("SWGBladeRF2MIMOReport").compare(type) == 0) { - SWGBladeRF2MIMOReport *obj = new SWGBladeRF2MIMOReport(); - obj->init(); - return obj; + return new SWGBladeRF2MIMOReport(); } if(QString("SWGBladeRF2MIMOSettings").compare(type) == 0) { - SWGBladeRF2MIMOSettings *obj = new SWGBladeRF2MIMOSettings(); - obj->init(); - return obj; + return new SWGBladeRF2MIMOSettings(); } if(QString("SWGBladeRF2OutputReport").compare(type) == 0) { - SWGBladeRF2OutputReport *obj = new SWGBladeRF2OutputReport(); - obj->init(); - return obj; + return new SWGBladeRF2OutputReport(); } if(QString("SWGBladeRF2OutputSettings").compare(type) == 0) { - SWGBladeRF2OutputSettings *obj = new SWGBladeRF2OutputSettings(); - obj->init(); - return obj; + return new SWGBladeRF2OutputSettings(); } if(QString("SWGCWKeyerSettings").compare(type) == 0) { - SWGCWKeyerSettings *obj = new SWGCWKeyerSettings(); - obj->init(); - return obj; + return new SWGCWKeyerSettings(); } if(QString("SWGCapture").compare(type) == 0) { - SWGCapture *obj = new SWGCapture(); - obj->init(); - return obj; + return new SWGCapture(); } if(QString("SWGChannel").compare(type) == 0) { - SWGChannel *obj = new SWGChannel(); - obj->init(); - return obj; + return new SWGChannel(); } if(QString("SWGChannelActions").compare(type) == 0) { - SWGChannelActions *obj = new SWGChannelActions(); - obj->init(); - return obj; + return new SWGChannelActions(); } if(QString("SWGChannelAnalyzerSettings").compare(type) == 0) { - SWGChannelAnalyzerSettings *obj = new SWGChannelAnalyzerSettings(); - obj->init(); - return obj; + return new SWGChannelAnalyzerSettings(); } if(QString("SWGChannelConfig").compare(type) == 0) { - SWGChannelConfig *obj = new SWGChannelConfig(); - obj->init(); - return obj; + return new SWGChannelConfig(); } if(QString("SWGChannelListItem").compare(type) == 0) { - SWGChannelListItem *obj = new SWGChannelListItem(); - obj->init(); - return obj; + return new SWGChannelListItem(); } if(QString("SWGChannelReport").compare(type) == 0) { - SWGChannelReport *obj = new SWGChannelReport(); - obj->init(); - return obj; + return new SWGChannelReport(); } if(QString("SWGChannelSettings").compare(type) == 0) { - SWGChannelSettings *obj = new SWGChannelSettings(); - obj->init(); - return obj; + return new SWGChannelSettings(); } if(QString("SWGChannelsDetail").compare(type) == 0) { - SWGChannelsDetail *obj = new SWGChannelsDetail(); - obj->init(); - return obj; + return new SWGChannelsDetail(); } if(QString("SWGChirpChatDemodReport").compare(type) == 0) { - SWGChirpChatDemodReport *obj = new SWGChirpChatDemodReport(); - obj->init(); - return obj; + return new SWGChirpChatDemodReport(); } if(QString("SWGChirpChatDemodSettings").compare(type) == 0) { - SWGChirpChatDemodSettings *obj = new SWGChirpChatDemodSettings(); - obj->init(); - return obj; + return new SWGChirpChatDemodSettings(); } if(QString("SWGChirpChatModReport").compare(type) == 0) { - SWGChirpChatModReport *obj = new SWGChirpChatModReport(); - obj->init(); - return obj; + return new SWGChirpChatModReport(); } if(QString("SWGChirpChatModSettings").compare(type) == 0) { - SWGChirpChatModSettings *obj = new SWGChirpChatModSettings(); - obj->init(); - return obj; + return new SWGChirpChatModSettings(); } if(QString("SWGCommand").compare(type) == 0) { - SWGCommand *obj = new SWGCommand(); - obj->init(); - return obj; + return new SWGCommand(); } if(QString("SWGComplex").compare(type) == 0) { - SWGComplex *obj = new SWGComplex(); - obj->init(); - return obj; + return new SWGComplex(); } if(QString("SWGDABDemodSettings").compare(type) == 0) { - SWGDABDemodSettings *obj = new SWGDABDemodSettings(); - obj->init(); - return obj; + return new SWGDABDemodSettings(); } if(QString("SWGDATVDemodSettings").compare(type) == 0) { - SWGDATVDemodSettings *obj = new SWGDATVDemodSettings(); - obj->init(); - return obj; + return new SWGDATVDemodSettings(); } if(QString("SWGDATVModReport").compare(type) == 0) { - SWGDATVModReport *obj = new SWGDATVModReport(); - obj->init(); - return obj; + return new SWGDATVModReport(); } if(QString("SWGDATVModSettings").compare(type) == 0) { - SWGDATVModSettings *obj = new SWGDATVModSettings(); - obj->init(); - return obj; + return new SWGDATVModSettings(); } if(QString("SWGDSDDemodReport").compare(type) == 0) { - SWGDSDDemodReport *obj = new SWGDSDDemodReport(); - obj->init(); - return obj; + return new SWGDSDDemodReport(); } if(QString("SWGDSDDemodSettings").compare(type) == 0) { - SWGDSDDemodSettings *obj = new SWGDSDDemodSettings(); - obj->init(); - return obj; + return new SWGDSDDemodSettings(); } if(QString("SWGDVSerialDevice").compare(type) == 0) { - SWGDVSerialDevice *obj = new SWGDVSerialDevice(); - obj->init(); - return obj; + return new SWGDVSerialDevice(); } if(QString("SWGDVSerialDevices").compare(type) == 0) { - SWGDVSerialDevices *obj = new SWGDVSerialDevices(); - obj->init(); - return obj; + return new SWGDVSerialDevices(); } if(QString("SWGDemodAnalyzerSettings").compare(type) == 0) { - SWGDemodAnalyzerSettings *obj = new SWGDemodAnalyzerSettings(); - obj->init(); - return obj; + return new SWGDemodAnalyzerSettings(); } if(QString("SWGDeviceActions").compare(type) == 0) { - SWGDeviceActions *obj = new SWGDeviceActions(); - obj->init(); - return obj; + return new SWGDeviceActions(); } if(QString("SWGDeviceConfig").compare(type) == 0) { - SWGDeviceConfig *obj = new SWGDeviceConfig(); - obj->init(); - return obj; + return new SWGDeviceConfig(); } if(QString("SWGDeviceListItem").compare(type) == 0) { - SWGDeviceListItem *obj = new SWGDeviceListItem(); - obj->init(); - return obj; + return new SWGDeviceListItem(); } if(QString("SWGDeviceReport").compare(type) == 0) { - SWGDeviceReport *obj = new SWGDeviceReport(); - obj->init(); - return obj; + return new SWGDeviceReport(); } if(QString("SWGDeviceSet").compare(type) == 0) { - SWGDeviceSet *obj = new SWGDeviceSet(); - obj->init(); - return obj; + return new SWGDeviceSet(); } if(QString("SWGDeviceSetList").compare(type) == 0) { - SWGDeviceSetList *obj = new SWGDeviceSetList(); - obj->init(); - return obj; + return new SWGDeviceSetList(); } if(QString("SWGDeviceSettings").compare(type) == 0) { - SWGDeviceSettings *obj = new SWGDeviceSettings(); - obj->init(); - return obj; + return new SWGDeviceSettings(); } if(QString("SWGDeviceState").compare(type) == 0) { - SWGDeviceState *obj = new SWGDeviceState(); - obj->init(); - return obj; + return new SWGDeviceState(); } if(QString("SWGErrorResponse").compare(type) == 0) { - SWGErrorResponse *obj = new SWGErrorResponse(); - obj->init(); - return obj; + return new SWGErrorResponse(); } if(QString("SWGFCDProPlusSettings").compare(type) == 0) { - SWGFCDProPlusSettings *obj = new SWGFCDProPlusSettings(); - obj->init(); - return obj; + return new SWGFCDProPlusSettings(); } if(QString("SWGFCDProSettings").compare(type) == 0) { - SWGFCDProSettings *obj = new SWGFCDProSettings(); - obj->init(); - return obj; + return new SWGFCDProSettings(); } if(QString("SWGFeature").compare(type) == 0) { - SWGFeature *obj = new SWGFeature(); - obj->init(); - return obj; + return new SWGFeature(); } if(QString("SWGFeatureActions").compare(type) == 0) { - SWGFeatureActions *obj = new SWGFeatureActions(); - obj->init(); - return obj; + return new SWGFeatureActions(); } if(QString("SWGFeatureConfig").compare(type) == 0) { - SWGFeatureConfig *obj = new SWGFeatureConfig(); - obj->init(); - return obj; + return new SWGFeatureConfig(); } if(QString("SWGFeatureReport").compare(type) == 0) { - SWGFeatureReport *obj = new SWGFeatureReport(); - obj->init(); - return obj; + return new SWGFeatureReport(); } if(QString("SWGFeatureSet").compare(type) == 0) { - SWGFeatureSet *obj = new SWGFeatureSet(); - obj->init(); - return obj; + return new SWGFeatureSet(); } if(QString("SWGFeatureSetList").compare(type) == 0) { - SWGFeatureSetList *obj = new SWGFeatureSetList(); - obj->init(); - return obj; + return new SWGFeatureSetList(); } if(QString("SWGFeatureSetPreset").compare(type) == 0) { - SWGFeatureSetPreset *obj = new SWGFeatureSetPreset(); - obj->init(); - return obj; + return new SWGFeatureSetPreset(); } if(QString("SWGFeatureSettings").compare(type) == 0) { - SWGFeatureSettings *obj = new SWGFeatureSettings(); - obj->init(); - return obj; + return new SWGFeatureSettings(); } if(QString("SWGFileInputReport").compare(type) == 0) { - SWGFileInputReport *obj = new SWGFileInputReport(); - obj->init(); - return obj; + return new SWGFileInputReport(); } if(QString("SWGFileInputSettings").compare(type) == 0) { - SWGFileInputSettings *obj = new SWGFileInputSettings(); - obj->init(); - return obj; + return new SWGFileInputSettings(); } if(QString("SWGFileOutputSettings").compare(type) == 0) { - SWGFileOutputSettings *obj = new SWGFileOutputSettings(); - obj->init(); - return obj; + return new SWGFileOutputSettings(); } if(QString("SWGFileSinkActions").compare(type) == 0) { - SWGFileSinkActions *obj = new SWGFileSinkActions(); - obj->init(); - return obj; + return new SWGFileSinkActions(); } if(QString("SWGFileSinkReport").compare(type) == 0) { - SWGFileSinkReport *obj = new SWGFileSinkReport(); - obj->init(); - return obj; + return new SWGFileSinkReport(); } if(QString("SWGFileSinkSettings").compare(type) == 0) { - SWGFileSinkSettings *obj = new SWGFileSinkSettings(); - obj->init(); - return obj; + return new SWGFileSinkSettings(); } if(QString("SWGFileSourceActions").compare(type) == 0) { - SWGFileSourceActions *obj = new SWGFileSourceActions(); - obj->init(); - return obj; + return new SWGFileSourceActions(); } if(QString("SWGFileSourceReport").compare(type) == 0) { - SWGFileSourceReport *obj = new SWGFileSourceReport(); - obj->init(); - return obj; + return new SWGFileSourceReport(); } if(QString("SWGFileSourceSettings").compare(type) == 0) { - SWGFileSourceSettings *obj = new SWGFileSourceSettings(); - obj->init(); - return obj; + return new SWGFileSourceSettings(); } if(QString("SWGFreeDVDemodReport").compare(type) == 0) { - SWGFreeDVDemodReport *obj = new SWGFreeDVDemodReport(); - obj->init(); - return obj; + return new SWGFreeDVDemodReport(); } if(QString("SWGFreeDVDemodSettings").compare(type) == 0) { - SWGFreeDVDemodSettings *obj = new SWGFreeDVDemodSettings(); - obj->init(); - return obj; + return new SWGFreeDVDemodSettings(); } if(QString("SWGFreeDVModReport").compare(type) == 0) { - SWGFreeDVModReport *obj = new SWGFreeDVModReport(); - obj->init(); - return obj; + return new SWGFreeDVModReport(); } if(QString("SWGFreeDVModSettings").compare(type) == 0) { - SWGFreeDVModSettings *obj = new SWGFreeDVModSettings(); - obj->init(); - return obj; + return new SWGFreeDVModSettings(); } if(QString("SWGFreqTrackerReport").compare(type) == 0) { - SWGFreqTrackerReport *obj = new SWGFreqTrackerReport(); - obj->init(); - return obj; + return new SWGFreqTrackerReport(); } if(QString("SWGFreqTrackerSettings").compare(type) == 0) { - SWGFreqTrackerSettings *obj = new SWGFreqTrackerSettings(); - obj->init(); - return obj; + return new SWGFreqTrackerSettings(); } if(QString("SWGFrequency").compare(type) == 0) { - SWGFrequency *obj = new SWGFrequency(); - obj->init(); - return obj; + return new SWGFrequency(); } if(QString("SWGFrequencyBand").compare(type) == 0) { - SWGFrequencyBand *obj = new SWGFrequencyBand(); - obj->init(); - return obj; + return new SWGFrequencyBand(); } if(QString("SWGFrequencyRange").compare(type) == 0) { - SWGFrequencyRange *obj = new SWGFrequencyRange(); - obj->init(); - return obj; + return new SWGFrequencyRange(); } if(QString("SWGGLScope").compare(type) == 0) { - SWGGLScope *obj = new SWGGLScope(); - obj->init(); - return obj; + return new SWGGLScope(); } if(QString("SWGGLSpectrum").compare(type) == 0) { - SWGGLSpectrum *obj = new SWGGLSpectrum(); - obj->init(); - return obj; + return new SWGGLSpectrum(); } if(QString("SWGGS232ControllerSettings").compare(type) == 0) { - SWGGS232ControllerSettings *obj = new SWGGS232ControllerSettings(); - obj->init(); - return obj; + return new SWGGS232ControllerSettings(); } if(QString("SWGGain").compare(type) == 0) { - SWGGain *obj = new SWGGain(); - obj->init(); - return obj; + return new SWGGain(); } if(QString("SWGHackRFInputSettings").compare(type) == 0) { - SWGHackRFInputSettings *obj = new SWGHackRFInputSettings(); - obj->init(); - return obj; + return new SWGHackRFInputSettings(); } if(QString("SWGHackRFOutputSettings").compare(type) == 0) { - SWGHackRFOutputSettings *obj = new SWGHackRFOutputSettings(); - obj->init(); - return obj; + return new SWGHackRFOutputSettings(); } if(QString("SWGIEEE_802_15_4_ModActions").compare(type) == 0) { - SWGIEEE_802_15_4_ModActions *obj = new SWGIEEE_802_15_4_ModActions(); - obj->init(); - return obj; + return new SWGIEEE_802_15_4_ModActions(); } if(QString("SWGIEEE_802_15_4_ModActions_tx").compare(type) == 0) { - SWGIEEE_802_15_4_ModActions_tx *obj = new SWGIEEE_802_15_4_ModActions_tx(); - obj->init(); - return obj; + return new SWGIEEE_802_15_4_ModActions_tx(); } if(QString("SWGIEEE_802_15_4_ModReport").compare(type) == 0) { - SWGIEEE_802_15_4_ModReport *obj = new SWGIEEE_802_15_4_ModReport(); - obj->init(); - return obj; + return new SWGIEEE_802_15_4_ModReport(); } if(QString("SWGIEEE_802_15_4_ModSettings").compare(type) == 0) { - SWGIEEE_802_15_4_ModSettings *obj = new SWGIEEE_802_15_4_ModSettings(); - obj->init(); - return obj; + return new SWGIEEE_802_15_4_ModSettings(); } if(QString("SWGInstanceChannelsResponse").compare(type) == 0) { - SWGInstanceChannelsResponse *obj = new SWGInstanceChannelsResponse(); - obj->init(); - return obj; + return new SWGInstanceChannelsResponse(); } if(QString("SWGInstanceConfigResponse").compare(type) == 0) { - SWGInstanceConfigResponse *obj = new SWGInstanceConfigResponse(); - obj->init(); - return obj; + return new SWGInstanceConfigResponse(); } if(QString("SWGInstanceDevicesResponse").compare(type) == 0) { - SWGInstanceDevicesResponse *obj = new SWGInstanceDevicesResponse(); - obj->init(); - return obj; + return new SWGInstanceDevicesResponse(); } if(QString("SWGInstanceSummaryResponse").compare(type) == 0) { - SWGInstanceSummaryResponse *obj = new SWGInstanceSummaryResponse(); - obj->init(); - return obj; + return new SWGInstanceSummaryResponse(); } if(QString("SWGInterferometerSettings").compare(type) == 0) { - SWGInterferometerSettings *obj = new SWGInterferometerSettings(); - obj->init(); - return obj; + return new SWGInterferometerSettings(); } if(QString("SWGKiwiSDRReport").compare(type) == 0) { - SWGKiwiSDRReport *obj = new SWGKiwiSDRReport(); - obj->init(); - return obj; + return new SWGKiwiSDRReport(); } if(QString("SWGKiwiSDRSettings").compare(type) == 0) { - SWGKiwiSDRSettings *obj = new SWGKiwiSDRSettings(); - obj->init(); - return obj; + return new SWGKiwiSDRSettings(); } if(QString("SWGLimeRFEDevice").compare(type) == 0) { - SWGLimeRFEDevice *obj = new SWGLimeRFEDevice(); - obj->init(); - return obj; + return new SWGLimeRFEDevice(); } if(QString("SWGLimeRFEDevices").compare(type) == 0) { - SWGLimeRFEDevices *obj = new SWGLimeRFEDevices(); - obj->init(); - return obj; + return new SWGLimeRFEDevices(); } if(QString("SWGLimeRFEPower").compare(type) == 0) { - SWGLimeRFEPower *obj = new SWGLimeRFEPower(); - obj->init(); - return obj; + return new SWGLimeRFEPower(); } if(QString("SWGLimeRFESettings").compare(type) == 0) { - SWGLimeRFESettings *obj = new SWGLimeRFESettings(); - obj->init(); - return obj; + return new SWGLimeRFESettings(); } if(QString("SWGLimeSdrInputReport").compare(type) == 0) { - SWGLimeSdrInputReport *obj = new SWGLimeSdrInputReport(); - obj->init(); - return obj; + return new SWGLimeSdrInputReport(); } if(QString("SWGLimeSdrInputSettings").compare(type) == 0) { - SWGLimeSdrInputSettings *obj = new SWGLimeSdrInputSettings(); - obj->init(); - return obj; + return new SWGLimeSdrInputSettings(); } if(QString("SWGLimeSdrMIMOReport").compare(type) == 0) { - SWGLimeSdrMIMOReport *obj = new SWGLimeSdrMIMOReport(); - obj->init(); - return obj; + return new SWGLimeSdrMIMOReport(); } if(QString("SWGLimeSdrMIMOSettings").compare(type) == 0) { - SWGLimeSdrMIMOSettings *obj = new SWGLimeSdrMIMOSettings(); - obj->init(); - return obj; + return new SWGLimeSdrMIMOSettings(); } if(QString("SWGLimeSdrOutputReport").compare(type) == 0) { - SWGLimeSdrOutputReport *obj = new SWGLimeSdrOutputReport(); - obj->init(); - return obj; + return new SWGLimeSdrOutputReport(); } if(QString("SWGLimeSdrOutputSettings").compare(type) == 0) { - SWGLimeSdrOutputSettings *obj = new SWGLimeSdrOutputSettings(); - obj->init(); - return obj; + return new SWGLimeSdrOutputSettings(); } if(QString("SWGLocalInputReport").compare(type) == 0) { - SWGLocalInputReport *obj = new SWGLocalInputReport(); - obj->init(); - return obj; + return new SWGLocalInputReport(); } if(QString("SWGLocalInputSettings").compare(type) == 0) { - SWGLocalInputSettings *obj = new SWGLocalInputSettings(); - obj->init(); - return obj; + return new SWGLocalInputSettings(); } if(QString("SWGLocalOutputReport").compare(type) == 0) { - SWGLocalOutputReport *obj = new SWGLocalOutputReport(); - obj->init(); - return obj; + return new SWGLocalOutputReport(); } if(QString("SWGLocalOutputSettings").compare(type) == 0) { - SWGLocalOutputSettings *obj = new SWGLocalOutputSettings(); - obj->init(); - return obj; + return new SWGLocalOutputSettings(); } if(QString("SWGLocalSinkSettings").compare(type) == 0) { - SWGLocalSinkSettings *obj = new SWGLocalSinkSettings(); - obj->init(); - return obj; + return new SWGLocalSinkSettings(); } if(QString("SWGLocalSourceSettings").compare(type) == 0) { - SWGLocalSourceSettings *obj = new SWGLocalSourceSettings(); - obj->init(); - return obj; + return new SWGLocalSourceSettings(); } if(QString("SWGLocationInformation").compare(type) == 0) { - SWGLocationInformation *obj = new SWGLocationInformation(); - obj->init(); - return obj; + return new SWGLocationInformation(); } if(QString("SWGLoggingInfo").compare(type) == 0) { - SWGLoggingInfo *obj = new SWGLoggingInfo(); - obj->init(); - return obj; + return new SWGLoggingInfo(); } if(QString("SWGMapActions").compare(type) == 0) { - SWGMapActions *obj = new SWGMapActions(); - obj->init(); - return obj; + return new SWGMapActions(); } if(QString("SWGMapCoordinate").compare(type) == 0) { - SWGMapCoordinate *obj = new SWGMapCoordinate(); - obj->init(); - return obj; + return new SWGMapCoordinate(); } if(QString("SWGMapItem").compare(type) == 0) { - SWGMapItem *obj = new SWGMapItem(); - obj->init(); - return obj; + return new SWGMapItem(); } if(QString("SWGMapItem_2").compare(type) == 0) { - SWGMapItem_2 *obj = new SWGMapItem_2(); - obj->init(); - return obj; + return new SWGMapItem_2(); } if(QString("SWGMapSettings").compare(type) == 0) { - SWGMapSettings *obj = new SWGMapSettings(); - obj->init(); - return obj; + return new SWGMapSettings(); } if(QString("SWGMetisMISOSettings").compare(type) == 0) { - SWGMetisMISOSettings *obj = new SWGMetisMISOSettings(); - obj->init(); - return obj; + return new SWGMetisMISOSettings(); } if(QString("SWGNFMDemodReport").compare(type) == 0) { - SWGNFMDemodReport *obj = new SWGNFMDemodReport(); - obj->init(); - return obj; + return new SWGNFMDemodReport(); } if(QString("SWGNFMDemodSettings").compare(type) == 0) { - SWGNFMDemodSettings *obj = new SWGNFMDemodSettings(); - obj->init(); - return obj; + return new SWGNFMDemodSettings(); } if(QString("SWGNFMModReport").compare(type) == 0) { - SWGNFMModReport *obj = new SWGNFMModReport(); - obj->init(); - return obj; + return new SWGNFMModReport(); } if(QString("SWGNFMModSettings").compare(type) == 0) { - SWGNFMModSettings *obj = new SWGNFMModSettings(); - obj->init(); - return obj; + return new SWGNFMModSettings(); } if(QString("SWGNamedEnum").compare(type) == 0) { - SWGNamedEnum *obj = new SWGNamedEnum(); - obj->init(); - return obj; + return new SWGNamedEnum(); } if(QString("SWGNoiseFigureReport").compare(type) == 0) { - SWGNoiseFigureReport *obj = new SWGNoiseFigureReport(); - obj->init(); - return obj; + return new SWGNoiseFigureReport(); } if(QString("SWGNoiseFigureSettings").compare(type) == 0) { - SWGNoiseFigureSettings *obj = new SWGNoiseFigureSettings(); - obj->init(); - return obj; + return new SWGNoiseFigureSettings(); } if(QString("SWGPERTesterActions").compare(type) == 0) { - SWGPERTesterActions *obj = new SWGPERTesterActions(); - obj->init(); - return obj; + return new SWGPERTesterActions(); } if(QString("SWGPERTesterActions_aos").compare(type) == 0) { - SWGPERTesterActions_aos *obj = new SWGPERTesterActions_aos(); - obj->init(); - return obj; + return new SWGPERTesterActions_aos(); } if(QString("SWGPERTesterSettings").compare(type) == 0) { - SWGPERTesterSettings *obj = new SWGPERTesterSettings(); - obj->init(); - return obj; + return new SWGPERTesterSettings(); } if(QString("SWGPacketDemodSettings").compare(type) == 0) { - SWGPacketDemodSettings *obj = new SWGPacketDemodSettings(); - obj->init(); - return obj; + return new SWGPacketDemodSettings(); } if(QString("SWGPacketModActions").compare(type) == 0) { - SWGPacketModActions *obj = new SWGPacketModActions(); - obj->init(); - return obj; + return new SWGPacketModActions(); } if(QString("SWGPacketModActions_tx").compare(type) == 0) { - SWGPacketModActions_tx *obj = new SWGPacketModActions_tx(); - obj->init(); - return obj; + return new SWGPacketModActions_tx(); } if(QString("SWGPacketModReport").compare(type) == 0) { - SWGPacketModReport *obj = new SWGPacketModReport(); - obj->init(); - return obj; + return new SWGPacketModReport(); } if(QString("SWGPacketModSettings").compare(type) == 0) { - SWGPacketModSettings *obj = new SWGPacketModSettings(); - obj->init(); - return obj; + return new SWGPacketModSettings(); } if(QString("SWGPerseusReport").compare(type) == 0) { - SWGPerseusReport *obj = new SWGPerseusReport(); - obj->init(); - return obj; + return new SWGPerseusReport(); } if(QString("SWGPerseusSettings").compare(type) == 0) { - SWGPerseusSettings *obj = new SWGPerseusSettings(); - obj->init(); - return obj; + return new SWGPerseusSettings(); } if(QString("SWGPlutoSdrInputReport").compare(type) == 0) { - SWGPlutoSdrInputReport *obj = new SWGPlutoSdrInputReport(); - obj->init(); - return obj; + return new SWGPlutoSdrInputReport(); } if(QString("SWGPlutoSdrInputSettings").compare(type) == 0) { - SWGPlutoSdrInputSettings *obj = new SWGPlutoSdrInputSettings(); - obj->init(); - return obj; + return new SWGPlutoSdrInputSettings(); } if(QString("SWGPlutoSdrMIMOReport").compare(type) == 0) { - SWGPlutoSdrMIMOReport *obj = new SWGPlutoSdrMIMOReport(); - obj->init(); - return obj; + return new SWGPlutoSdrMIMOReport(); } if(QString("SWGPlutoSdrMIMOSettings").compare(type) == 0) { - SWGPlutoSdrMIMOSettings *obj = new SWGPlutoSdrMIMOSettings(); - obj->init(); - return obj; + return new SWGPlutoSdrMIMOSettings(); } if(QString("SWGPlutoSdrOutputReport").compare(type) == 0) { - SWGPlutoSdrOutputReport *obj = new SWGPlutoSdrOutputReport(); - obj->init(); - return obj; + return new SWGPlutoSdrOutputReport(); } if(QString("SWGPlutoSdrOutputSettings").compare(type) == 0) { - SWGPlutoSdrOutputSettings *obj = new SWGPlutoSdrOutputSettings(); - obj->init(); - return obj; + return new SWGPlutoSdrOutputSettings(); } if(QString("SWGPreferences").compare(type) == 0) { - SWGPreferences *obj = new SWGPreferences(); - obj->init(); - return obj; + return new SWGPreferences(); } if(QString("SWGPreset").compare(type) == 0) { - SWGPreset *obj = new SWGPreset(); - obj->init(); - return obj; + return new SWGPreset(); } if(QString("SWGPresetExport").compare(type) == 0) { - SWGPresetExport *obj = new SWGPresetExport(); - obj->init(); - return obj; + return new SWGPresetExport(); } if(QString("SWGPresetGroup").compare(type) == 0) { - SWGPresetGroup *obj = new SWGPresetGroup(); - obj->init(); - return obj; + return new SWGPresetGroup(); } if(QString("SWGPresetIdentifier").compare(type) == 0) { - SWGPresetIdentifier *obj = new SWGPresetIdentifier(); - obj->init(); - return obj; + return new SWGPresetIdentifier(); } if(QString("SWGPresetImport").compare(type) == 0) { - SWGPresetImport *obj = new SWGPresetImport(); - obj->init(); - return obj; + return new SWGPresetImport(); } if(QString("SWGPresetItem").compare(type) == 0) { - SWGPresetItem *obj = new SWGPresetItem(); - obj->init(); - return obj; + return new SWGPresetItem(); } if(QString("SWGPresetTransfer").compare(type) == 0) { - SWGPresetTransfer *obj = new SWGPresetTransfer(); - obj->init(); - return obj; + return new SWGPresetTransfer(); } if(QString("SWGPresets").compare(type) == 0) { - SWGPresets *obj = new SWGPresets(); - obj->init(); - return obj; + return new SWGPresets(); } if(QString("SWGRDSReport").compare(type) == 0) { - SWGRDSReport *obj = new SWGRDSReport(); - obj->init(); - return obj; + return new SWGRDSReport(); } if(QString("SWGRDSReport_altFrequencies").compare(type) == 0) { - SWGRDSReport_altFrequencies *obj = new SWGRDSReport_altFrequencies(); - obj->init(); - return obj; + return new SWGRDSReport_altFrequencies(); + } + if(QString("SWGRadioClockReport").compare(type) == 0) { + return new SWGRadioClockReport(); + } + if(QString("SWGRadioClockSettings").compare(type) == 0) { + return new SWGRadioClockSettings(); } if(QString("SWGRange").compare(type) == 0) { - SWGRange *obj = new SWGRange(); - obj->init(); - return obj; + return new SWGRange(); } if(QString("SWGRangeFloat").compare(type) == 0) { - SWGRangeFloat *obj = new SWGRangeFloat(); - obj->init(); - return obj; + return new SWGRangeFloat(); } if(QString("SWGRemoteInputReport").compare(type) == 0) { - SWGRemoteInputReport *obj = new SWGRemoteInputReport(); - obj->init(); - return obj; + return new SWGRemoteInputReport(); } if(QString("SWGRemoteInputSettings").compare(type) == 0) { - SWGRemoteInputSettings *obj = new SWGRemoteInputSettings(); - obj->init(); - return obj; + return new SWGRemoteInputSettings(); } if(QString("SWGRemoteOutputReport").compare(type) == 0) { - SWGRemoteOutputReport *obj = new SWGRemoteOutputReport(); - obj->init(); - return obj; + return new SWGRemoteOutputReport(); } if(QString("SWGRemoteOutputSettings").compare(type) == 0) { - SWGRemoteOutputSettings *obj = new SWGRemoteOutputSettings(); - obj->init(); - return obj; + return new SWGRemoteOutputSettings(); } if(QString("SWGRemoteSinkSettings").compare(type) == 0) { - SWGRemoteSinkSettings *obj = new SWGRemoteSinkSettings(); - obj->init(); - return obj; + return new SWGRemoteSinkSettings(); } if(QString("SWGRemoteSourceReport").compare(type) == 0) { - SWGRemoteSourceReport *obj = new SWGRemoteSourceReport(); - obj->init(); - return obj; + return new SWGRemoteSourceReport(); } if(QString("SWGRemoteSourceSettings").compare(type) == 0) { - SWGRemoteSourceSettings *obj = new SWGRemoteSourceSettings(); - obj->init(); - return obj; + return new SWGRemoteSourceSettings(); } if(QString("SWGRigCtlServerSettings").compare(type) == 0) { - SWGRigCtlServerSettings *obj = new SWGRigCtlServerSettings(); - obj->init(); - return obj; + return new SWGRigCtlServerSettings(); } if(QString("SWGRtlSdrReport").compare(type) == 0) { - SWGRtlSdrReport *obj = new SWGRtlSdrReport(); - obj->init(); - return obj; + return new SWGRtlSdrReport(); } if(QString("SWGRtlSdrSettings").compare(type) == 0) { - SWGRtlSdrSettings *obj = new SWGRtlSdrSettings(); - obj->init(); - return obj; + return new SWGRtlSdrSettings(); } if(QString("SWGSDRPlayReport").compare(type) == 0) { - SWGSDRPlayReport *obj = new SWGSDRPlayReport(); - obj->init(); - return obj; + return new SWGSDRPlayReport(); } if(QString("SWGSDRPlaySettings").compare(type) == 0) { - SWGSDRPlaySettings *obj = new SWGSDRPlaySettings(); - obj->init(); - return obj; + return new SWGSDRPlaySettings(); } if(QString("SWGSDRPlayV3Report").compare(type) == 0) { - SWGSDRPlayV3Report *obj = new SWGSDRPlayV3Report(); - obj->init(); - return obj; + return new SWGSDRPlayV3Report(); } if(QString("SWGSDRPlayV3Settings").compare(type) == 0) { - SWGSDRPlayV3Settings *obj = new SWGSDRPlayV3Settings(); - obj->init(); - return obj; + return new SWGSDRPlayV3Settings(); } if(QString("SWGSSBDemodReport").compare(type) == 0) { - SWGSSBDemodReport *obj = new SWGSSBDemodReport(); - obj->init(); - return obj; + return new SWGSSBDemodReport(); } if(QString("SWGSSBDemodSettings").compare(type) == 0) { - SWGSSBDemodSettings *obj = new SWGSSBDemodSettings(); - obj->init(); - return obj; + return new SWGSSBDemodSettings(); } if(QString("SWGSSBModReport").compare(type) == 0) { - SWGSSBModReport *obj = new SWGSSBModReport(); - obj->init(); - return obj; + return new SWGSSBModReport(); } if(QString("SWGSSBModSettings").compare(type) == 0) { - SWGSSBModSettings *obj = new SWGSSBModSettings(); - obj->init(); - return obj; + return new SWGSSBModSettings(); } if(QString("SWGSampleRate").compare(type) == 0) { - SWGSampleRate *obj = new SWGSampleRate(); - obj->init(); - return obj; + return new SWGSampleRate(); } if(QString("SWGSamplingDevice").compare(type) == 0) { - SWGSamplingDevice *obj = new SWGSamplingDevice(); - obj->init(); - return obj; + return new SWGSamplingDevice(); } if(QString("SWGSatelliteTrackerSettings").compare(type) == 0) { - SWGSatelliteTrackerSettings *obj = new SWGSatelliteTrackerSettings(); - obj->init(); - return obj; + return new SWGSatelliteTrackerSettings(); } if(QString("SWGSigMFFileInputActions").compare(type) == 0) { - SWGSigMFFileInputActions *obj = new SWGSigMFFileInputActions(); - obj->init(); - return obj; + return new SWGSigMFFileInputActions(); } if(QString("SWGSigMFFileInputReport").compare(type) == 0) { - SWGSigMFFileInputReport *obj = new SWGSigMFFileInputReport(); - obj->init(); - return obj; + return new SWGSigMFFileInputReport(); } if(QString("SWGSigMFFileInputSettings").compare(type) == 0) { - SWGSigMFFileInputSettings *obj = new SWGSigMFFileInputSettings(); - obj->init(); - return obj; + return new SWGSigMFFileInputSettings(); } if(QString("SWGSigMFFileSinkActions").compare(type) == 0) { - SWGSigMFFileSinkActions *obj = new SWGSigMFFileSinkActions(); - obj->init(); - return obj; + return new SWGSigMFFileSinkActions(); } if(QString("SWGSigMFFileSinkReport").compare(type) == 0) { - SWGSigMFFileSinkReport *obj = new SWGSigMFFileSinkReport(); - obj->init(); - return obj; + return new SWGSigMFFileSinkReport(); } if(QString("SWGSigMFFileSinkSettings").compare(type) == 0) { - SWGSigMFFileSinkSettings *obj = new SWGSigMFFileSinkSettings(); - obj->init(); - return obj; + return new SWGSigMFFileSinkSettings(); } if(QString("SWGSimplePTTActions").compare(type) == 0) { - SWGSimplePTTActions *obj = new SWGSimplePTTActions(); - obj->init(); - return obj; + return new SWGSimplePTTActions(); } if(QString("SWGSimplePTTReport").compare(type) == 0) { - SWGSimplePTTReport *obj = new SWGSimplePTTReport(); - obj->init(); - return obj; + return new SWGSimplePTTReport(); } if(QString("SWGSimplePTTSettings").compare(type) == 0) { - SWGSimplePTTSettings *obj = new SWGSimplePTTSettings(); - obj->init(); - return obj; + return new SWGSimplePTTSettings(); } if(QString("SWGSoapySDRFrequencySetting").compare(type) == 0) { - SWGSoapySDRFrequencySetting *obj = new SWGSoapySDRFrequencySetting(); - obj->init(); - return obj; + return new SWGSoapySDRFrequencySetting(); } if(QString("SWGSoapySDRGainSetting").compare(type) == 0) { - SWGSoapySDRGainSetting *obj = new SWGSoapySDRGainSetting(); - obj->init(); - return obj; + return new SWGSoapySDRGainSetting(); } if(QString("SWGSoapySDRInputSettings").compare(type) == 0) { - SWGSoapySDRInputSettings *obj = new SWGSoapySDRInputSettings(); - obj->init(); - return obj; + return new SWGSoapySDRInputSettings(); } if(QString("SWGSoapySDROutputSettings").compare(type) == 0) { - SWGSoapySDROutputSettings *obj = new SWGSoapySDROutputSettings(); - obj->init(); - return obj; + return new SWGSoapySDROutputSettings(); } if(QString("SWGSoapySDRReport").compare(type) == 0) { - SWGSoapySDRReport *obj = new SWGSoapySDRReport(); - obj->init(); - return obj; + return new SWGSoapySDRReport(); } if(QString("SWGSpectrumServer").compare(type) == 0) { - SWGSpectrumServer *obj = new SWGSpectrumServer(); - obj->init(); - return obj; + return new SWGSpectrumServer(); } if(QString("SWGSpectrumServer_clients").compare(type) == 0) { - SWGSpectrumServer_clients *obj = new SWGSpectrumServer_clients(); - obj->init(); - return obj; + return new SWGSpectrumServer_clients(); } if(QString("SWGStarTrackerSettings").compare(type) == 0) { - SWGStarTrackerSettings *obj = new SWGStarTrackerSettings(); - obj->init(); - return obj; + return new SWGStarTrackerSettings(); } if(QString("SWGSuccessResponse").compare(type) == 0) { - SWGSuccessResponse *obj = new SWGSuccessResponse(); - obj->init(); - return obj; + return new SWGSuccessResponse(); } if(QString("SWGTargetAzimuthElevation").compare(type) == 0) { - SWGTargetAzimuthElevation *obj = new SWGTargetAzimuthElevation(); - obj->init(); - return obj; + return new SWGTargetAzimuthElevation(); } if(QString("SWGTestMISettings").compare(type) == 0) { - SWGTestMISettings *obj = new SWGTestMISettings(); - obj->init(); - return obj; + return new SWGTestMISettings(); } if(QString("SWGTestMOSyncSettings").compare(type) == 0) { - SWGTestMOSyncSettings *obj = new SWGTestMOSyncSettings(); - obj->init(); - return obj; + return new SWGTestMOSyncSettings(); } if(QString("SWGTestMiStreamSettings").compare(type) == 0) { - SWGTestMiStreamSettings *obj = new SWGTestMiStreamSettings(); - obj->init(); - return obj; + return new SWGTestMiStreamSettings(); } if(QString("SWGTestSourceSettings").compare(type) == 0) { - SWGTestSourceSettings *obj = new SWGTestSourceSettings(); - obj->init(); - return obj; + return new SWGTestSourceSettings(); } if(QString("SWGTraceData").compare(type) == 0) { - SWGTraceData *obj = new SWGTraceData(); - obj->init(); - return obj; + return new SWGTraceData(); } if(QString("SWGTriggerData").compare(type) == 0) { - SWGTriggerData *obj = new SWGTriggerData(); - obj->init(); - return obj; + return new SWGTriggerData(); } if(QString("SWGUDPSinkReport").compare(type) == 0) { - SWGUDPSinkReport *obj = new SWGUDPSinkReport(); - obj->init(); - return obj; + return new SWGUDPSinkReport(); } if(QString("SWGUDPSinkSettings").compare(type) == 0) { - SWGUDPSinkSettings *obj = new SWGUDPSinkSettings(); - obj->init(); - return obj; + return new SWGUDPSinkSettings(); } if(QString("SWGUDPSourceReport").compare(type) == 0) { - SWGUDPSourceReport *obj = new SWGUDPSourceReport(); - obj->init(); - return obj; + return new SWGUDPSourceReport(); } if(QString("SWGUDPSourceSettings").compare(type) == 0) { - SWGUDPSourceSettings *obj = new SWGUDPSourceSettings(); - obj->init(); - return obj; + return new SWGUDPSourceSettings(); } if(QString("SWGUSRPInputReport").compare(type) == 0) { - SWGUSRPInputReport *obj = new SWGUSRPInputReport(); - obj->init(); - return obj; + return new SWGUSRPInputReport(); } if(QString("SWGUSRPInputSettings").compare(type) == 0) { - SWGUSRPInputSettings *obj = new SWGUSRPInputSettings(); - obj->init(); - return obj; + return new SWGUSRPInputSettings(); } if(QString("SWGUSRPOutputReport").compare(type) == 0) { - SWGUSRPOutputReport *obj = new SWGUSRPOutputReport(); - obj->init(); - return obj; + return new SWGUSRPOutputReport(); } if(QString("SWGUSRPOutputSettings").compare(type) == 0) { - SWGUSRPOutputSettings *obj = new SWGUSRPOutputSettings(); - obj->init(); - return obj; + return new SWGUSRPOutputSettings(); } if(QString("SWGVORDemodReport").compare(type) == 0) { - SWGVORDemodReport *obj = new SWGVORDemodReport(); - obj->init(); - return obj; + return new SWGVORDemodReport(); } if(QString("SWGVORDemodSCReport").compare(type) == 0) { - SWGVORDemodSCReport *obj = new SWGVORDemodSCReport(); - obj->init(); - return obj; + return new SWGVORDemodSCReport(); } if(QString("SWGVORDemodSCSettings").compare(type) == 0) { - SWGVORDemodSCSettings *obj = new SWGVORDemodSCSettings(); - obj->init(); - return obj; + return new SWGVORDemodSCSettings(); } if(QString("SWGVORDemodSettings").compare(type) == 0) { - SWGVORDemodSettings *obj = new SWGVORDemodSettings(); - obj->init(); - return obj; + return new SWGVORDemodSettings(); } if(QString("SWGVORLocalizerSettings").compare(type) == 0) { - SWGVORLocalizerSettings *obj = new SWGVORLocalizerSettings(); - obj->init(); - return obj; + return new SWGVORLocalizerSettings(); } if(QString("SWGWFMDemodReport").compare(type) == 0) { - SWGWFMDemodReport *obj = new SWGWFMDemodReport(); - obj->init(); - return obj; + return new SWGWFMDemodReport(); } if(QString("SWGWFMDemodSettings").compare(type) == 0) { - SWGWFMDemodSettings *obj = new SWGWFMDemodSettings(); - obj->init(); - return obj; + return new SWGWFMDemodSettings(); } if(QString("SWGWFMModReport").compare(type) == 0) { - SWGWFMModReport *obj = new SWGWFMModReport(); - obj->init(); - return obj; + return new SWGWFMModReport(); } if(QString("SWGWFMModSettings").compare(type) == 0) { - SWGWFMModSettings *obj = new SWGWFMModSettings(); - obj->init(); - return obj; + return new SWGWFMModSettings(); } if(QString("SWGXtrxInputReport").compare(type) == 0) { - SWGXtrxInputReport *obj = new SWGXtrxInputReport(); - obj->init(); - return obj; + return new SWGXtrxInputReport(); } if(QString("SWGXtrxInputSettings").compare(type) == 0) { - SWGXtrxInputSettings *obj = new SWGXtrxInputSettings(); - obj->init(); - return obj; + return new SWGXtrxInputSettings(); } if(QString("SWGXtrxMIMOReport").compare(type) == 0) { - SWGXtrxMIMOReport *obj = new SWGXtrxMIMOReport(); - obj->init(); - return obj; + return new SWGXtrxMIMOReport(); } if(QString("SWGXtrxMIMOSettings").compare(type) == 0) { - SWGXtrxMIMOSettings *obj = new SWGXtrxMIMOSettings(); - obj->init(); - return obj; + return new SWGXtrxMIMOSettings(); } if(QString("SWGXtrxOutputReport").compare(type) == 0) { - SWGXtrxOutputReport *obj = new SWGXtrxOutputReport(); - obj->init(); - return obj; + return new SWGXtrxOutputReport(); } if(QString("SWGXtrxOutputSettings").compare(type) == 0) { - SWGXtrxOutputSettings *obj = new SWGXtrxOutputSettings(); - obj->init(); - return obj; + return new SWGXtrxOutputSettings(); } - + return nullptr; } diff --git a/swagger/sdrangel/code/qt5/client/SWGRadioClockReport.cpp b/swagger/sdrangel/code/qt5/client/SWGRadioClockReport.cpp new file mode 100644 index 000000000..f95a18b5c --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGRadioClockReport.cpp @@ -0,0 +1,181 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGRadioClockReport.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGRadioClockReport::SWGRadioClockReport(QString* json) { + init(); + this->fromJson(*json); +} + +SWGRadioClockReport::SWGRadioClockReport() { + channel_power_db = 0.0f; + m_channel_power_db_isSet = false; + channel_sample_rate = 0; + m_channel_sample_rate_isSet = false; + date = nullptr; + m_date_isSet = false; + time = nullptr; + m_time_isSet = false; +} + +SWGRadioClockReport::~SWGRadioClockReport() { + this->cleanup(); +} + +void +SWGRadioClockReport::init() { + channel_power_db = 0.0f; + m_channel_power_db_isSet = false; + channel_sample_rate = 0; + m_channel_sample_rate_isSet = false; + date = new QString(""); + m_date_isSet = false; + time = new QString(""); + m_time_isSet = false; +} + +void +SWGRadioClockReport::cleanup() { + + + if(date != nullptr) { + delete date; + } + if(time != nullptr) { + delete time; + } +} + +SWGRadioClockReport* +SWGRadioClockReport::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGRadioClockReport::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&channel_power_db, pJson["channelPowerDB"], "float", ""); + + ::SWGSDRangel::setValue(&channel_sample_rate, pJson["channelSampleRate"], "qint32", ""); + + ::SWGSDRangel::setValue(&date, pJson["date"], "QString", "QString"); + + ::SWGSDRangel::setValue(&time, pJson["time"], "QString", "QString"); + +} + +QString +SWGRadioClockReport::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGRadioClockReport::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_channel_power_db_isSet){ + obj->insert("channelPowerDB", QJsonValue(channel_power_db)); + } + if(m_channel_sample_rate_isSet){ + obj->insert("channelSampleRate", QJsonValue(channel_sample_rate)); + } + if(date != nullptr && *date != QString("")){ + toJsonValue(QString("date"), date, obj, QString("QString")); + } + if(time != nullptr && *time != QString("")){ + toJsonValue(QString("time"), time, obj, QString("QString")); + } + + return obj; +} + +float +SWGRadioClockReport::getChannelPowerDb() { + return channel_power_db; +} +void +SWGRadioClockReport::setChannelPowerDb(float channel_power_db) { + this->channel_power_db = channel_power_db; + this->m_channel_power_db_isSet = true; +} + +qint32 +SWGRadioClockReport::getChannelSampleRate() { + return channel_sample_rate; +} +void +SWGRadioClockReport::setChannelSampleRate(qint32 channel_sample_rate) { + this->channel_sample_rate = channel_sample_rate; + this->m_channel_sample_rate_isSet = true; +} + +QString* +SWGRadioClockReport::getDate() { + return date; +} +void +SWGRadioClockReport::setDate(QString* date) { + this->date = date; + this->m_date_isSet = true; +} + +QString* +SWGRadioClockReport::getTime() { + return time; +} +void +SWGRadioClockReport::setTime(QString* time) { + this->time = time; + this->m_time_isSet = true; +} + + +bool +SWGRadioClockReport::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_channel_power_db_isSet){ + isObjectUpdated = true; break; + } + if(m_channel_sample_rate_isSet){ + isObjectUpdated = true; break; + } + if(date && *date != QString("")){ + isObjectUpdated = true; break; + } + if(time && *time != QString("")){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGRadioClockReport.h b/swagger/sdrangel/code/qt5/client/SWGRadioClockReport.h new file mode 100644 index 000000000..f264813fe --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGRadioClockReport.h @@ -0,0 +1,77 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGRadioClockReport.h + * + * RadioClock + */ + +#ifndef SWGRadioClockReport_H_ +#define SWGRadioClockReport_H_ + +#include + + +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGRadioClockReport: public SWGObject { +public: + SWGRadioClockReport(); + SWGRadioClockReport(QString* json); + virtual ~SWGRadioClockReport(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGRadioClockReport* fromJson(QString &jsonString) override; + + float getChannelPowerDb(); + void setChannelPowerDb(float channel_power_db); + + qint32 getChannelSampleRate(); + void setChannelSampleRate(qint32 channel_sample_rate); + + QString* getDate(); + void setDate(QString* date); + + QString* getTime(); + void setTime(QString* time); + + + virtual bool isSet() override; + +private: + float channel_power_db; + bool m_channel_power_db_isSet; + + qint32 channel_sample_rate; + bool m_channel_sample_rate_isSet; + + QString* date; + bool m_date_isSet; + + QString* time; + bool m_time_isSet; + +}; + +} + +#endif /* SWGRadioClockReport_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGRadioClockSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGRadioClockSettings.cpp new file mode 100644 index 000000000..e388ea83b --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGRadioClockSettings.cpp @@ -0,0 +1,388 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +#include "SWGRadioClockSettings.h" + +#include "SWGHelpers.h" + +#include +#include +#include +#include + +namespace SWGSDRangel { + +SWGRadioClockSettings::SWGRadioClockSettings(QString* json) { + init(); + this->fromJson(*json); +} + +SWGRadioClockSettings::SWGRadioClockSettings() { + input_frequency_offset = 0L; + m_input_frequency_offset_isSet = false; + rf_bandwidth = 0.0f; + m_rf_bandwidth_isSet = false; + threshold = 0.0f; + m_threshold_isSet = false; + modulation = 0; + m_modulation_isSet = false; + timezone = 0; + m_timezone_isSet = false; + rgb_color = 0; + m_rgb_color_isSet = false; + title = nullptr; + m_title_isSet = false; + stream_index = 0; + m_stream_index_isSet = false; + use_reverse_api = 0; + m_use_reverse_api_isSet = false; + reverse_api_address = nullptr; + m_reverse_api_address_isSet = false; + reverse_api_port = 0; + m_reverse_api_port_isSet = false; + reverse_api_device_index = 0; + m_reverse_api_device_index_isSet = false; + reverse_api_channel_index = 0; + m_reverse_api_channel_index_isSet = false; +} + +SWGRadioClockSettings::~SWGRadioClockSettings() { + this->cleanup(); +} + +void +SWGRadioClockSettings::init() { + input_frequency_offset = 0L; + m_input_frequency_offset_isSet = false; + rf_bandwidth = 0.0f; + m_rf_bandwidth_isSet = false; + threshold = 0.0f; + m_threshold_isSet = false; + modulation = 0; + m_modulation_isSet = false; + timezone = 0; + m_timezone_isSet = false; + rgb_color = 0; + m_rgb_color_isSet = false; + title = new QString(""); + m_title_isSet = false; + stream_index = 0; + m_stream_index_isSet = false; + use_reverse_api = 0; + m_use_reverse_api_isSet = false; + reverse_api_address = new QString(""); + m_reverse_api_address_isSet = false; + reverse_api_port = 0; + m_reverse_api_port_isSet = false; + reverse_api_device_index = 0; + m_reverse_api_device_index_isSet = false; + reverse_api_channel_index = 0; + m_reverse_api_channel_index_isSet = false; +} + +void +SWGRadioClockSettings::cleanup() { + + + + + + + if(title != nullptr) { + delete title; + } + + + if(reverse_api_address != nullptr) { + delete reverse_api_address; + } + + + +} + +SWGRadioClockSettings* +SWGRadioClockSettings::fromJson(QString &json) { + QByteArray array (json.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); + return this; +} + +void +SWGRadioClockSettings::fromJsonObject(QJsonObject &pJson) { + ::SWGSDRangel::setValue(&input_frequency_offset, pJson["inputFrequencyOffset"], "qint64", ""); + + ::SWGSDRangel::setValue(&rf_bandwidth, pJson["rfBandwidth"], "float", ""); + + ::SWGSDRangel::setValue(&threshold, pJson["threshold"], "float", ""); + + ::SWGSDRangel::setValue(&modulation, pJson["modulation"], "qint32", ""); + + ::SWGSDRangel::setValue(&timezone, pJson["timezone"], "qint32", ""); + + ::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", ""); + + ::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString"); + + ::SWGSDRangel::setValue(&stream_index, pJson["streamIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString"); + + ::SWGSDRangel::setValue(&reverse_api_port, pJson["reverseAPIPort"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_device_index, pJson["reverseAPIDeviceIndex"], "qint32", ""); + + ::SWGSDRangel::setValue(&reverse_api_channel_index, pJson["reverseAPIChannelIndex"], "qint32", ""); + +} + +QString +SWGRadioClockSettings::asJson () +{ + QJsonObject* obj = this->asJsonObject(); + + QJsonDocument doc(*obj); + QByteArray bytes = doc.toJson(); + delete obj; + return QString(bytes); +} + +QJsonObject* +SWGRadioClockSettings::asJsonObject() { + QJsonObject* obj = new QJsonObject(); + if(m_input_frequency_offset_isSet){ + obj->insert("inputFrequencyOffset", QJsonValue(input_frequency_offset)); + } + if(m_rf_bandwidth_isSet){ + obj->insert("rfBandwidth", QJsonValue(rf_bandwidth)); + } + if(m_threshold_isSet){ + obj->insert("threshold", QJsonValue(threshold)); + } + if(m_modulation_isSet){ + obj->insert("modulation", QJsonValue(modulation)); + } + if(m_timezone_isSet){ + obj->insert("timezone", QJsonValue(timezone)); + } + if(m_rgb_color_isSet){ + obj->insert("rgbColor", QJsonValue(rgb_color)); + } + if(title != nullptr && *title != QString("")){ + toJsonValue(QString("title"), title, obj, QString("QString")); + } + if(m_stream_index_isSet){ + obj->insert("streamIndex", QJsonValue(stream_index)); + } + if(m_use_reverse_api_isSet){ + obj->insert("useReverseAPI", QJsonValue(use_reverse_api)); + } + if(reverse_api_address != nullptr && *reverse_api_address != QString("")){ + toJsonValue(QString("reverseAPIAddress"), reverse_api_address, obj, QString("QString")); + } + if(m_reverse_api_port_isSet){ + obj->insert("reverseAPIPort", QJsonValue(reverse_api_port)); + } + if(m_reverse_api_device_index_isSet){ + obj->insert("reverseAPIDeviceIndex", QJsonValue(reverse_api_device_index)); + } + if(m_reverse_api_channel_index_isSet){ + obj->insert("reverseAPIChannelIndex", QJsonValue(reverse_api_channel_index)); + } + + return obj; +} + +qint64 +SWGRadioClockSettings::getInputFrequencyOffset() { + return input_frequency_offset; +} +void +SWGRadioClockSettings::setInputFrequencyOffset(qint64 input_frequency_offset) { + this->input_frequency_offset = input_frequency_offset; + this->m_input_frequency_offset_isSet = true; +} + +float +SWGRadioClockSettings::getRfBandwidth() { + return rf_bandwidth; +} +void +SWGRadioClockSettings::setRfBandwidth(float rf_bandwidth) { + this->rf_bandwidth = rf_bandwidth; + this->m_rf_bandwidth_isSet = true; +} + +float +SWGRadioClockSettings::getThreshold() { + return threshold; +} +void +SWGRadioClockSettings::setThreshold(float threshold) { + this->threshold = threshold; + this->m_threshold_isSet = true; +} + +qint32 +SWGRadioClockSettings::getModulation() { + return modulation; +} +void +SWGRadioClockSettings::setModulation(qint32 modulation) { + this->modulation = modulation; + this->m_modulation_isSet = true; +} + +qint32 +SWGRadioClockSettings::getTimezone() { + return timezone; +} +void +SWGRadioClockSettings::setTimezone(qint32 timezone) { + this->timezone = timezone; + this->m_timezone_isSet = true; +} + +qint32 +SWGRadioClockSettings::getRgbColor() { + return rgb_color; +} +void +SWGRadioClockSettings::setRgbColor(qint32 rgb_color) { + this->rgb_color = rgb_color; + this->m_rgb_color_isSet = true; +} + +QString* +SWGRadioClockSettings::getTitle() { + return title; +} +void +SWGRadioClockSettings::setTitle(QString* title) { + this->title = title; + this->m_title_isSet = true; +} + +qint32 +SWGRadioClockSettings::getStreamIndex() { + return stream_index; +} +void +SWGRadioClockSettings::setStreamIndex(qint32 stream_index) { + this->stream_index = stream_index; + this->m_stream_index_isSet = true; +} + +qint32 +SWGRadioClockSettings::getUseReverseApi() { + return use_reverse_api; +} +void +SWGRadioClockSettings::setUseReverseApi(qint32 use_reverse_api) { + this->use_reverse_api = use_reverse_api; + this->m_use_reverse_api_isSet = true; +} + +QString* +SWGRadioClockSettings::getReverseApiAddress() { + return reverse_api_address; +} +void +SWGRadioClockSettings::setReverseApiAddress(QString* reverse_api_address) { + this->reverse_api_address = reverse_api_address; + this->m_reverse_api_address_isSet = true; +} + +qint32 +SWGRadioClockSettings::getReverseApiPort() { + return reverse_api_port; +} +void +SWGRadioClockSettings::setReverseApiPort(qint32 reverse_api_port) { + this->reverse_api_port = reverse_api_port; + this->m_reverse_api_port_isSet = true; +} + +qint32 +SWGRadioClockSettings::getReverseApiDeviceIndex() { + return reverse_api_device_index; +} +void +SWGRadioClockSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) { + this->reverse_api_device_index = reverse_api_device_index; + this->m_reverse_api_device_index_isSet = true; +} + +qint32 +SWGRadioClockSettings::getReverseApiChannelIndex() { + return reverse_api_channel_index; +} +void +SWGRadioClockSettings::setReverseApiChannelIndex(qint32 reverse_api_channel_index) { + this->reverse_api_channel_index = reverse_api_channel_index; + this->m_reverse_api_channel_index_isSet = true; +} + + +bool +SWGRadioClockSettings::isSet(){ + bool isObjectUpdated = false; + do{ + if(m_input_frequency_offset_isSet){ + isObjectUpdated = true; break; + } + if(m_rf_bandwidth_isSet){ + isObjectUpdated = true; break; + } + if(m_threshold_isSet){ + isObjectUpdated = true; break; + } + if(m_modulation_isSet){ + isObjectUpdated = true; break; + } + if(m_timezone_isSet){ + isObjectUpdated = true; break; + } + if(m_rgb_color_isSet){ + isObjectUpdated = true; break; + } + if(title && *title != QString("")){ + isObjectUpdated = true; break; + } + if(m_stream_index_isSet){ + isObjectUpdated = true; break; + } + if(m_use_reverse_api_isSet){ + isObjectUpdated = true; break; + } + if(reverse_api_address && *reverse_api_address != QString("")){ + isObjectUpdated = true; break; + } + if(m_reverse_api_port_isSet){ + isObjectUpdated = true; break; + } + if(m_reverse_api_device_index_isSet){ + isObjectUpdated = true; break; + } + if(m_reverse_api_channel_index_isSet){ + isObjectUpdated = true; break; + } + }while(false); + return isObjectUpdated; +} +} + diff --git a/swagger/sdrangel/code/qt5/client/SWGRadioClockSettings.h b/swagger/sdrangel/code/qt5/client/SWGRadioClockSettings.h new file mode 100644 index 000000000..db17188eb --- /dev/null +++ b/swagger/sdrangel/code/qt5/client/SWGRadioClockSettings.h @@ -0,0 +1,131 @@ +/** + * SDRangel + * This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time --- + * + * OpenAPI spec version: 6.0.0 + * Contact: f4exb06@gmail.com + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/* + * SWGRadioClockSettings.h + * + * RadioClock + */ + +#ifndef SWGRadioClockSettings_H_ +#define SWGRadioClockSettings_H_ + +#include + + +#include + +#include "SWGObject.h" +#include "export.h" + +namespace SWGSDRangel { + +class SWG_API SWGRadioClockSettings: public SWGObject { +public: + SWGRadioClockSettings(); + SWGRadioClockSettings(QString* json); + virtual ~SWGRadioClockSettings(); + void init(); + void cleanup(); + + virtual QString asJson () override; + virtual QJsonObject* asJsonObject() override; + virtual void fromJsonObject(QJsonObject &json) override; + virtual SWGRadioClockSettings* fromJson(QString &jsonString) override; + + qint64 getInputFrequencyOffset(); + void setInputFrequencyOffset(qint64 input_frequency_offset); + + float getRfBandwidth(); + void setRfBandwidth(float rf_bandwidth); + + float getThreshold(); + void setThreshold(float threshold); + + qint32 getModulation(); + void setModulation(qint32 modulation); + + qint32 getTimezone(); + void setTimezone(qint32 timezone); + + qint32 getRgbColor(); + void setRgbColor(qint32 rgb_color); + + QString* getTitle(); + void setTitle(QString* title); + + qint32 getStreamIndex(); + void setStreamIndex(qint32 stream_index); + + qint32 getUseReverseApi(); + void setUseReverseApi(qint32 use_reverse_api); + + QString* getReverseApiAddress(); + void setReverseApiAddress(QString* reverse_api_address); + + qint32 getReverseApiPort(); + void setReverseApiPort(qint32 reverse_api_port); + + qint32 getReverseApiDeviceIndex(); + void setReverseApiDeviceIndex(qint32 reverse_api_device_index); + + qint32 getReverseApiChannelIndex(); + void setReverseApiChannelIndex(qint32 reverse_api_channel_index); + + + virtual bool isSet() override; + +private: + qint64 input_frequency_offset; + bool m_input_frequency_offset_isSet; + + float rf_bandwidth; + bool m_rf_bandwidth_isSet; + + float threshold; + bool m_threshold_isSet; + + qint32 modulation; + bool m_modulation_isSet; + + qint32 timezone; + bool m_timezone_isSet; + + qint32 rgb_color; + bool m_rgb_color_isSet; + + QString* title; + bool m_title_isSet; + + qint32 stream_index; + bool m_stream_index_isSet; + + qint32 use_reverse_api; + bool m_use_reverse_api_isSet; + + QString* reverse_api_address; + bool m_reverse_api_address_isSet; + + qint32 reverse_api_port; + bool m_reverse_api_port_isSet; + + qint32 reverse_api_device_index; + bool m_reverse_api_device_index_isSet; + + qint32 reverse_api_channel_index; + bool m_reverse_api_channel_index_isSet; + +}; + +} + +#endif /* SWGRadioClockSettings_H_ */