M17 demod: plugin base

This commit is contained in:
f4exb 2022-06-05 00:54:59 +02:00
parent 63e41e18ef
commit 9510913930
43 changed files with 7394 additions and 2 deletions

View File

@ -91,6 +91,7 @@ endif()
if (ENABLE_CHANNELRX_DEMODFREEDV AND CODEC2_FOUND)
add_subdirectory(demodfreedv)
add_subdirectory(demodm17)
endif(CODEC2_FOUND)
if (ENABLE_CHANNELRX_SIGMFFILESINK AND LIBSIGMF_FOUND AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")

View File

@ -0,0 +1,74 @@
project(demodm17)
set(m17_SOURCES
m17demod.cpp
m17demodbaseband.cpp
m17demodsink.cpp
m17demodsettings.cpp
m17demodwebapiadapter.cpp
m17demodplugin.cpp
m17demodbaudrates.cpp
)
set(m17_HEADERS
m17demod.h
m17demodbaseband.h
m17demodsink.h
m17demodsettings.h
m17demodwebapiadapter.h
m17demodplugin.h
m17demodbaudrates.h
)
include_directories(
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
${CODEC2_INCLUDE_DIR}
)
if(NOT SERVER_MODE)
set(m17_SOURCES
${m17_SOURCES}
m17demodgui.cpp
m17demodgui.ui
m17statustextdialog.cpp
m17statustextdialog.ui
)
set(m17_HEADERS
${m17_HEADERS}
m17demodgui.h
m17statustextdialog.h
)
set(TARGET_NAME demodm17)
set(TARGET_LIB "Qt5::Widgets")
set(TARGET_LIB_GUI "sdrgui")
set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR})
else()
set(TARGET_NAME demodm17srv)
set(TARGET_LIB "")
set(TARGET_LIB_GUI "")
set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR})
endif()
add_library(${TARGET_NAME} SHARED
${m17_SOURCES}
)
if(CODEC2_EXTERNAL)
add_dependencies(${TARGET_NAME} codec2)
endif()
target_link_libraries(${TARGET_NAME}
Qt5::Core
${TARGET_LIB}
sdrbase
${TARGET_LIB_GUI}
swagger
${CODEC2_LIBRARIES}
)
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})
# Install debug symbols
if (WIN32)
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
endif()

View File

@ -0,0 +1,729 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 F4EXB //
// written by Edouard Griffiths //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <string.h>
#include <stdio.h>
#include <complex.h>
#include <QTime>
#include <QDebug>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QBuffer>
#include <QThread>
#include "SWGChannelSettings.h"
#include "SWGWorkspaceInfo.h"
#include "SWGChannelReport.h"
#include "dsp/dspengine.h"
#include "dsp/dspcommands.h"
#include "device/deviceapi.h"
#include "feature/feature.h"
#include "feature/featureset.h"
#include "settings/serializable.h"
#include "util/db.h"
#include "maincore.h"
#include "m17demod.h"
MESSAGE_CLASS_DEFINITION(M17Demod::MsgConfigureM17Demod, Message)
const char* const M17Demod::m_channelIdURI = "sdrangel.channel.m17demod";
const char* const M17Demod::m_channelId = "M17Demod";
const int M17Demod::m_udpBlockSize = 512;
M17Demod::M17Demod(DeviceAPI *deviceAPI) :
ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSink),
m_deviceAPI(deviceAPI),
m_basebandSampleRate(0)
{
qDebug("M17Demod::M17Demod");
setObjectName(m_channelId);
m_thread = new QThread(this);
m_basebandSink = new M17DemodBaseband();
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();
QObject::connect(
m_networkManager,
&QNetworkAccessManager::finished,
this,
&M17Demod::networkManagerFinished
);
QObject::connect(
this,
&ChannelAPI::indexInDeviceSetChanged,
this,
&M17Demod::handleIndexInDeviceSetChanged
);
}
M17Demod::~M17Demod()
{
QObject::disconnect(
m_networkManager,
&QNetworkAccessManager::finished,
this,
&M17Demod::networkManagerFinished
);
delete m_networkManager;
m_deviceAPI->removeChannelSinkAPI(this);
m_deviceAPI->removeChannelSink(this);
delete m_basebandSink;
delete m_thread;
}
void M17Demod::setDeviceAPI(DeviceAPI *deviceAPI)
{
if (deviceAPI != m_deviceAPI)
{
m_deviceAPI->removeChannelSinkAPI(this);
m_deviceAPI->removeChannelSink(this);
m_deviceAPI = deviceAPI;
m_deviceAPI->addChannelSink(this);
m_deviceAPI->addChannelSinkAPI(this);
}
}
uint32_t M17Demod::getNumberOfDeviceStreams() const
{
return m_deviceAPI->getNbSourceStreams();
}
void M17Demod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst)
{
(void) firstOfBurst;
m_basebandSink->feed(begin, end);
}
void M17Demod::start()
{
qDebug() << "M17Demod::start";
if (m_basebandSampleRate != 0) {
m_basebandSink->setBasebandSampleRate(m_basebandSampleRate);
}
m_basebandSink->reset();
m_thread->start();
}
void M17Demod::stop()
{
qDebug() << "M17Demod::stop";
m_thread->exit();
m_thread->wait();
}
bool M17Demod::handleMessage(const Message& cmd)
{
qDebug() << "M17Demod::handleMessage";
if (MsgConfigureM17Demod::match(cmd))
{
MsgConfigureM17Demod& cfg = (MsgConfigureM17Demod&) cmd;
qDebug("M17Demod::handleMessage: MsgConfigureM17Demod");
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
else if (DSPSignalNotification::match(cmd))
{
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
m_basebandSampleRate = notif.getSampleRate();
// Forward to the sink
DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy
qDebug() << "M17Demod::handleMessage: DSPSignalNotification";
m_basebandSink->getInputMessageQueue()->push(rep);
// Forward to GUI if any
if (getMessageQueueToGUI()) {
getMessageQueueToGUI()->push(new DSPSignalNotification(notif));
}
return true;
}
else if (MainCore::MsgChannelDemodQuery::match(cmd))
{
qDebug() << "M17Demod::handleMessage: MsgChannelDemodQuery";
sendSampleRateToDemodAnalyzer();
return true;
}
else
{
return false;
}
}
void M17Demod::setCenterFrequency(qint64 frequency)
{
M17DemodSettings settings = m_settings;
settings.m_inputFrequencyOffset = frequency;
applySettings(settings, false);
if (m_guiMessageQueue) // forward to GUI if any
{
MsgConfigureM17Demod *msgToGUI = MsgConfigureM17Demod::create(settings, false);
m_guiMessageQueue->push(msgToGUI);
}
}
void M17Demod::applySettings(const M17DemodSettings& settings, bool force)
{
qDebug() << "M17Demod::applySettings: "
<< " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset
<< " m_rfBandwidth: " << settings.m_rfBandwidth
<< " m_fmDeviation: " << settings.m_fmDeviation
<< " m_demodGain: " << settings.m_demodGain
<< " m_volume: " << settings.m_volume
<< " m_baudRate: " << settings.m_baudRate
<< " m_squelchGate" << settings.m_squelchGate
<< " m_squelch: " << settings.m_squelch
<< " m_audioMute: " << settings.m_audioMute
<< " m_syncOrConstellation: " << settings.m_syncOrConstellation
<< " m_highPassFilter: "<< settings.m_highPassFilter
<< " m_audioDeviceName: " << settings.m_audioDeviceName
<< " m_traceLengthMutliplier: " << settings.m_traceLengthMutliplier
<< " m_traceStroke: " << settings.m_traceStroke
<< " m_traceDecay: " << settings.m_traceDecay
<< " m_streamIndex: " << settings.m_streamIndex
<< " force: " << force;
QList<QString> reverseAPIKeys;
if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) {
reverseAPIKeys.append("inputFrequencyOffset");
}
if ((settings.m_demodGain != m_settings.m_demodGain) || force) {
reverseAPIKeys.append("demodGain");
}
if ((settings.m_audioMute != m_settings.m_audioMute) || force) {
reverseAPIKeys.append("audioMute");
}
if ((settings.m_syncOrConstellation != m_settings.m_syncOrConstellation) || force) {
reverseAPIKeys.append("syncOrConstellation");
}
if ((settings.m_demodGain != m_settings.m_demodGain) || force) {
reverseAPIKeys.append("demodGain");
}
if ((settings.m_traceLengthMutliplier != m_settings.m_traceLengthMutliplier) || force) {
reverseAPIKeys.append("traceLengthMutliplier");
}
if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) {
reverseAPIKeys.append("rfBandwidth");
}
if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force) {
reverseAPIKeys.append("fmDeviation");
}
if ((settings.m_squelchGate != m_settings.m_squelchGate) || force) {
reverseAPIKeys.append("squelchGate");
}
if ((settings.m_squelch != m_settings.m_squelch) || force) {
reverseAPIKeys.append("squelch");
}
if ((settings.m_volume != m_settings.m_volume) || force) {
reverseAPIKeys.append("volume");
}
if ((settings.m_baudRate != m_settings.m_baudRate) || force) {
reverseAPIKeys.append("baudRate");
}
if ((settings.m_highPassFilter != m_settings.m_highPassFilter) || force) {
reverseAPIKeys.append("highPassFilter");
}
if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force) {
reverseAPIKeys.append("audioDeviceName");
}
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");
}
M17DemodBaseband::MsgConfigureM17DemodBaseband *msg = M17DemodBaseband::MsgConfigureM17DemodBaseband::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);
}
QList<ObjectPipe*> pipes;
MainCore::instance()->getMessagePipes().getMessagePipes(this, "settings", pipes);
if (pipes.size() > 0) {
sendChannelSettings(pipes, reverseAPIKeys, settings, force);
}
m_settings = settings;
}
QByteArray M17Demod::serialize() const
{
return m_settings.serialize();
}
bool M17Demod::deserialize(const QByteArray& data)
{
if (m_settings.deserialize(data))
{
MsgConfigureM17Demod *msg = MsgConfigureM17Demod::create(m_settings, true);
m_inputMessageQueue.push(msg);
return true;
}
else
{
m_settings.resetToDefaults();
MsgConfigureM17Demod *msg = MsgConfigureM17Demod::create(m_settings, true);
m_inputMessageQueue.push(msg);
return false;
}
}
void M17Demod::sendSampleRateToDemodAnalyzer()
{
QList<ObjectPipe*> pipes;
MainCore::instance()->getMessagePipes().getMessagePipes(this, "reportdemod", pipes);
if (pipes.size() > 0)
{
for (const auto& pipe : pipes)
{
MessageQueue *messageQueue = qobject_cast<MessageQueue*>(pipe->m_element);
MainCore::MsgChannelDemodReport *msg = MainCore::MsgChannelDemodReport::create(
this,
getAudioSampleRate()
);
messageQueue->push(msg);
}
}
}
int M17Demod::webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setM17DemodSettings(new SWGSDRangel::SWGM17DemodSettings());
response.getM17DemodSettings()->init();
webapiFormatChannelSettings(response, m_settings);
return 200;
}
int M17Demod::webapiWorkspaceGet(
SWGSDRangel::SWGWorkspaceInfo& response,
QString& errorMessage)
{
(void) errorMessage;
response.setIndex(m_settings.m_workspaceIndex);
return 200;
}
int M17Demod::webapiSettingsPutPatch(
bool force,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) errorMessage;
M17DemodSettings settings = m_settings;
webapiUpdateChannelSettings(settings, channelSettingsKeys, response);
MsgConfigureM17Demod *msg = MsgConfigureM17Demod::create(settings, force);
m_inputMessageQueue.push(msg);
qDebug("M17Demod::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue);
if (m_guiMessageQueue) // forward to GUI if any
{
MsgConfigureM17Demod *msgToGUI = MsgConfigureM17Demod::create(settings, force);
m_guiMessageQueue->push(msgToGUI);
}
webapiFormatChannelSettings(response, settings);
return 200;
}
void M17Demod::webapiUpdateChannelSettings(
M17DemodSettings& settings,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response)
{
if (channelSettingsKeys.contains("inputFrequencyOffset")) {
settings.m_inputFrequencyOffset = response.getM17DemodSettings()->getInputFrequencyOffset();
}
if (channelSettingsKeys.contains("rfBandwidth")) {
settings.m_rfBandwidth = response.getM17DemodSettings()->getRfBandwidth();
}
if (channelSettingsKeys.contains("fmDeviation")) {
settings.m_fmDeviation = response.getM17DemodSettings()->getFmDeviation();
}
if (channelSettingsKeys.contains("demodGain")) {
settings.m_demodGain = response.getM17DemodSettings()->getDemodGain();
}
if (channelSettingsKeys.contains("volume")) {
settings.m_volume = response.getM17DemodSettings()->getVolume();
}
if (channelSettingsKeys.contains("baudRate")) {
settings.m_baudRate = response.getM17DemodSettings()->getBaudRate();
}
if (channelSettingsKeys.contains("squelchGate")) {
settings.m_squelchGate = response.getM17DemodSettings()->getSquelchGate();
}
if (channelSettingsKeys.contains("squelch")) {
settings.m_squelch = response.getM17DemodSettings()->getSquelch();
}
if (channelSettingsKeys.contains("audioMute")) {
settings.m_audioMute = response.getM17DemodSettings()->getAudioMute() != 0;
}
if (channelSettingsKeys.contains("syncOrConstellation")) {
settings.m_syncOrConstellation = response.getM17DemodSettings()->getSyncOrConstellation() != 0;
}
if (channelSettingsKeys.contains("rgbColor")) {
settings.m_rgbColor = response.getM17DemodSettings()->getRgbColor();
}
if (channelSettingsKeys.contains("title")) {
settings.m_title = *response.getM17DemodSettings()->getTitle();
}
if (channelSettingsKeys.contains("audioDeviceName")) {
settings.m_audioDeviceName = *response.getM17DemodSettings()->getAudioDeviceName();
}
if (channelSettingsKeys.contains("highPassFilter")) {
settings.m_highPassFilter = response.getM17DemodSettings()->getHighPassFilter() != 0;
}
if (channelSettingsKeys.contains("traceLengthMutliplier")) {
settings.m_traceLengthMutliplier = response.getM17DemodSettings()->getTraceLengthMutliplier();
}
if (channelSettingsKeys.contains("traceStroke")) {
settings.m_traceStroke = response.getM17DemodSettings()->getTraceStroke();
}
if (channelSettingsKeys.contains("traceDecay")) {
settings.m_traceDecay = response.getM17DemodSettings()->getTraceDecay();
}
if (channelSettingsKeys.contains("streamIndex")) {
settings.m_streamIndex = response.getM17DemodSettings()->getStreamIndex();
}
if (channelSettingsKeys.contains("useReverseAPI")) {
settings.m_useReverseAPI = response.getM17DemodSettings()->getUseReverseApi() != 0;
}
if (channelSettingsKeys.contains("reverseAPIAddress")) {
settings.m_reverseAPIAddress = *response.getM17DemodSettings()->getReverseApiAddress();
}
if (channelSettingsKeys.contains("reverseAPIPort")) {
settings.m_reverseAPIPort = response.getM17DemodSettings()->getReverseApiPort();
}
if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
settings.m_reverseAPIDeviceIndex = response.getM17DemodSettings()->getReverseApiDeviceIndex();
}
if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
settings.m_reverseAPIChannelIndex = response.getM17DemodSettings()->getReverseApiChannelIndex();
}
if (settings.m_channelMarker && channelSettingsKeys.contains("channelMarker")) {
settings.m_channelMarker->updateFrom(channelSettingsKeys, response.getM17DemodSettings()->getChannelMarker());
}
if (settings.m_rollupState && channelSettingsKeys.contains("rollupState")) {
settings.m_rollupState->updateFrom(channelSettingsKeys, response.getM17DemodSettings()->getRollupState());
}
}
int M17Demod::webapiReportGet(
SWGSDRangel::SWGChannelReport& response,
QString& errorMessage)
{
(void) errorMessage;
response.setM17DemodReport(new SWGSDRangel::SWGM17DemodReport());
response.getM17DemodReport()->init();
webapiFormatChannelReport(response);
return 200;
}
void M17Demod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const M17DemodSettings& settings)
{
response.getM17DemodSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
response.getM17DemodSettings()->setRfBandwidth(settings.m_rfBandwidth);
response.getM17DemodSettings()->setFmDeviation(settings.m_fmDeviation);
response.getM17DemodSettings()->setDemodGain(settings.m_demodGain);
response.getM17DemodSettings()->setVolume(settings.m_volume);
response.getM17DemodSettings()->setBaudRate(settings.m_baudRate);
response.getM17DemodSettings()->setSquelchGate(settings.m_squelchGate);
response.getM17DemodSettings()->setSquelch(settings.m_squelch);
response.getM17DemodSettings()->setAudioMute(settings.m_audioMute ? 1 : 0);
response.getM17DemodSettings()->setSyncOrConstellation(settings.m_syncOrConstellation ? 1 : 0);
response.getM17DemodSettings()->setRgbColor(settings.m_rgbColor);
if (response.getM17DemodSettings()->getTitle()) {
*response.getM17DemodSettings()->getTitle() = settings.m_title;
} else {
response.getM17DemodSettings()->setTitle(new QString(settings.m_title));
}
if (response.getM17DemodSettings()->getAudioDeviceName()) {
*response.getM17DemodSettings()->getAudioDeviceName() = settings.m_audioDeviceName;
} else {
response.getM17DemodSettings()->setAudioDeviceName(new QString(settings.m_audioDeviceName));
}
response.getM17DemodSettings()->setHighPassFilter(settings.m_highPassFilter ? 1 : 0);
response.getM17DemodSettings()->setTraceLengthMutliplier(settings.m_traceLengthMutliplier);
response.getM17DemodSettings()->setTraceStroke(settings.m_traceStroke);
response.getM17DemodSettings()->setTraceDecay(settings.m_traceDecay);
response.getM17DemodSettings()->setStreamIndex(settings.m_streamIndex);
response.getM17DemodSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
if (response.getM17DemodSettings()->getReverseApiAddress()) {
*response.getM17DemodSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress;
} else {
response.getM17DemodSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
}
response.getM17DemodSettings()->setReverseApiPort(settings.m_reverseAPIPort);
response.getM17DemodSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex);
response.getM17DemodSettings()->setReverseApiChannelIndex(settings.m_reverseAPIChannelIndex);
if (settings.m_channelMarker)
{
if (response.getM17DemodSettings()->getChannelMarker())
{
settings.m_channelMarker->formatTo(response.getM17DemodSettings()->getChannelMarker());
}
else
{
SWGSDRangel::SWGChannelMarker *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
settings.m_channelMarker->formatTo(swgChannelMarker);
response.getM17DemodSettings()->setChannelMarker(swgChannelMarker);
}
}
if (settings.m_rollupState)
{
if (response.getM17DemodSettings()->getRollupState())
{
settings.m_rollupState->formatTo(response.getM17DemodSettings()->getRollupState());
}
else
{
SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState();
settings.m_rollupState->formatTo(swgRollupState);
response.getM17DemodSettings()->setRollupState(swgRollupState);
}
}
}
void M17Demod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response)
{
double magsqAvg, magsqPeak;
int nbMagsqSamples;
getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples);
response.getM17DemodReport()->setChannelPowerDb(CalcDb::dbPower(magsqAvg));
response.getM17DemodReport()->setAudioSampleRate(m_basebandSink->getAudioSampleRate());
response.getM17DemodReport()->setChannelSampleRate(m_basebandSink->getChannelSampleRate());
response.getM17DemodReport()->setSquelch(m_basebandSink->getSquelchOpen() ? 1 : 0);
}
void M17Demod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const M17DemodSettings& 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;
}
void M17Demod::sendChannelSettings(
const QList<ObjectPipe*>& pipes,
QList<QString>& channelSettingsKeys,
const M17DemodSettings& settings,
bool force)
{
for (const auto& pipe : pipes)
{
MessageQueue *messageQueue = qobject_cast<MessageQueue*>(pipe->m_element);
if (messageQueue)
{
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
MainCore::MsgChannelSettings *msg = MainCore::MsgChannelSettings::create(
this,
channelSettingsKeys,
swgChannelSettings,
force
);
messageQueue->push(msg);
}
}
}
void M17Demod::webapiFormatChannelSettings(
QList<QString>& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
const M17DemodSettings& settings,
bool force
)
{
swgChannelSettings->setDirection(0); // Single sink (Rx)
swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet());
swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex());
swgChannelSettings->setChannelType(new QString(m_channelId));
swgChannelSettings->setM17DemodSettings(new SWGSDRangel::SWGM17DemodSettings());
SWGSDRangel::SWGM17DemodSettings *swgM17DemodSettings = swgChannelSettings->getM17DemodSettings();
// transfer data that has been modified. When force is on transfer all data except reverse API data
if (channelSettingsKeys.contains("inputFrequencyOffset") || force) {
swgM17DemodSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
}
if (channelSettingsKeys.contains("rfBandwidth") || force) {
swgM17DemodSettings->setRfBandwidth(settings.m_rfBandwidth);
}
if (channelSettingsKeys.contains("fmDeviation") || force) {
swgM17DemodSettings->setFmDeviation(settings.m_fmDeviation);
}
if (channelSettingsKeys.contains("demodGain") || force) {
swgM17DemodSettings->setDemodGain(settings.m_demodGain);
}
if (channelSettingsKeys.contains("volume") || force) {
swgM17DemodSettings->setVolume(settings.m_volume);
}
if (channelSettingsKeys.contains("baudRate") || force) {
swgM17DemodSettings->setBaudRate(settings.m_baudRate);
}
if (channelSettingsKeys.contains("squelchGate") || force) {
swgM17DemodSettings->setSquelchGate(settings.m_squelchGate);
}
if (channelSettingsKeys.contains("squelch") || force) {
swgM17DemodSettings->setSquelch(settings.m_squelch);
}
if (channelSettingsKeys.contains("audioMute") || force) {
swgM17DemodSettings->setAudioMute(settings.m_audioMute ? 1 : 0);
}
if (channelSettingsKeys.contains("syncOrConstellation") || force) {
swgM17DemodSettings->setSyncOrConstellation(settings.m_syncOrConstellation ? 1 : 0);
}
if (channelSettingsKeys.contains("rgbColor") || force) {
swgM17DemodSettings->setRgbColor(settings.m_rgbColor);
}
if (channelSettingsKeys.contains("title") || force) {
swgM17DemodSettings->setTitle(new QString(settings.m_title));
}
if (channelSettingsKeys.contains("audioDeviceName") || force) {
swgM17DemodSettings->setAudioDeviceName(new QString(settings.m_audioDeviceName));
}
if (channelSettingsKeys.contains("highPassFilter") || force) {
swgM17DemodSettings->setHighPassFilter(settings.m_highPassFilter ? 1 : 0);
}
if (channelSettingsKeys.contains("traceLengthMutliplier") || force) {
swgM17DemodSettings->setTraceLengthMutliplier(settings.m_traceLengthMutliplier);
}
if (channelSettingsKeys.contains("traceStroke") || force) {
swgM17DemodSettings->setTraceStroke(settings.m_traceStroke);
}
if (channelSettingsKeys.contains("traceDecay") || force) {
swgM17DemodSettings->setTraceDecay(settings.m_traceDecay);
}
if (channelSettingsKeys.contains("streamIndex") || force) {
swgM17DemodSettings->setStreamIndex(settings.m_streamIndex);
}
if (settings.m_channelMarker && (channelSettingsKeys.contains("channelMarker") || force))
{
SWGSDRangel::SWGChannelMarker *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
settings.m_channelMarker->formatTo(swgChannelMarker);
swgM17DemodSettings->setChannelMarker(swgChannelMarker);
}
if (settings.m_rollupState && (channelSettingsKeys.contains("rollupState") || force))
{
SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState();
settings.m_rollupState->formatTo(swgRollupState);
swgM17DemodSettings->setRollupState(swgRollupState);
}
}
void M17Demod::networkManagerFinished(QNetworkReply *reply)
{
QNetworkReply::NetworkError replyError = reply->error();
if (replyError)
{
qWarning() << "M17Demod::networkManagerFinished:"
<< " error(" << (int) replyError
<< "): " << replyError
<< ": " << reply->errorString();
}
else
{
QString answer = reply->readAll();
answer.chop(1); // remove last \n
qDebug("M17Demod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
}
reply->deleteLater();
}
void M17Demod::handleIndexInDeviceSetChanged(int index)
{
if (index < 0) {
return;
}
QString fifoLabel = QString("%1 [%2:%3]")
.arg(m_channelId)
.arg(m_deviceAPI->getDeviceSetIndex())
.arg(index);
m_basebandSink->setFifoLabel(fifoLabel);
m_basebandSink->setAudioFifoLabel(fifoLabel);
}

View File

@ -0,0 +1,169 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 F4EXB //
// written by Edouard Griffiths //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_M17DEMOD_H
#define INCLUDE_M17DEMOD_H
#include <vector>
#include <QNetworkRequest>
#include "dsp/basebandsamplesink.h"
#include "channel/channelapi.h"
#include "util/message.h"
#include "m17demodsettings.h"
#include "m17demodbaseband.h"
class QNetworkAccessManager;
class QNetworkReply;
class QThread;
class DownChannelizer;
class ObjectPipe;
class M17Demod : public BasebandSampleSink, public ChannelAPI {
public:
class MsgConfigureM17Demod : public Message {
MESSAGE_CLASS_DECLARATION
public:
const M17DemodSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureM17Demod* create(const M17DemodSettings& settings, bool force)
{
return new MsgConfigureM17Demod(settings, force);
}
private:
M17DemodSettings m_settings;
bool m_force;
MsgConfigureM17Demod(const M17DemodSettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
M17Demod(DeviceAPI *deviceAPI);
virtual ~M17Demod();
virtual void destroy() { delete this; }
virtual void setDeviceAPI(DeviceAPI *deviceAPI);
virtual DeviceAPI *getDeviceAPI() { return m_deviceAPI; }
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 void pushMessage(Message *msg) { m_inputMessageQueue.push(msg); }
virtual QString getSinkName() { return objectName(); }
virtual void getIdentifier(QString& id) { id = objectName(); }
virtual QString getIdentifier() const { return objectName(); }
virtual void getTitle(QString& title) { title = m_settings.m_title; }
virtual qint64 getCenterFrequency() const { return m_settings.m_inputFrequencyOffset; }
virtual void setCenterFrequency(qint64 frequency);
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 m_settings.m_inputFrequencyOffset;
}
virtual int webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage);
virtual int webapiWorkspaceGet(
SWGSDRangel::SWGWorkspaceInfo& 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 M17DemodSettings& settings);
static void webapiUpdateChannelSettings(
M17DemodSettings& settings,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response);
uint32_t getNumberOfDeviceStreams() const;
void setScopeXYSink(BasebandSampleSink* sampleSink) { m_basebandSink->setScopeXYSink(sampleSink); }
void configureMyPosition(float myLatitude, float myLongitude) { m_basebandSink->configureMyPosition(myLatitude, myLongitude); }
double getMagSq() { return m_basebandSink->getMagSq(); }
bool getSquelchOpen() const { return m_basebandSink->getSquelchOpen(); }
void getMagSqLevels(double& avg, double& peak, int& nbSamples) { m_basebandSink->getMagSqLevels(avg, peak, nbSamples); }
int getAudioSampleRate() const { return m_basebandSink->getAudioSampleRate(); }
static const char* const m_channelIdURI;
static const char* const m_channelId;
private:
DeviceAPI *m_deviceAPI;
QThread *m_thread;
M17DemodBaseband *m_basebandSink;
M17DemodSettings m_settings;
int m_basebandSampleRate; //!< stored from device message used when starting baseband sink
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
static const int m_udpBlockSize;
virtual bool handleMessage(const Message& cmd);
void applySettings(const M17DemodSettings& settings, bool force = false);
void sendSampleRateToDemodAnalyzer();
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const M17DemodSettings& settings, bool force);
void sendChannelSettings(
const QList<ObjectPipe*>& pipes,
QList<QString>& channelSettingsKeys,
const M17DemodSettings& settings,
bool force
);
void webapiFormatChannelSettings(
QList<QString>& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
const M17DemodSettings& settings,
bool force
);
private slots:
void networkManagerFinished(QNetworkReply *reply);
void handleIndexInDeviceSetChanged(int index);
};
#endif // INCLUDE_M17DEMOD_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,190 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QDebug>
#include "dsp/dspengine.h"
#include "dsp/dspcommands.h"
#include "dsp/downchannelizer.h"
#include "m17demodbaseband.h"
MESSAGE_CLASS_DEFINITION(M17DemodBaseband::MsgConfigureM17DemodBaseband, Message)
M17DemodBaseband::M17DemodBaseband() :
m_mutex(QMutex::Recursive)
{
qDebug("M17DemodBaseband::M17DemodBaseband");
m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(48000));
m_channelizer = new DownChannelizer(&m_sink);
QObject::connect(
&m_sampleFifo,
&SampleSinkFifo::dataReady,
this,
&M17DemodBaseband::handleData,
Qt::QueuedConnection
);
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(m_sink.getAudioFifo(), getInputMessageQueue());
m_sink.applyAudioSampleRate(DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate());
m_channelSampleRate = 0;
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
}
M17DemodBaseband::~M17DemodBaseband()
{
DSPEngine::instance()->getAudioDeviceManager()->removeAudioSink(m_sink.getAudioFifo());
delete m_channelizer;
}
void M17DemodBaseband::reset()
{
QMutexLocker mutexLocker(&m_mutex);
m_sampleFifo.reset();
m_channelSampleRate = 0;
}
void M17DemodBaseband::setChannel(ChannelAPI *channel)
{
m_sink.setChannel(channel);
}
void M17DemodBaseband::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
{
m_sampleFifo.write(begin, end);
}
void M17DemodBaseband::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 M17DemodBaseband::handleInputMessages()
{
Message* message;
while ((message = m_inputMessageQueue.pop()) != nullptr)
{
if (handleMessage(*message)) {
delete message;
}
}
}
bool M17DemodBaseband::handleMessage(const Message& cmd)
{
if (MsgConfigureM17DemodBaseband::match(cmd))
{
QMutexLocker mutexLocker(&m_mutex);
MsgConfigureM17DemodBaseband& cfg = (MsgConfigureM17DemodBaseband&) cmd;
qDebug() << "M17DemodBaseband::handleMessage: MsgConfigureM17DemodBaseband";
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
else if (DSPSignalNotification::match(cmd))
{
QMutexLocker mutexLocker(&m_mutex);
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
qDebug() << "M17DemodBaseband::handleMessage: DSPSignalNotification: basebandSampleRate: " << notif.getSampleRate();
m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(notif.getSampleRate()));
m_channelizer->setBasebandSampleRate(notif.getSampleRate());
m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
if (m_channelSampleRate != m_channelizer->getChannelSampleRate())
{
m_sink.applyAudioSampleRate(m_sink.getAudioSampleRate()); // reapply when channel sample rate changes
m_channelSampleRate = m_channelizer->getChannelSampleRate();
}
return true;
}
else
{
return false;
}
}
void M17DemodBaseband::applySettings(const M17DemodSettings& settings, bool force)
{
if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force)
{
m_channelizer->setChannelization(48000, settings.m_inputFrequencyOffset);
m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
if (m_channelSampleRate != m_channelizer->getChannelSampleRate())
{
m_sink.applyAudioSampleRate(m_sink.getAudioSampleRate()); // reapply when channel sample rate changes
m_channelSampleRate = m_channelizer->getChannelSampleRate();
}
}
if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force)
{
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
int audioDeviceIndex = audioDeviceManager->getOutputDeviceIndex(settings.m_audioDeviceName);
//qDebug("AMDemod::applySettings: audioDeviceName: %s audioDeviceIndex: %d", qPrintable(settings.m_audioDeviceName), audioDeviceIndex);
audioDeviceManager->removeAudioSink(m_sink.getAudioFifo());
audioDeviceManager->addAudioSink(m_sink.getAudioFifo(), getInputMessageQueue(), audioDeviceIndex);
int audioSampleRate = audioDeviceManager->getOutputSampleRate(audioDeviceIndex);
if (m_sink.getAudioSampleRate() != audioSampleRate) {
m_sink.applyAudioSampleRate(audioSampleRate);
}
}
m_sink.applySettings(settings, force);
m_settings = settings;
}
int M17DemodBaseband::getChannelSampleRate() const
{
return m_channelizer->getChannelSampleRate();
}
void M17DemodBaseband::setBasebandSampleRate(int sampleRate)
{
m_channelizer->setBasebandSampleRate(sampleRate);
m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
}

View File

@ -0,0 +1,94 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_M17DEMODBASEBAND_H
#define INCLUDE_M17DEMODBASEBAND_H
#include <QObject>
#include <QMutex>
#include "dsp/samplesinkfifo.h"
#include "util/message.h"
#include "util/messagequeue.h"
#include "m17demodsink.h"
class DownChannelizer;
class ChannelAPI;
class M17DemodBaseband : public QObject
{
Q_OBJECT
public:
class MsgConfigureM17DemodBaseband : public Message {
MESSAGE_CLASS_DECLARATION
public:
const M17DemodSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureM17DemodBaseband* create(const M17DemodSettings& settings, bool force)
{
return new MsgConfigureM17DemodBaseband(settings, force);
}
private:
M17DemodSettings m_settings;
bool m_force;
MsgConfigureM17DemodBaseband(const M17DemodSettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
M17DemodBaseband();
~M17DemodBaseband();
void reset();
void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
int getChannelSampleRate() const;
int getAudioSampleRate() const { return m_sink.getAudioSampleRate(); }
double getMagSq() { return m_sink.getMagSq(); }
void getMagSqLevels(double& avg, double& peak, int& nbSamples) { m_sink.getMagSqLevels(avg, peak, nbSamples); }
bool getSquelchOpen() const { return m_sink.getSquelchOpen(); }
void setBasebandSampleRate(int sampleRate);
void setScopeXYSink(BasebandSampleSink* scopeSink) { m_sink.setScopeXYSink(scopeSink); }
void configureMyPosition(float myLatitude, float myLongitude) { m_sink.configureMyPosition(myLatitude, myLongitude); }
void setChannel(ChannelAPI *channel);
void setFifoLabel(const QString& label) { m_sampleFifo.setLabel(label); }
void setAudioFifoLabel(const QString& label) { m_sink.setAudioFifoLabel(label); }
private:
SampleSinkFifo m_sampleFifo;
DownChannelizer *m_channelizer;
int m_channelSampleRate;
M17DemodSink m_sink;
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
M17DemodSettings m_settings;
QMutex m_mutex;
bool handleMessage(const Message& cmd);
void applySettings(const M17DemodSettings& settings, bool force = false);
private slots:
void handleInputMessages();
void handleData(); //!< Handle data when samples have to be processed
};
#endif // INCLUDE_M17DEMODBASEBAND_H

View File

@ -0,0 +1,48 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 F4EXB //
// written by Edouard Griffiths //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "m17demodbaudrates.h"
unsigned int M17DemodBaudRates::m_rates[] = {4800};
unsigned int M17DemodBaudRates::m_nb_rates = 1;
unsigned int M17DemodBaudRates::m_defaultRateIndex = 0; // 4800 bauds
unsigned int M17DemodBaudRates::getRate(unsigned int rate_index)
{
if (rate_index < m_nb_rates)
{
return m_rates[rate_index];
}
else
{
return m_rates[m_defaultRateIndex];
}
}
unsigned int M17DemodBaudRates::getRateIndex(unsigned int rate)
{
for (unsigned int i=0; i < m_nb_rates; i++)
{
if (rate == m_rates[i])
{
return i;
}
}
return m_defaultRateIndex;
}

View File

@ -0,0 +1,36 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 F4EXB //
// written by Edouard Griffiths //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_CHANNELRX_DEMODM17_M17DEMODBAUDRATES_H_
#define PLUGINS_CHANNELRX_DEMODM17_M17DEMODBAUDRATES_H_
class M17DemodBaudRates
{
public:
static unsigned int getRate(unsigned int rate_index);
static unsigned int getRateIndex(unsigned int rate);
static unsigned int getDefaultRate() { return m_rates[m_defaultRateIndex]; }
static unsigned int getDefaultRateIndex() { return m_defaultRateIndex; }
static unsigned int getNbRates() { return m_nb_rates; }
private:
static unsigned int m_nb_rates;
static unsigned int m_rates[2];
static unsigned int m_defaultRateIndex;
};
#endif /* PLUGINS_CHANNELRX_DEMODM17_M17DEMODBAUDRATES_H_ */

View File

@ -0,0 +1,571 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 F4EXB //
// written by Edouard Griffiths //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QDockWidget>
#include <QMainWindow>
#include <QDebug>
#include <complex>
#include "device/deviceuiset.h"
#include "dsp/scopevisxy.h"
#include "dsp/dspcommands.h"
#include "plugin/pluginapi.h"
#include "util/simpleserializer.h"
#include "util/db.h"
#include "gui/basicchannelsettingsdialog.h"
#include "gui/devicestreamselectiondialog.h"
#include "gui/crightclickenabler.h"
#include "gui/audioselectdialog.h"
#include "dsp/dspengine.h"
#include "maincore.h"
#include "m17demod.h"
#include "m17demodbaudrates.h"
#include "ui_m17demodgui.h"
#include "m17demodgui.h"
M17DemodGUI* M17DemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
{
M17DemodGUI* gui = new M17DemodGUI(pluginAPI, deviceUISet, rxChannel);
return gui;
}
void M17DemodGUI::destroy()
{
delete this;
}
void M17DemodGUI::resetToDefaults()
{
m_settings.resetToDefaults();
blockApplySettings(true);
displaySettings();
blockApplySettings(false);
applySettings();
}
QByteArray M17DemodGUI::serialize() const
{
return m_settings.serialize();
}
bool M17DemodGUI::deserialize(const QByteArray& data)
{
if (m_settings.deserialize(data))
{
displaySettings();
applySettings(true);
return true;
}
else
{
resetToDefaults();
return false;
}
}
void M17DemodGUI::resizeEvent(QResizeEvent* size)
{
int maxWidth = getRollupContents()->maximumWidth();
int minHeight = getRollupContents()->minimumHeight() + getAdditionalHeight();
resize(width() < maxWidth ? width() : maxWidth, minHeight);
size->accept();
}
bool M17DemodGUI::handleMessage(const Message& message)
{
if (M17Demod::MsgConfigureM17Demod::match(message))
{
qDebug("M17DemodGUI::handleMessage: M17Demod::MsgConfigureM17Demod");
const M17Demod::MsgConfigureM17Demod& cfg = (M17Demod::MsgConfigureM17Demod&) message;
m_settings = cfg.getSettings();
blockApplySettings(true);
m_channelMarker.updateSettings(static_cast<const ChannelMarker*>(m_settings.m_channelMarker));
displaySettings();
blockApplySettings(false);
return true;
}
else if (DSPSignalNotification::match(message))
{
DSPSignalNotification& notif = (DSPSignalNotification&) message;
m_deviceCenterFrequency = notif.getCenterFrequency();
m_basebandSampleRate = notif.getSampleRate();
ui->deltaFrequency->setValueRange(false, 7, -m_basebandSampleRate/2, m_basebandSampleRate/2);
ui->deltaFrequencyLabel->setToolTip(tr("Range %1 %L2 Hz").arg(QChar(0xB1)).arg(m_basebandSampleRate/2));
updateAbsoluteCenterFrequency();
return true;
}
else
{
return false;
}
}
void M17DemodGUI::handleInputMessages()
{
Message* message;
while ((message = getInputMessageQueue()->pop()) != 0)
{
if (handleMessage(*message))
{
delete message;
}
}
}
void M17DemodGUI::on_deltaFrequency_changed(qint64 value)
{
m_channelMarker.setCenterFrequency(value);
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
updateAbsoluteCenterFrequency();
applySettings();
}
void M17DemodGUI::on_rfBW_valueChanged(int value)
{
m_channelMarker.setBandwidth(value * 100);
m_settings.m_rfBandwidth = value * 100.0;
ui->rfBWText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1));
applySettings();
}
void M17DemodGUI::on_demodGain_valueChanged(int value)
{
m_settings.m_demodGain = value / 100.0;
ui->demodGainText->setText(QString("%1").arg(value / 100.0, 0, 'f', 2));
applySettings();
}
void M17DemodGUI::on_fmDeviation_valueChanged(int value)
{
m_settings.m_fmDeviation = value * 100.0;
ui->fmDeviationText->setText(QString("%1%2k").arg(QChar(0xB1, 0x00)).arg(value / 10.0, 0, 'f', 1));
applySettings();
}
void M17DemodGUI::on_volume_valueChanged(int value)
{
m_settings.m_volume= value / 10.0;
ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
applySettings();
}
void M17DemodGUI::on_baudRate_currentIndexChanged(int index)
{
m_settings.m_baudRate = M17DemodBaudRates::getRate(index);
applySettings();
}
void M17DemodGUI::on_syncOrConstellation_toggled(bool checked)
{
m_settings.m_syncOrConstellation = checked;
applySettings();
}
void M17DemodGUI::on_traceLength_valueChanged(int value)
{
m_settings.m_traceLengthMutliplier = value;
ui->traceLengthText->setText(QString("%1").arg(m_settings.m_traceLengthMutliplier*50));
m_scopeVisXY->setPixelsPerFrame(m_settings.m_traceLengthMutliplier*960); // 48000 / 50. Chunks of 50 ms.
}
void M17DemodGUI::on_traceStroke_valueChanged(int value)
{
m_settings.m_traceStroke = value;
ui->traceStrokeText->setText(QString("%1").arg(m_settings.m_traceStroke));
m_scopeVisXY->setStroke(m_settings.m_traceStroke);
}
void M17DemodGUI::on_traceDecay_valueChanged(int value)
{
m_settings.m_traceDecay = value;
ui->traceDecayText->setText(QString("%1").arg(m_settings.m_traceDecay));
m_scopeVisXY->setDecay(m_settings.m_traceDecay);
}
void M17DemodGUI::on_squelchGate_valueChanged(int value)
{
m_settings.m_squelchGate = value;
ui->squelchGateText->setText(QString("%1").arg(value * 10.0, 0, 'f', 0));
applySettings();
}
void M17DemodGUI::on_squelch_valueChanged(int value)
{
ui->squelchText->setText(QString("%1").arg(value / 1.0, 0, 'f', 0));
m_settings.m_squelch = value;
applySettings();
}
void M17DemodGUI::on_audioMute_toggled(bool checked)
{
m_settings.m_audioMute = checked;
applySettings();
}
void M17DemodGUI::on_highPassFilter_toggled(bool checked)
{
m_settings.m_highPassFilter = checked;
applySettings();
}
void M17DemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
(void) widget;
(void) rollDown;
getRollupContents()->saveState(m_rollupState);
applySettings();
}
void M17DemodGUI::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.setDefaultTitle(m_displayedName);
if (m_deviceUISet->m_deviceMIMOEngine)
{
dialog.setNumberOfStreams(m_m17Demod->getNumberOfDeviceStreams());
dialog.setStreamIndex(m_settings.m_streamIndex);
}
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);
setTitle(m_channelMarker.getTitle());
setTitleColor(m_settings.m_rgbColor);
if (m_deviceUISet->m_deviceMIMOEngine)
{
m_settings.m_streamIndex = dialog.getSelectedStreamIndex();
m_channelMarker.clearStreamIndexes();
m_channelMarker.addStreamIndex(m_settings.m_streamIndex);
updateIndexLabel();
}
applySettings();
}
resetContextMenuType();
}
void M17DemodGUI::on_viewStatusLog_clicked()
{
qDebug("M17DemodGUI::on_viewStatusLog_clicked");
m_m17StatusTextDialog.exec();
}
M17DemodGUI::M17DemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent) :
ChannelGUI(parent),
ui(new Ui::M17DemodGUI),
m_pluginAPI(pluginAPI),
m_deviceUISet(deviceUISet),
m_channelMarker(this),
m_deviceCenterFrequency(0),
m_basebandSampleRate(1),
m_doApplySettings(true),
m_enableCosineFiltering(false),
m_syncOrConstellation(false),
m_slot1On(false),
m_slot2On(false),
m_tdmaStereo(false),
m_squelchOpen(false),
m_audioSampleRate(-1),
m_tickCount(0)
{
setAttribute(Qt::WA_DeleteOnClose, true);
m_helpURL = "plugins/channelrx/demodm17/readme.md";
RollupContents *rollupContents = getRollupContents();
ui->setupUi(rollupContents);
setSizePolicy(rollupContents->sizePolicy());
rollupContents->arrangeRollups();
connect(rollupContents, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
ui->screenTV->setColor(true);
ui->screenTV->resizeTVScreen(200,200);
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->audioMute);
connect(audioMuteRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect()));
m_scopeVisXY = new ScopeVisXY(ui->screenTV);
m_scopeVisXY->setScale(2.0);
m_scopeVisXY->setPixelsPerFrame(4001);
m_scopeVisXY->setPlotRGB(qRgb(0, 220, 250));
m_scopeVisXY->setGridRGB(qRgb(255, 255, 128));
for (float x = -0.84; x < 1.0; x += 0.56)
{
for (float y = -0.84; y < 1.0; y += 0.56)
{
m_scopeVisXY->addGraticulePoint(std::complex<float>(x, y));
}
}
m_scopeVisXY->calculateGraticule(200,200);
m_m17Demod = (M17Demod*) rxChannel;
m_m17Demod->setScopeXYSink(m_scopeVisXY);
m_m17Demod->setMessageQueueToGUI(getInputMessageQueue());
connect(&MainCore::instance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
ui->audioMute->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
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::cyan);
m_channelMarker.setBandwidth(10000);
m_channelMarker.setCenterFrequency(0);
m_channelMarker.setTitle("M17 Demodulator");
m_channelMarker.blockSignals(false);
m_channelMarker.setVisible(true); // activate signal on the last setting only
m_deviceUISet->addChannelMarker(&m_channelMarker);
connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor()));
connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor()));
m_settings.setChannelMarker(&m_channelMarker);
m_settings.setRollupState(&m_rollupState);
updateMyPosition();
displaySettings();
makeUIConnections();
applySettings(true);
}
M17DemodGUI::~M17DemodGUI()
{
delete m_scopeVisXY;
ui->screenTV->setParent(nullptr); // Prefer memory leak to core dump... ~TVScreen() is buggy
delete ui;
}
void M17DemodGUI::updateMyPosition()
{
float latitude = MainCore::instance()->getSettings().getLatitude();
float longitude = MainCore::instance()->getSettings().getLongitude();
if ((m_myLatitude != latitude) || (m_myLongitude != longitude))
{
m_m17Demod->configureMyPosition(latitude, longitude);
m_myLatitude = latitude;
m_myLongitude = longitude;
}
}
void M17DemodGUI::displaySettings()
{
m_channelMarker.blockSignals(true);
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
m_channelMarker.setColor(m_settings.m_rgbColor);
m_channelMarker.setTitle(m_settings.m_title);
m_channelMarker.blockSignals(false);
setTitleColor(m_settings.m_rgbColor); // activate signal on the last setting only
setTitleColor(m_settings.m_rgbColor);
setWindowTitle(m_channelMarker.getTitle());
setTitle(m_channelMarker.getTitle());
blockApplySettings(true);
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
ui->rfBW->setValue(m_settings.m_rfBandwidth / 100.0);
ui->rfBWText->setText(QString("%1k").arg(ui->rfBW->value() / 10.0, 0, 'f', 1));
ui->fmDeviation->setValue(m_settings.m_fmDeviation / 100.0);
ui->fmDeviationText->setText(QString("%1%2k").arg(QChar(0xB1, 0x00)).arg(ui->fmDeviation->value() / 10.0, 0, 'f', 1));
ui->squelch->setValue(m_settings.m_squelch);
ui->squelchText->setText(QString("%1").arg(ui->squelch->value() / 1.0, 0, 'f', 0));
ui->squelchGate->setValue(m_settings.m_squelchGate);
ui->squelchGateText->setText(QString("%1").arg(ui->squelchGate->value() * 10.0, 0, 'f', 0));
ui->demodGain->setValue(m_settings.m_demodGain * 100.0);
ui->demodGainText->setText(QString("%1").arg(ui->demodGain->value() / 100.0, 0, 'f', 2));
ui->volume->setValue(m_settings.m_volume * 10.0);
ui->volumeText->setText(QString("%1").arg(ui->volume->value() / 10.0, 0, 'f', 1));
ui->syncOrConstellation->setChecked(m_settings.m_syncOrConstellation);
ui->audioMute->setChecked(m_settings.m_audioMute);
ui->highPassFilter->setChecked(m_settings.m_highPassFilter);
ui->baudRate->setCurrentIndex(M17DemodBaudRates::getRateIndex(m_settings.m_baudRate));
ui->traceLength->setValue(m_settings.m_traceLengthMutliplier);
ui->traceLengthText->setText(QString("%1").arg(m_settings.m_traceLengthMutliplier*50));
m_scopeVisXY->setPixelsPerFrame(m_settings.m_traceLengthMutliplier*960); // 48000 / 50. Chunks of 50 ms.
ui->traceStroke->setValue(m_settings.m_traceStroke);
ui->traceStrokeText->setText(QString("%1").arg(m_settings.m_traceStroke));
m_scopeVisXY->setStroke(m_settings.m_traceStroke);
ui->traceDecay->setValue(m_settings.m_traceDecay);
ui->traceDecayText->setText(QString("%1").arg(m_settings.m_traceDecay));
m_scopeVisXY->setDecay(m_settings.m_traceDecay);
updateIndexLabel();
getRollupContents()->restoreState(m_rollupState);
updateAbsoluteCenterFrequency();
blockApplySettings(false);
}
void M17DemodGUI::applySettings(bool force)
{
if (m_doApplySettings)
{
qDebug() << "M17DemodGUI::applySettings";
M17Demod::MsgConfigureM17Demod* message = M17Demod::MsgConfigureM17Demod::create( m_settings, force);
m_m17Demod->getInputMessageQueue()->push(message);
}
}
void M17DemodGUI::leaveEvent(QEvent* event)
{
m_channelMarker.setHighlighted(false);
ChannelGUI::leaveEvent(event);
}
void M17DemodGUI::enterEvent(QEvent* event)
{
m_channelMarker.setHighlighted(true);
ChannelGUI::enterEvent(event);
}
void M17DemodGUI::blockApplySettings(bool block)
{
m_doApplySettings = !block;
}
void M17DemodGUI::channelMarkerChangedByCursor()
{
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
applySettings();
}
void M17DemodGUI::channelMarkerHighlightedByCursor()
{
setHighlighted(m_channelMarker.getHighlighted());
}
void M17DemodGUI::audioSelect()
{
qDebug("M17DemodGUI::audioSelect");
AudioSelectDialog audioSelect(DSPEngine::instance()->getAudioDeviceManager(), m_settings.m_audioDeviceName);
audioSelect.exec();
if (audioSelect.m_selected)
{
m_settings.m_audioDeviceName = audioSelect.m_audioDeviceName;
applySettings();
}
}
void M17DemodGUI::tick()
{
double magsqAvg, magsqPeak;
int nbMagsqSamples;
m_m17Demod->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(tr("%1 dB").arg(powDbAvg, 0, 'f', 1));
}
int audioSampleRate = m_m17Demod->getAudioSampleRate();
bool squelchOpen = m_m17Demod->getSquelchOpen();
if ((audioSampleRate != m_audioSampleRate) || (squelchOpen != m_squelchOpen))
{
if (audioSampleRate < 0) {
ui->audioMute->setStyleSheet("QToolButton { background-color : red; }");
} else if (squelchOpen) {
ui->audioMute->setStyleSheet("QToolButton { background-color : green; }");
} else {
ui->audioMute->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
}
m_audioSampleRate = audioSampleRate;
m_squelchOpen = squelchOpen;
}
m_tickCount++;
}
void M17DemodGUI::makeUIConnections()
{
QObject::connect(ui->deltaFrequency, &ValueDialZ::changed, this, &M17DemodGUI::on_deltaFrequency_changed);
QObject::connect(ui->rfBW, &QSlider::valueChanged, this, &M17DemodGUI::on_rfBW_valueChanged);
QObject::connect(ui->demodGain, &QSlider::valueChanged, this, &M17DemodGUI::on_demodGain_valueChanged);
QObject::connect(ui->volume, &QDial::valueChanged, this, &M17DemodGUI::on_volume_valueChanged);
QObject::connect(ui->baudRate, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &M17DemodGUI::on_baudRate_currentIndexChanged);
QObject::connect(ui->syncOrConstellation, &QToolButton::toggled, this, &M17DemodGUI::on_syncOrConstellation_toggled);
QObject::connect(ui->traceLength, &QDial::valueChanged, this, &M17DemodGUI::on_traceLength_valueChanged);
QObject::connect(ui->traceStroke, &QDial::valueChanged, this, &M17DemodGUI::on_traceStroke_valueChanged);
QObject::connect(ui->traceDecay, &QDial::valueChanged, this, &M17DemodGUI::on_traceDecay_valueChanged);
QObject::connect(ui->fmDeviation, &QSlider::valueChanged, this, &M17DemodGUI::on_fmDeviation_valueChanged);
QObject::connect(ui->squelchGate, &QDial::valueChanged, this, &M17DemodGUI::on_squelchGate_valueChanged);
QObject::connect(ui->squelch, &QDial::valueChanged, this, &M17DemodGUI::on_squelch_valueChanged);
QObject::connect(ui->highPassFilter, &ButtonSwitch::toggled, this, &M17DemodGUI::on_highPassFilter_toggled);
QObject::connect(ui->audioMute, &QToolButton::toggled, this, &M17DemodGUI::on_audioMute_toggled);
QObject::connect(ui->viewStatusLog, &QPushButton::clicked, this, &M17DemodGUI::on_viewStatusLog_clicked);
}
void M17DemodGUI::updateAbsoluteCenterFrequency()
{
setStatusFrequency(m_deviceCenterFrequency + m_settings.m_inputFrequencyOffset);
}

View File

@ -0,0 +1,142 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 F4EXB //
// written by Edouard Griffiths //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_M17DEMODGUI_H
#define INCLUDE_M17DEMODGUI_H
#include <QMenu>
#include "channel/channelgui.h"
#include "dsp/dsptypes.h"
#include "dsp/channelmarker.h"
#include "dsp/movingaverage.h"
#include "util/messagequeue.h"
#include "settings/rollupstate.h"
#include "m17demodsettings.h"
#include "m17statustextdialog.h"
class PluginAPI;
class DeviceUISet;
class BasebandSampleSink;
class ScopeVisXY;
class M17Demod;
namespace Ui {
class M17DemodGUI;
}
class M17DemodGUI : public ChannelGUI {
Q_OBJECT
public:
static M17DemodGUI* 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; }
virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; };
virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; };
virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; };
virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; };
virtual QString getTitle() const { return m_settings.m_title; };
virtual QColor getTitleColor() const { return m_settings.m_rgbColor; };
virtual void zetHidden(bool hidden) { m_settings.m_hidden = hidden; }
virtual bool getHidden() const { return m_settings.m_hidden; }
virtual ChannelMarker& getChannelMarker() { return m_channelMarker; }
virtual int getStreamIndex() const { return m_settings.m_streamIndex; }
virtual void setStreamIndex(int streamIndex) { m_settings.m_streamIndex = streamIndex; }
public slots:
void channelMarkerChangedByCursor();
void channelMarkerHighlightedByCursor();
protected:
void resizeEvent(QResizeEvent* size);
private:
Ui::M17DemodGUI* ui;
PluginAPI* m_pluginAPI;
DeviceUISet* m_deviceUISet;
ChannelMarker m_channelMarker;
RollupState m_rollupState;
M17DemodSettings m_settings;
qint64 m_deviceCenterFrequency;
int m_basebandSampleRate;
bool m_doApplySettings;
ScopeVisXY* m_scopeVisXY;
M17Demod* m_m17Demod;
bool m_enableCosineFiltering;
bool m_syncOrConstellation;
bool m_slot1On;
bool m_slot2On;
bool m_tdmaStereo;
bool m_audioMute;
bool m_squelchOpen;
int m_audioSampleRate;
uint32_t m_tickCount;
float m_myLatitude;
float m_myLongitude;
MessageQueue m_inputMessageQueue;
M17StatusTextDialog m_m17StatusTextDialog;
explicit M17DemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = nullptr);
virtual ~M17DemodGUI();
void blockApplySettings(bool block);
void applySettings(bool force = false);
void displaySettings();
void updateAMBEFeaturesList();
void updateMyPosition();
bool handleMessage(const Message& message);
void makeUIConnections();
void updateAbsoluteCenterFrequency();
void leaveEvent(QEvent*);
void enterEvent(QEvent*);
private slots:
void on_deltaFrequency_changed(qint64 value);
void on_rfBW_valueChanged(int index);
void on_demodGain_valueChanged(int value);
void on_volume_valueChanged(int value);
void on_baudRate_currentIndexChanged(int index);
void on_syncOrConstellation_toggled(bool checked);
void on_traceLength_valueChanged(int value);
void on_traceStroke_valueChanged(int value);
void on_traceDecay_valueChanged(int value);
void on_fmDeviation_valueChanged(int value);
void on_squelchGate_valueChanged(int value);
void on_squelch_valueChanged(int value);
void on_highPassFilter_toggled(bool checked);
void on_audioMute_toggled(bool checked);
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDialogCalled(const QPoint& p);
void on_viewStatusLog_clicked();
void handleInputMessages();
void audioSelect();
void tick();
};
#endif // INCLUDE_DSDDEMODGUI_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,94 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 F4EXB //
// written by Edouard Griffiths //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "m17demodplugin.h"
#include <QtPlugin>
#include "plugin/pluginapi.h"
#ifndef SERVER_MODE
#include "m17demodgui.h"
#endif
#include "m17demod.h"
#include "m17demodwebapiadapter.h"
#include "m17demodplugin.h"
const PluginDescriptor M17DemodPlugin::m_pluginDescriptor = {
M17Demod::m_channelId,
QStringLiteral("M17 Demodulator"),
QStringLiteral("7.4.0"),
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,
QStringLiteral("https://github.com/f4exb/sdrangel")
};
M17DemodPlugin::M17DemodPlugin(QObject* parent) :
QObject(parent),
m_pluginAPI(nullptr)
{
}
const PluginDescriptor& M17DemodPlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void M17DemodPlugin::initPlugin(PluginAPI* pluginAPI)
{
m_pluginAPI = pluginAPI;
// register DSD demodulator
m_pluginAPI->registerRxChannel(M17Demod::m_channelIdURI, M17Demod::m_channelId, this);
}
void M17DemodPlugin::createRxChannel(DeviceAPI *deviceAPI, BasebandSampleSink **bs, ChannelAPI **cs) const
{
if (bs || cs)
{
M17Demod *instance = new M17Demod(deviceAPI);
if (bs) {
*bs = instance;
}
if (cs) {
*cs = instance;
}
}
}
#ifdef SERVER_MODE
ChannelGUI* M17DemodPlugin::createRxChannelGUI(
DeviceUISet *deviceUISet,
BasebandSampleSink *rxChannel) const
{
(void) deviceUISet;
(void) rxChannel;
return nullptr;
}
#else
ChannelGUI* M17DemodPlugin::createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) const
{
return M17DemodGUI::create(m_pluginAPI, deviceUISet, rxChannel);
}
#endif
ChannelWebAPIAdapter* M17DemodPlugin::createChannelWebAPIAdapter() const
{
return new M17DemodWebAPIAdapter();
}

View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 F4EXB //
// written by Edouard Griffiths //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_M17DEMODLUGIN_H
#define INCLUDE_M17DEMODLUGIN_H
#include <QObject>
#include "plugin/plugininterface.h"
class DeviceUISet;
class BasebandSampleSink;
class M17DemodPlugin : public QObject, PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID "sdrangel.channel.m17demod")
public:
explicit M17DemodPlugin(QObject* parent = nullptr);
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_M17DEMODLUGIN_H

View File

@ -0,0 +1,188 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 Edouard Griffiths, F4EXB. //
// //
// This program is free som_udpCopyAudioftware; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QColor>
#include "dsp/dspengine.h"
#include "util/simpleserializer.h"
#include "settings/serializable.h"
#include "m17demodsettings.h"
M17DemodSettings::M17DemodSettings() :
m_channelMarker(nullptr),
m_rollupState(nullptr)
{
resetToDefaults();
}
void M17DemodSettings::resetToDefaults()
{
m_inputFrequencyOffset = 0;
m_rfBandwidth = 12500.0;
m_fmDeviation = 3500.0;
m_demodGain = 1.0;
m_volume = 2.0;
m_baudRate = 4800;
m_squelchGate = 5; // 10s of ms at 48000 Hz sample rate. Corresponds to 2400 for AGC attack
m_squelch = -40.0;
m_audioMute = false;
m_syncOrConstellation = false;
m_rgbColor = QColor(255, 0, 255).rgb();
m_title = "M17 Demodulator";
m_highPassFilter = false;
m_traceLengthMutliplier = 6; // 300 ms
m_traceStroke = 100;
m_traceDecay = 200;
m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName;
m_streamIndex = 0;
m_useReverseAPI = false;
m_reverseAPIAddress = "127.0.0.1";
m_reverseAPIPort = 8888;
m_reverseAPIDeviceIndex = 0;
m_reverseAPIChannelIndex = 0;
m_workspaceIndex = 0;
m_hidden = false;
}
QByteArray M17DemodSettings::serialize() const
{
SimpleSerializer s(1);
s.writeS32(1, m_inputFrequencyOffset);
s.writeS32(2, m_rfBandwidth/100.0);
s.writeS32(3, m_demodGain*100.0);
s.writeS32(4, m_fmDeviation/100.0);
s.writeS32(5, m_squelch);
s.writeU32(7, m_rgbColor);
s.writeS32(8, m_squelchGate);
s.writeS32(9, m_volume*10.0);
s.writeS32(11, m_baudRate);
s.writeBool(13, m_syncOrConstellation);
if (m_channelMarker) {
s.writeBlob(17, m_channelMarker->serialize());
}
s.writeString(18, m_title);
s.writeBool(19, m_highPassFilter);
s.writeString(20, m_audioDeviceName);
s.writeS32(21, m_traceLengthMutliplier);
s.writeS32(22, m_traceStroke);
s.writeS32(23, m_traceDecay);
s.writeBool(24, m_useReverseAPI);
s.writeString(25, m_reverseAPIAddress);
s.writeU32(26, m_reverseAPIPort);
s.writeU32(27, m_reverseAPIDeviceIndex);
s.writeU32(28, m_reverseAPIChannelIndex);
s.writeBool(29, m_audioMute);
s.writeS32(30, m_streamIndex);
if (m_rollupState) {
s.writeBlob(31, m_rollupState->serialize());
}
s.writeS32(32, m_workspaceIndex);
s.writeBlob(33, m_geometryBytes);
s.writeBool(34, m_hidden);
return s.final();
}
bool M17DemodSettings::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if (!d.isValid())
{
resetToDefaults();
return false;
}
if (d.getVersion() == 1)
{
QByteArray bytetmp;
QString strtmp;
qint32 tmp;
uint32_t utmp;
if (m_channelMarker)
{
d.readBlob(17, &bytetmp);
m_channelMarker->deserialize(bytetmp);
}
d.readS32(1, &tmp, 0);
m_inputFrequencyOffset = tmp;
d.readS32(2, &tmp, 125);
m_rfBandwidth = tmp * 100.0;
d.readS32(3, &tmp, 125);
m_demodGain = tmp / 100.0;
d.readS32(4, &tmp, 50);
m_fmDeviation = tmp * 100.0;
d.readS32(5, &tmp, -40);
m_squelch = tmp < -100 ? tmp / 10.0 : tmp;
d.readU32(7, &m_rgbColor);
d.readS32(8, &m_squelchGate, 5);
d.readS32(9, &tmp, 20);
m_volume = tmp / 10.0;
d.readS32(11, &m_baudRate, 4800);
d.readBool(13, &m_syncOrConstellation, false);
d.readString(18, &m_title, "M17 Demodulator");
d.readBool(19, &m_highPassFilter, false);
d.readString(20, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName);
d.readS32(21, &tmp, 6);
m_traceLengthMutliplier = tmp < 2 ? 2 : tmp > 30 ? 30 : tmp;
d.readS32(22, &tmp, 100);
m_traceStroke = tmp < 0 ? 0 : tmp > 255 ? 255 : tmp;
d.readS32(23, &tmp, 200);
m_traceDecay = tmp < 0 ? 0 : tmp > 255 ? 255 : tmp;
d.readBool(24, &m_useReverseAPI, false);
d.readString(25, &m_reverseAPIAddress, "127.0.0.1");
d.readU32(26, &utmp, 0);
if ((utmp > 1023) && (utmp < 65535)) {
m_reverseAPIPort = utmp;
} else {
m_reverseAPIPort = 8888;
}
d.readU32(27, &utmp, 0);
m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp;
d.readU32(28, &utmp, 0);
m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp;
d.readBool(29, &m_audioMute, false);
d.readS32(30, &m_streamIndex, 0);
if (m_rollupState)
{
d.readBlob(31, &bytetmp);
m_rollupState->deserialize(bytetmp);
}
d.readS32(32, &m_workspaceIndex, 0);
d.readBlob(33, &m_geometryBytes);
d.readBool(34, &m_hidden, false);
return true;
}
else
{
resetToDefaults();
return false;
}
}

View File

@ -0,0 +1,69 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_CHANNELRX_DEMODM17_M17DEMODSETTINGS_H_
#define PLUGINS_CHANNELRX_DEMODM17_M17DEMODSETTINGS_H_
#include <QByteArray>
#include <QString>
#include <dsp/dsptypes.h>
class Serializable;
struct M17DemodSettings
{
qint64 m_inputFrequencyOffset;
Real m_rfBandwidth;
Real m_fmDeviation;
Real m_demodGain;
Real m_volume;
int m_baudRate;
int m_squelchGate;
Real m_squelch;
bool m_audioMute;
bool m_syncOrConstellation;
quint32 m_rgbColor;
QString m_title;
bool m_highPassFilter;
int m_traceLengthMutliplier; // x 50ms
int m_traceStroke; // [0..255]
int m_traceDecay; // [0..255]
QString m_audioDeviceName;
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;
int m_workspaceIndex;
QByteArray m_geometryBytes;
bool m_hidden;
Serializable *m_channelMarker;
Serializable *m_rollupState;
M17DemodSettings();
void resetToDefaults();
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; }
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
};
#endif /* PLUGINS_CHANNELRX_DEMODM17_M17DEMODSETTINGS_H_ */

View File

@ -0,0 +1,397 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <string.h>
#include <stdio.h>
#include <complex.h>
#include <QTime>
#include <QDebug>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QBuffer>
#include "SWGChannelSettings.h"
#include "SWGDSDDemodSettings.h"
#include "SWGChannelReport.h"
#include "SWGDSDDemodReport.h"
#include "dsp/dspengine.h"
#include "dsp/basebandsamplesink.h"
#include "dsp/datafifo.h"
#include "dsp/dspcommands.h"
#include "feature/feature.h"
#include "audio/audiooutputdevice.h"
#include "util/db.h"
#include "util/messagequeue.h"
#include "maincore.h"
#include "m17demodsink.h"
M17DemodSink::M17DemodSink() :
m_channelSampleRate(48000),
m_channelFrequencyOffset(0),
m_audioSampleRate(48000),
m_interpolatorDistance(0.0f),
m_interpolatorDistanceRemain(0.0f),
m_sampleCount(0),
m_squelchCount(0),
m_squelchGate(0),
m_squelchLevel(1e-4),
m_squelchOpen(false),
m_squelchDelayLine(24000),
m_audioFifo(48000),
m_scopeXY(nullptr),
m_scopeEnabled(true)
{
m_audioBuffer.resize(1<<14);
m_audioBufferFill = 0;
m_demodBuffer.resize(1<<12);
m_demodBufferFill = 0;
m_sampleBuffer = new FixReal[1<<17]; // 128 kS
m_sampleBufferIndex = 0;
m_scaleFromShort = SDR_RX_SAMP_SZ < sizeof(short)*8 ? 1 : 1<<(SDR_RX_SAMP_SZ - sizeof(short)*8);
m_magsq = 0.0f;
m_magsqSum = 0.0f;
m_magsqPeak = 0.0f;
m_magsqCount = 0;
applySettings(m_settings, true);
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
}
M17DemodSink::~M17DemodSink()
{
delete[] m_sampleBuffer;
}
void M17DemodSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
{
Complex ci;
int samplesPerSymbol = 10;
m_scopeSampleBuffer.clear();
for (SampleVector::const_iterator it = begin; it != end; ++it)
{
Complex c(it->real(), it->imag());
c *= m_nco.nextIQ();
if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci))
{
FixReal sample, delayedSample;
qint16 sampleM17;
Real re = ci.real() / SDR_RX_SCALED;
Real im = ci.imag() / SDR_RX_SCALED;
Real magsq = re*re + im*im;
m_movingAverage(magsq);
m_magsqSum += magsq;
if (magsq > m_magsqPeak)
{
m_magsqPeak = magsq;
}
m_magsqCount++;
Real demod = m_phaseDiscri.phaseDiscriminator(ci) * m_settings.m_demodGain; // [-1.0:1.0]
m_sampleCount++;
// AF processing
if (m_movingAverage.asDouble() > m_squelchLevel)
{
if (m_squelchGate > 0)
{
if (m_squelchCount < m_squelchGate*2) {
m_squelchCount++;
}
m_squelchDelayLine.write(demod);
m_squelchOpen = m_squelchCount > m_squelchGate;
}
else
{
m_squelchOpen = true;
}
}
else
{
if (m_squelchGate > 0)
{
if (m_squelchCount > 0) {
m_squelchCount--;
}
m_squelchDelayLine.write(0);
m_squelchOpen = m_squelchCount > m_squelchGate;
}
else
{
m_squelchOpen = false;
}
}
if (m_squelchOpen)
{
if (m_squelchGate > 0)
{
sampleM17 = m_squelchDelayLine.readBack(m_squelchGate) * 32768.0f; // DSD decoder takes int16 samples
sample = m_squelchDelayLine.readBack(m_squelchGate) * SDR_RX_SCALEF; // scale to sample size
}
else
{
sampleM17 = demod * 32768.0f; // M17 decoder takes int16 samples
sample = demod * SDR_RX_SCALEF; // scale to sample size
}
}
else
{
sampleM17 = 0;
sample = 0;
}
// m_dsdDecoder.pushSample(sampleM17);
m_demodBuffer[m_demodBufferFill] = sampleM17;
++m_demodBufferFill;
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataPipes.size() > 0)
{
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo) {
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}
}
m_demodBufferFill = 0;
}
// if (m_settings.m_enableCosineFiltering) { // show actual input to FSK demod
// sample = m_dsdDecoder.getFilteredSample() * m_scaleFromShort;
// }
if (m_sampleBufferIndex < (1<<17)-1) {
m_sampleBufferIndex++;
} else {
m_sampleBufferIndex = 0;
}
m_sampleBuffer[m_sampleBufferIndex] = sample;
if (m_sampleBufferIndex < samplesPerSymbol) {
delayedSample = m_sampleBuffer[(1<<17) - samplesPerSymbol + m_sampleBufferIndex]; // wrap
} else {
delayedSample = m_sampleBuffer[m_sampleBufferIndex - samplesPerSymbol];
}
// if (m_settings.m_syncOrConstellation)
// {
// Sample s(sample, m_dsdDecoder.getSymbolSyncSample() * m_scaleFromShort * 0.84);
// m_scopeSampleBuffer.push_back(s);
// }
// else
// {
Sample s(sample, delayedSample); // I=signal, Q=signal delayed by 20 samples (2400 baud: lowest rate)
m_scopeSampleBuffer.push_back(s);
// }
m_interpolatorDistanceRemain += m_interpolatorDistance;
}
}
// if (!m_ambeFeature)
// {
// if (m_settings.m_slot1On)
// {
// int nbAudioSamples;
// short *dsdAudio = m_dsdDecoder.getAudio1(nbAudioSamples);
// if (nbAudioSamples > 0)
// {
// if (!m_settings.m_audioMute) {
// m_audioFifo1.write((const quint8*) dsdAudio, nbAudioSamples);
// }
// m_dsdDecoder.resetAudio1();
// }
// }
// if (m_settings.m_slot2On)
// {
// int nbAudioSamples;
// short *dsdAudio = m_dsdDecoder.getAudio2(nbAudioSamples);
// if (nbAudioSamples > 0)
// {
// if (!m_settings.m_audioMute) {
// m_audioFifo2.write((const quint8*) dsdAudio, nbAudioSamples);
// }
// m_dsdDecoder.resetAudio2();
// }
// }
// }
if ((m_scopeXY != nullptr) && (m_scopeEnabled))
{
m_scopeXY->feed(m_scopeSampleBuffer.begin(), m_scopeSampleBuffer.end(), true); // true = real samples for what it's worth
}
}
void M17DemodSink::applyAudioSampleRate(int sampleRate)
{
if (sampleRate < 0)
{
qWarning("M17DemodSink::applyAudioSampleRate: invalid sample rate: %d", sampleRate);
return;
}
int upsampling = sampleRate / 8000;
qDebug("M17DemodSink::applyAudioSampleRate: audio rate: %d upsample by %d", sampleRate, upsampling);
if (sampleRate % 8000 != 0) {
qDebug("M17DemodSink::applyAudioSampleRate: audio will sound best with sample rates that are integer multiples of 8 kS/s");
}
// m_dsdDecoder.setUpsampling(upsampling);
m_audioSampleRate = sampleRate;
QList<ObjectPipe*> pipes;
MainCore::instance()->getMessagePipes().getMessagePipes(m_channel, "reportdemod", pipes);
if (pipes.size() > 0)
{
for (const auto& pipe : pipes)
{
MessageQueue *messageQueue = qobject_cast<MessageQueue*>(pipe->m_element);
MainCore::MsgChannelDemodReport *msg = MainCore::MsgChannelDemodReport::create(m_channel, sampleRate);
messageQueue->push(msg);
}
}
}
void M17DemodSink::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force)
{
qDebug() << "DSDDemodSink::applyChannelSettings:"
<< " channelSampleRate: " << channelSampleRate
<< " inputFrequencyOffset: " << channelFrequencyOffset;
if ((channelFrequencyOffset != m_channelFrequencyOffset) ||
(channelSampleRate != m_channelSampleRate) || force)
{
m_nco.setFreq(-channelFrequencyOffset, channelSampleRate);
}
if ((channelSampleRate != m_channelSampleRate) || force)
{
m_interpolator.create(16, channelSampleRate, (m_settings.m_rfBandwidth) / 2.2);
m_interpolatorDistanceRemain = 0;
m_interpolatorDistance = (Real) channelSampleRate / (Real) 48000;
}
m_channelSampleRate = channelSampleRate;
m_channelFrequencyOffset = channelFrequencyOffset;
}
void M17DemodSink::applySettings(const M17DemodSettings& settings, bool force)
{
qDebug() << "M17DemodSink::applySettings: "
<< " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset
<< " m_rfBandwidth: " << settings.m_rfBandwidth
<< " m_fmDeviation: " << settings.m_fmDeviation
<< " m_demodGain: " << settings.m_demodGain
<< " m_volume: " << settings.m_volume
<< " m_baudRate: " << settings.m_baudRate
<< " m_squelchGate" << settings.m_squelchGate
<< " m_squelch: " << settings.m_squelch
<< " m_audioMute: " << settings.m_audioMute
<< " m_syncOrConstellation: " << settings.m_syncOrConstellation
<< " m_highPassFilter: "<< settings.m_highPassFilter
<< " m_audioDeviceName: " << settings.m_audioDeviceName
<< " m_traceLengthMutliplier: " << settings.m_traceLengthMutliplier
<< " m_traceStroke: " << settings.m_traceStroke
<< " m_traceDecay: " << settings.m_traceDecay
<< " m_streamIndex: " << settings.m_streamIndex
<< " force: " << force;
if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force)
{
m_interpolator.create(16, m_channelSampleRate, (settings.m_rfBandwidth) / 2.2);
m_interpolatorDistanceRemain = 0;
m_interpolatorDistance = (Real) m_channelSampleRate / (Real) 48000;
//m_phaseDiscri.setFMScaling((float) settings.m_rfBandwidth / (float) settings.m_fmDeviation);
}
if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force)
{
m_phaseDiscri.setFMScaling(48000.0f / (2.0f*settings.m_fmDeviation));
}
if ((settings.m_squelchGate != m_settings.m_squelchGate) || force)
{
m_squelchGate = 480 * settings.m_squelchGate; // gate is given in 10s of ms at 48000 Hz audio sample rate
m_squelchCount = 0; // reset squelch open counter
}
if ((settings.m_squelch != m_settings.m_squelch) || force)
{
// input is a value in dB
m_squelchLevel = std::pow(10.0, settings.m_squelch / 10.0);
}
if ((settings.m_volume != m_settings.m_volume) || force)
{
// m_dsdDecoder.setAudioGain(settings.m_volume);
}
if ((settings.m_baudRate != m_settings.m_baudRate) || force)
{
// m_dsdDecoder.setBaudRate(settings.m_baudRate);
}
if ((settings.m_highPassFilter != m_settings.m_highPassFilter) || force)
{
// m_dsdDecoder.useHPMbelib(settings.m_highPassFilter);
}
m_settings = settings;
}
void M17DemodSink::configureMyPosition(float myLatitude, float myLongitude)
{
// m_dsdDecoder.setMyPoint(myLatitude, myLongitude);
}

View File

@ -0,0 +1,134 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_M17DEMODSINK_H
#define INCLUDE_M17DEMODSINK_H
#include <QVector>
#include "dsp/channelsamplesink.h"
#include "dsp/phasediscri.h"
#include "dsp/nco.h"
#include "dsp/interpolator.h"
#include "dsp/firfilter.h"
#include "dsp/afsquelch.h"
#include "dsp/afsquelch.h"
#include "audio/audiofifo.h"
#include "util/movingaverage.h"
#include "util/doublebufferfifo.h"
#include "m17demodsettings.h"
class BasebandSampleSink;
class ChannelAPI;
class M17DemodSink : public ChannelSampleSink {
public:
M17DemodSink();
~M17DemodSink();
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
void applyAudioSampleRate(int sampleRate);
void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false);
void applySettings(const M17DemodSettings& settings, bool force = false);
AudioFifo *getAudioFifo() { return &m_audioFifo; }
void setAudioFifoLabel(const QString& label) { m_audioFifo.setLabel("1:" + label); }
int getAudioSampleRate() const { return m_audioSampleRate; }
void setChannel(ChannelAPI *channel) { m_channel = channel; }
void setScopeXYSink(BasebandSampleSink* scopeSink) { m_scopeXY = scopeSink; }
void configureMyPosition(float myLatitude, float myLongitude);
double getMagSq() { return m_magsq; }
bool getSquelchOpen() const { return m_squelchOpen; }
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;
};
enum RateState {
RSInitialFill,
RSRunning
};
int m_channelSampleRate;
int m_channelFrequencyOffset;
M17DemodSettings m_settings;
ChannelAPI *m_channel;
int m_audioSampleRate;
QVector<qint16> m_demodBuffer;
int m_demodBufferFill;
NCO m_nco;
Interpolator m_interpolator;
Real m_interpolatorDistance;
Real m_interpolatorDistanceRemain;
int m_sampleCount;
int m_squelchCount;
int m_squelchGate;
double m_squelchLevel;
bool m_squelchOpen;
DoubleBufferFIFO<Real> m_squelchDelayLine;
MovingAverageUtil<Real, double, 16> m_movingAverage;
double m_magsq;
double m_magsqSum;
double m_magsqPeak;
int m_magsqCount;
MagSqLevelsStore m_magSqLevelStore;
SampleVector m_scopeSampleBuffer;
AudioVector m_audioBuffer;
uint m_audioBufferFill;
FixReal *m_sampleBuffer; //!< samples ring buffer
int m_sampleBufferIndex;
int m_scaleFromShort;
AudioFifo m_audioFifo;
BasebandSampleSink* m_scopeXY;
bool m_scopeEnabled;
PhaseDiscriminators m_phaseDiscri;
};
#endif // INCLUDE_DSDDEMODSINK_H

View File

@ -0,0 +1,51 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "SWGChannelSettings.h"
#include "m17demod.h"
#include "m17demodwebapiadapter.h"
M17DemodWebAPIAdapter::M17DemodWebAPIAdapter()
{}
M17DemodWebAPIAdapter::~M17DemodWebAPIAdapter()
{}
int M17DemodWebAPIAdapter::webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setDsdDemodSettings(new SWGSDRangel::SWGDSDDemodSettings());
response.getDsdDemodSettings()->init();
M17Demod::webapiFormatChannelSettings(response, m_settings);
return 200;
}
int M17DemodWebAPIAdapter::webapiSettingsPutPatch(
bool force,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) force; // no action
(void) errorMessage;
M17Demod::webapiUpdateChannelSettings(m_settings, channelSettingsKeys, response);
return 200;
}

View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_M17DEMOD_WEBAPIADAPTER_H
#define INCLUDE_M17DEMOD_WEBAPIADAPTER_H
#include "channel/channelwebapiadapter.h"
#include "m17demodsettings.h"
/**
* Standalone API adapter only for the settings
*/
class M17DemodWebAPIAdapter : public ChannelWebAPIAdapter {
public:
M17DemodWebAPIAdapter();
virtual ~M17DemodWebAPIAdapter();
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:
M17DemodSettings m_settings;
};
#endif // INCLUDE_M17DEMOD_WEBAPIADAPTER_H

View File

@ -0,0 +1,88 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022s F4EXB //
// written by Edouard Griffiths //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "m17statustextdialog.h"
#include "ui_m17statustextdialog.h"
#include <QDateTime>
#include <QScrollBar>
#include <QFileDialog>
#include <QMessageBox>
#include <QTextStream>
M17StatusTextDialog::M17StatusTextDialog(QWidget* parent) :
QDialog(parent),
ui(new Ui::M17StatusTextDialog)
{
ui->setupUi(this);
}
M17StatusTextDialog::~M17StatusTextDialog()
{
delete ui;
}
void M17StatusTextDialog::addLine(const QString& line)
{
if ((line.size() > 0) && (line != m_lastLine))
{
QDateTime dt = QDateTime::currentDateTime();
QString dateStr = dt.toString("HH:mm:ss");
QTextCursor cursor = ui->logEdit->textCursor();
cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
cursor.insertText(tr("%1 %2\n").arg(dateStr).arg(line));
if (ui->pinToLastLine->isChecked()) {
ui->logEdit->verticalScrollBar()->setValue(ui->logEdit->verticalScrollBar()->maximum());
}
m_lastLine = line;
}
}
void M17StatusTextDialog::on_clear_clicked()
{
ui->logEdit->clear();
}
void M17StatusTextDialog::on_saveLog_clicked()
{
QString fileName = QFileDialog::getSaveFileName(this,
tr("Open log file"), ".", tr("Log files (*.log)"), 0, QFileDialog::DontUseNativeDialog);
if (fileName != "")
{
QFileInfo fileInfo(fileName);
if (fileInfo.suffix() != "log") {
fileName += ".log";
}
QFile exportFile(fileName);
if (exportFile.open(QIODevice::WriteOnly | QIODevice::Text))
{
QTextStream outstream(&exportFile);
outstream << ui->logEdit->toPlainText();
exportFile.close();
}
else
{
QMessageBox::information(this, tr("Message"), tr("Cannot open file for writing"));
}
}
}

View File

@ -0,0 +1,47 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 F4EXB //
// written by Edouard Griffiths //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_CHANNELRX_DEMODM17_M17STATUSTEXTDIALOG_H_
#define PLUGINS_CHANNELRX_DEMODM17_M17STATUSTEXTDIALOG_H_
#include <QDialog>
namespace Ui {
class M17StatusTextDialog;
}
class M17StatusTextDialog : public QDialog {
Q_OBJECT
public:
explicit M17StatusTextDialog(QWidget* parent = nullptr);
~M17StatusTextDialog();
void addLine(const QString& line);
private:
Ui::M17StatusTextDialog* ui;
QString m_lastLine;
private slots:
void on_clear_clicked();
void on_saveLog_clicked();
};
#endif /* PLUGINS_CHANNELRX_DEMODM17_M17STATUSTEXTDIALOG_H_ */

View File

@ -0,0 +1,181 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>M17StatusTextDialog</class>
<widget class="QDialog" name="M17StatusTextDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>740</width>
<height>380</height>
</rect>
</property>
<property name="font">
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Status text log</string>
</property>
<property name="windowIcon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/sdrangel_icon.png</normaloff>:/sdrangel_icon.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="processLayout">
<item>
<widget class="QPushButton" name="clear">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>Clear log</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/sweep.png</normaloff>:/sweep.png</iconset>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="pinToLastLine">
<property name="toolTip">
<string>Pin to last line</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/pin_last.png</normaloff>:/pin_last.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="saveLog">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>Save log to file</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/save.png</normaloff>:/save.png</iconset>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QPlainTextEdit" name="logEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="font">
<font>
<family>Liberation Mono</family>
</font>
</property>
<property name="toolTip">
<string>Log</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ButtonSwitch</class>
<extends>QToolButton</extends>
<header>gui/buttonswitch.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DSDStatusTextDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>257</x>
<y>194</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>203</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DSDStatusTextDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>314</x>
<y>194</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>203</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -69,6 +69,7 @@
<file>webapi/doc/swagger/include/LocalSource.yaml</file>
<file>webapi/doc/swagger/include/Map.yaml</file>
<file>webapi/doc/swagger/include/MetisMISO.yaml</file>
<file>webapi/doc/swagger/include/M17Demod.yaml</file>
<file>webapi/doc/swagger/include/NFMDemod.yaml</file>
<file>webapi/doc/swagger/include/NFMMod.yaml</file>
<file>webapi/doc/swagger/include/NoiseFigure.yaml</file>

View File

@ -3421,6 +3421,9 @@ margin-bottom: 20px;
"FreqTrackerReport" : {
"$ref" : "#/definitions/FreqTrackerReport"
},
"M17DemodReport" : {
"$ref" : "#/definitions/M17DemodReport"
},
"NFMDemodReport" : {
"$ref" : "#/definitions/NFMDemodReport"
},
@ -3573,6 +3576,9 @@ margin-bottom: 20px;
"IEEE_802_15_4_ModSettings" : {
"$ref" : "#/definitions/IEEE_802_15_4_ModSettings"
},
"M17DemodSettings" : {
"$ref" : "#/definitions/M17DemodSettings"
},
"NFMDemodSettings" : {
"$ref" : "#/definitions/NFMDemodSettings"
},
@ -8210,6 +8216,120 @@ margin-bottom: 20px;
}
},
"description" : "Logging parameters setting"
};
defs.M17DemodReport = {
"properties" : {
"channelPowerDB" : {
"type" : "number",
"format" : "float",
"description" : "power transmitted in channel (dB)"
},
"audioSampleRate" : {
"type" : "integer"
},
"channelSampleRate" : {
"type" : "integer"
},
"squelch" : {
"type" : "integer",
"description" : "squelch status (1 if open else 0)"
}
},
"description" : "M17Demod"
};
defs.M17DemodSettings = {
"properties" : {
"inputFrequencyOffset" : {
"type" : "integer",
"format" : "int64"
},
"rfBandwidth" : {
"type" : "number",
"format" : "float"
},
"fmDeviation" : {
"type" : "number",
"format" : "float"
},
"demodGain" : {
"type" : "number",
"format" : "float"
},
"volume" : {
"type" : "number",
"format" : "float"
},
"baudRate" : {
"type" : "integer"
},
"squelchGate" : {
"type" : "integer"
},
"squelch" : {
"type" : "number",
"format" : "float"
},
"audioMute" : {
"type" : "integer"
},
"syncOrConstellation" : {
"type" : "integer"
},
"pllLock" : {
"type" : "integer"
},
"rgbColor" : {
"type" : "integer"
},
"title" : {
"type" : "string"
},
"audioDeviceName" : {
"type" : "string"
},
"highPassFilter" : {
"type" : "integer"
},
"traceLengthMutliplier" : {
"type" : "integer",
"description" : "multiply by 50ms"
},
"traceStroke" : {
"type" : "integer",
"description" : "0 to 255"
},
"traceDecay" : {
"type" : "integer",
"description" : "0 to 255"
},
"streamIndex" : {
"type" : "integer",
"description" : "MIMO channel. Not relevant when connected to SI (single Rx)."
},
"useReverseAPI" : {
"type" : "integer",
"description" : "Synchronize with reverse API (1 for yes, 0 for no)"
},
"reverseAPIAddress" : {
"type" : "string"
},
"reverseAPIPort" : {
"type" : "integer"
},
"reverseAPIDeviceIndex" : {
"type" : "integer"
},
"reverseAPIChannelIndex" : {
"type" : "integer"
},
"channelMarker" : {
"$ref" : "#/definitions/ChannelMarker"
},
"rollupState" : {
"$ref" : "#/definitions/RollupState"
}
},
"description" : "M17Demod"
};
defs.MapActions = {
"properties" : {
@ -56169,7 +56289,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2022-06-04T08:51:44.121+02:00
Generated 2022-06-05T00:26:14.019+02:00
</div>
</div>
</div>

View File

@ -49,6 +49,8 @@ ChannelReport:
$ref: "/doc/swagger/include/FreeDVMod.yaml#/FreeDVModReport"
FreqTrackerReport:
$ref: "/doc/swagger/include/FreqTracker.yaml#/FreqTrackerReport"
M17DemodReport:
$ref: "/doc/swagger/include/M17Demod.yaml#/M17DemodReport"
NFMDemodReport:
$ref: "/doc/swagger/include/NFMDemod.yaml#/NFMDemodReport"
NFMModReport:

View File

@ -67,6 +67,8 @@ ChannelSettings:
$ref: "/doc/swagger/include/Interferometer.yaml#/InterferometerSettings"
IEEE_802_15_4_ModSettings:
$ref: "/doc/swagger/include/IEEE_802_15_4_Mod.yaml#/IEEE_802_15_4_ModSettings"
M17DemodSettings:
$ref: "/doc/swagger/include/M17Demod.yaml#/M17DemodSettings"
NFMDemodSettings:
$ref: "/doc/swagger/include/NFMDemod.yaml#/NFMDemodSettings"
NFMModSettings:

View File

@ -0,0 +1,82 @@
M17DemodSettings:
description: M17Demod
properties:
inputFrequencyOffset:
type: integer
format: int64
rfBandwidth:
type: number
format: float
fmDeviation:
type: number
format: float
demodGain:
type: number
format: float
volume:
type: number
format: float
baudRate:
type: integer
squelchGate:
type: integer
squelch:
type: number
format: float
audioMute:
type: integer
syncOrConstellation:
type: integer
pllLock:
type: integer
rgbColor:
type: integer
title:
type: string
audioDeviceName:
type: string
highPassFilter:
type: integer
traceLengthMutliplier:
description: multiply by 50ms
type: integer
traceStroke:
description: 0 to 255
type: integer
traceDecay:
description: 0 to 255
type: integer
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
channelMarker:
$ref: "/doc/swagger/include/ChannelMarker.yaml#/ChannelMarker"
rollupState:
$ref: "/doc/swagger/include/RollupState.yaml#/RollupState"
M17DemodReport:
description: M17Demod
properties:
channelPowerDB:
description: power transmitted in channel (dB)
type: number
format: float
audioSampleRate:
type: integer
channelSampleRate:
type: integer
squelch:
description: squelch status (1 if open else 0)
type: integer

View File

@ -4521,6 +4521,11 @@ bool WebAPIRequestMapper::getChannelSettings(
channelSettings->setNfmDemodSettings(new SWGSDRangel::SWGNFMDemodSettings());
channelSettings->getNfmDemodSettings()->fromJsonObject(settingsJsonObject);
}
else if (channelSettingsKey == "M17DemodSettings")
{
channelSettings->setM17DemodSettings(new SWGSDRangel::SWGM17DemodSettings());
channelSettings->getM17DemodSettings()->fromJsonObject(settingsJsonObject);
}
else if (channelSettingsKey == "NFMModSettings")
{
channelSettings->setNfmModSettings(new SWGSDRangel::SWGNFMModSettings());

View File

@ -47,6 +47,7 @@ const QMap<QString, QString> WebAPIUtils::m_channelURIToSettingsKey = {
{"sdrangel.channel.freedvdemod", "FreeDVDemodSettings"},
{"sdrangel.channeltx.freedvmod", "FreeDVModSettings"},
{"sdrangel.channel.freqtracker", "FreqTrackerSettings"},
{"sdrangel.channel.m17demod", "M17DemodSettings"},
{"sdrangel.channel.nfmdemod", "NFMDemodSettings"},
{"de.maintech.sdrangelove.channel.nfm", "NFMDemodSettings"}, // remap
{"sdrangel.channeltx.modnfm", "NFMModSettings"},
@ -153,6 +154,7 @@ const QMap<QString, QString> WebAPIUtils::m_channelTypeToSettingsKey = {
{"FreeDVMod", "FreeDVModSettings"},
{"FreqTracker", "FreqTrackerSettings"},
{"IEEE_802_15_4_Mod", "IEEE_802_15_4_ModSettings"},
{"M17Demod", "M17DemodSettings"},
{"NFMDemod", "NFMDemodSettings"},
{"NFMMod", "NFMModSettings"},
{"NoiseFigure", "NoiseFigureSettings"},

View File

@ -49,6 +49,8 @@ ChannelReport:
$ref: "http://swgserver:8081/api/swagger/include/FreeDVMod.yaml#/FreeDVModReport"
FreqTrackerReport:
$ref: "http://swgserver:8081/api/swagger/include/FreqTracker.yaml#/FreqTrackerReport"
M17DemodReport:
$ref: "http://swgserver:8081/api/swagger/include/M17Demod.yaml#/M17DemodReport"
NFMDemodReport:
$ref: "http://swgserver:8081/api/swagger/include/NFMDemod.yaml#/NFMDemodReport"
NFMModReport:

View File

@ -67,6 +67,8 @@ ChannelSettings:
$ref: "http://swgserver:8081/api/swagger/include/Interferometer.yaml#/InterferometerSettings"
IEEE_802_15_4_ModSettings:
$ref: "http://swgserver:8081/api/swagger/include/IEEE_802_15_4_Mod.yaml#/IEEE_802_15_4_ModSettings"
M17DemodSettings:
$ref: "http://swgserver:8081/api/swagger/include/M17Demod.yaml#/M17DemodSettings"
NFMDemodSettings:
$ref: "http://swgserver:8081/api/swagger/include/NFMDemod.yaml#/NFMDemodSettings"
NFMModSettings:

View File

@ -0,0 +1,82 @@
M17DemodSettings:
description: M17Demod
properties:
inputFrequencyOffset:
type: integer
format: int64
rfBandwidth:
type: number
format: float
fmDeviation:
type: number
format: float
demodGain:
type: number
format: float
volume:
type: number
format: float
baudRate:
type: integer
squelchGate:
type: integer
squelch:
type: number
format: float
audioMute:
type: integer
syncOrConstellation:
type: integer
pllLock:
type: integer
rgbColor:
type: integer
title:
type: string
audioDeviceName:
type: string
highPassFilter:
type: integer
traceLengthMutliplier:
description: multiply by 50ms
type: integer
traceStroke:
description: 0 to 255
type: integer
traceDecay:
description: 0 to 255
type: integer
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
channelMarker:
$ref: "http://swgserver:8081/api/swagger/include/ChannelMarker.yaml#/ChannelMarker"
rollupState:
$ref: "http://swgserver:8081/api/swagger/include/RollupState.yaml#/RollupState"
M17DemodReport:
description: M17Demod
properties:
channelPowerDB:
description: power transmitted in channel (dB)
type: number
format: float
audioSampleRate:
type: integer
channelSampleRate:
type: integer
squelch:
description: squelch status (1 if open else 0)
type: integer

View File

@ -3421,6 +3421,9 @@ margin-bottom: 20px;
"FreqTrackerReport" : {
"$ref" : "#/definitions/FreqTrackerReport"
},
"M17DemodReport" : {
"$ref" : "#/definitions/M17DemodReport"
},
"NFMDemodReport" : {
"$ref" : "#/definitions/NFMDemodReport"
},
@ -3573,6 +3576,9 @@ margin-bottom: 20px;
"IEEE_802_15_4_ModSettings" : {
"$ref" : "#/definitions/IEEE_802_15_4_ModSettings"
},
"M17DemodSettings" : {
"$ref" : "#/definitions/M17DemodSettings"
},
"NFMDemodSettings" : {
"$ref" : "#/definitions/NFMDemodSettings"
},
@ -8210,6 +8216,120 @@ margin-bottom: 20px;
}
},
"description" : "Logging parameters setting"
};
defs.M17DemodReport = {
"properties" : {
"channelPowerDB" : {
"type" : "number",
"format" : "float",
"description" : "power transmitted in channel (dB)"
},
"audioSampleRate" : {
"type" : "integer"
},
"channelSampleRate" : {
"type" : "integer"
},
"squelch" : {
"type" : "integer",
"description" : "squelch status (1 if open else 0)"
}
},
"description" : "M17Demod"
};
defs.M17DemodSettings = {
"properties" : {
"inputFrequencyOffset" : {
"type" : "integer",
"format" : "int64"
},
"rfBandwidth" : {
"type" : "number",
"format" : "float"
},
"fmDeviation" : {
"type" : "number",
"format" : "float"
},
"demodGain" : {
"type" : "number",
"format" : "float"
},
"volume" : {
"type" : "number",
"format" : "float"
},
"baudRate" : {
"type" : "integer"
},
"squelchGate" : {
"type" : "integer"
},
"squelch" : {
"type" : "number",
"format" : "float"
},
"audioMute" : {
"type" : "integer"
},
"syncOrConstellation" : {
"type" : "integer"
},
"pllLock" : {
"type" : "integer"
},
"rgbColor" : {
"type" : "integer"
},
"title" : {
"type" : "string"
},
"audioDeviceName" : {
"type" : "string"
},
"highPassFilter" : {
"type" : "integer"
},
"traceLengthMutliplier" : {
"type" : "integer",
"description" : "multiply by 50ms"
},
"traceStroke" : {
"type" : "integer",
"description" : "0 to 255"
},
"traceDecay" : {
"type" : "integer",
"description" : "0 to 255"
},
"streamIndex" : {
"type" : "integer",
"description" : "MIMO channel. Not relevant when connected to SI (single Rx)."
},
"useReverseAPI" : {
"type" : "integer",
"description" : "Synchronize with reverse API (1 for yes, 0 for no)"
},
"reverseAPIAddress" : {
"type" : "string"
},
"reverseAPIPort" : {
"type" : "integer"
},
"reverseAPIDeviceIndex" : {
"type" : "integer"
},
"reverseAPIChannelIndex" : {
"type" : "integer"
},
"channelMarker" : {
"$ref" : "#/definitions/ChannelMarker"
},
"rollupState" : {
"$ref" : "#/definitions/RollupState"
}
},
"description" : "M17Demod"
};
defs.MapActions = {
"properties" : {
@ -56169,7 +56289,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2022-06-04T08:51:44.121+02:00
Generated 2022-06-05T00:26:14.019+02:00
</div>
</div>
</div>

View File

@ -70,6 +70,8 @@ SWGChannelReport::SWGChannelReport() {
m_free_dv_mod_report_isSet = false;
freq_tracker_report = nullptr;
m_freq_tracker_report_isSet = false;
m17_demod_report = nullptr;
m_m17_demod_report_isSet = false;
nfm_demod_report = nullptr;
m_nfm_demod_report_isSet = false;
nfm_mod_report = nullptr;
@ -156,6 +158,8 @@ SWGChannelReport::init() {
m_free_dv_mod_report_isSet = false;
freq_tracker_report = new SWGFreqTrackerReport();
m_freq_tracker_report_isSet = false;
m17_demod_report = new SWGM17DemodReport();
m_m17_demod_report_isSet = false;
nfm_demod_report = new SWGNFMDemodReport();
m_nfm_demod_report_isSet = false;
nfm_mod_report = new SWGNFMModReport();
@ -257,6 +261,9 @@ SWGChannelReport::cleanup() {
if(freq_tracker_report != nullptr) {
delete freq_tracker_report;
}
if(m17_demod_report != nullptr) {
delete m17_demod_report;
}
if(nfm_demod_report != nullptr) {
delete nfm_demod_report;
}
@ -366,6 +373,8 @@ SWGChannelReport::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&freq_tracker_report, pJson["FreqTrackerReport"], "SWGFreqTrackerReport", "SWGFreqTrackerReport");
::SWGSDRangel::setValue(&m17_demod_report, pJson["M17DemodReport"], "SWGM17DemodReport", "SWGM17DemodReport");
::SWGSDRangel::setValue(&nfm_demod_report, pJson["NFMDemodReport"], "SWGNFMDemodReport", "SWGNFMDemodReport");
::SWGSDRangel::setValue(&nfm_mod_report, pJson["NFMModReport"], "SWGNFMModReport", "SWGNFMModReport");
@ -481,6 +490,9 @@ SWGChannelReport::asJsonObject() {
if((freq_tracker_report != nullptr) && (freq_tracker_report->isSet())){
toJsonValue(QString("FreqTrackerReport"), freq_tracker_report, obj, QString("SWGFreqTrackerReport"));
}
if((m17_demod_report != nullptr) && (m17_demod_report->isSet())){
toJsonValue(QString("M17DemodReport"), m17_demod_report, obj, QString("SWGM17DemodReport"));
}
if((nfm_demod_report != nullptr) && (nfm_demod_report->isSet())){
toJsonValue(QString("NFMDemodReport"), nfm_demod_report, obj, QString("SWGNFMDemodReport"));
}
@ -749,6 +761,16 @@ SWGChannelReport::setFreqTrackerReport(SWGFreqTrackerReport* freq_tracker_report
this->m_freq_tracker_report_isSet = true;
}
SWGM17DemodReport*
SWGChannelReport::getM17DemodReport() {
return m17_demod_report;
}
void
SWGChannelReport::setM17DemodReport(SWGM17DemodReport* m17_demod_report) {
this->m17_demod_report = m17_demod_report;
this->m_m17_demod_report_isSet = true;
}
SWGNFMDemodReport*
SWGChannelReport::getNfmDemodReport() {
return nfm_demod_report;
@ -997,6 +1019,9 @@ SWGChannelReport::isSet(){
if(freq_tracker_report && freq_tracker_report->isSet()){
isObjectUpdated = true; break;
}
if(m17_demod_report && m17_demod_report->isSet()){
isObjectUpdated = true; break;
}
if(nfm_demod_report && nfm_demod_report->isSet()){
isObjectUpdated = true; break;
}

View File

@ -41,6 +41,7 @@
#include "SWGFreeDVModReport.h"
#include "SWGFreqTrackerReport.h"
#include "SWGIEEE_802_15_4_ModReport.h"
#include "SWGM17DemodReport.h"
#include "SWGNFMDemodReport.h"
#include "SWGNFMModReport.h"
#include "SWGNoiseFigureReport.h"
@ -142,6 +143,9 @@ public:
SWGFreqTrackerReport* getFreqTrackerReport();
void setFreqTrackerReport(SWGFreqTrackerReport* freq_tracker_report);
SWGM17DemodReport* getM17DemodReport();
void setM17DemodReport(SWGM17DemodReport* m17_demod_report);
SWGNFMDemodReport* getNfmDemodReport();
void setNfmDemodReport(SWGNFMDemodReport* nfm_demod_report);
@ -263,6 +267,9 @@ private:
SWGFreqTrackerReport* freq_tracker_report;
bool m_freq_tracker_report_isSet;
SWGM17DemodReport* m17_demod_report;
bool m_m17_demod_report_isSet;
SWGNFMDemodReport* nfm_demod_report;
bool m_nfm_demod_report_isSet;

View File

@ -86,6 +86,8 @@ SWGChannelSettings::SWGChannelSettings() {
m_interferometer_settings_isSet = false;
ieee_802_15_4_mod_settings = nullptr;
m_ieee_802_15_4_mod_settings_isSet = false;
m17_demod_settings = nullptr;
m_m17_demod_settings_isSet = false;
nfm_demod_settings = nullptr;
m_nfm_demod_settings_isSet = false;
nfm_mod_settings = nullptr;
@ -194,6 +196,8 @@ SWGChannelSettings::init() {
m_interferometer_settings_isSet = false;
ieee_802_15_4_mod_settings = new SWGIEEE_802_15_4_ModSettings();
m_ieee_802_15_4_mod_settings_isSet = false;
m17_demod_settings = new SWGM17DemodSettings();
m_m17_demod_settings_isSet = false;
nfm_demod_settings = new SWGNFMDemodSettings();
m_nfm_demod_settings_isSet = false;
nfm_mod_settings = new SWGNFMModSettings();
@ -321,6 +325,9 @@ SWGChannelSettings::cleanup() {
if(ieee_802_15_4_mod_settings != nullptr) {
delete ieee_802_15_4_mod_settings;
}
if(m17_demod_settings != nullptr) {
delete m17_demod_settings;
}
if(nfm_demod_settings != nullptr) {
delete nfm_demod_settings;
}
@ -455,6 +462,8 @@ SWGChannelSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&ieee_802_15_4_mod_settings, pJson["IEEE_802_15_4_ModSettings"], "SWGIEEE_802_15_4_ModSettings", "SWGIEEE_802_15_4_ModSettings");
::SWGSDRangel::setValue(&m17_demod_settings, pJson["M17DemodSettings"], "SWGM17DemodSettings", "SWGM17DemodSettings");
::SWGSDRangel::setValue(&nfm_demod_settings, pJson["NFMDemodSettings"], "SWGNFMDemodSettings", "SWGNFMDemodSettings");
::SWGSDRangel::setValue(&nfm_mod_settings, pJson["NFMModSettings"], "SWGNFMModSettings", "SWGNFMModSettings");
@ -600,6 +609,9 @@ SWGChannelSettings::asJsonObject() {
if((ieee_802_15_4_mod_settings != nullptr) && (ieee_802_15_4_mod_settings->isSet())){
toJsonValue(QString("IEEE_802_15_4_ModSettings"), ieee_802_15_4_mod_settings, obj, QString("SWGIEEE_802_15_4_ModSettings"));
}
if((m17_demod_settings != nullptr) && (m17_demod_settings->isSet())){
toJsonValue(QString("M17DemodSettings"), m17_demod_settings, obj, QString("SWGM17DemodSettings"));
}
if((nfm_demod_settings != nullptr) && (nfm_demod_settings->isSet())){
toJsonValue(QString("NFMDemodSettings"), nfm_demod_settings, obj, QString("SWGNFMDemodSettings"));
}
@ -957,6 +969,16 @@ SWGChannelSettings::setIeee802154ModSettings(SWGIEEE_802_15_4_ModSettings* ieee_
this->m_ieee_802_15_4_mod_settings_isSet = true;
}
SWGM17DemodSettings*
SWGChannelSettings::getM17DemodSettings() {
return m17_demod_settings;
}
void
SWGChannelSettings::setM17DemodSettings(SWGM17DemodSettings* m17_demod_settings) {
this->m17_demod_settings = m17_demod_settings;
this->m_m17_demod_settings_isSet = true;
}
SWGNFMDemodSettings*
SWGChannelSettings::getNfmDemodSettings() {
return nfm_demod_settings;
@ -1259,6 +1281,9 @@ SWGChannelSettings::isSet(){
if(ieee_802_15_4_mod_settings && ieee_802_15_4_mod_settings->isSet()){
isObjectUpdated = true; break;
}
if(m17_demod_settings && m17_demod_settings->isSet()){
isObjectUpdated = true; break;
}
if(nfm_demod_settings && nfm_demod_settings->isSet()){
isObjectUpdated = true; break;
}

View File

@ -49,6 +49,7 @@
#include "SWGInterferometerSettings.h"
#include "SWGLocalSinkSettings.h"
#include "SWGLocalSourceSettings.h"
#include "SWGM17DemodSettings.h"
#include "SWGNFMDemodSettings.h"
#include "SWGNFMModSettings.h"
#include "SWGNoiseFigureSettings.h"
@ -175,6 +176,9 @@ public:
SWGIEEE_802_15_4_ModSettings* getIeee802154ModSettings();
void setIeee802154ModSettings(SWGIEEE_802_15_4_ModSettings* ieee_802_15_4_mod_settings);
SWGM17DemodSettings* getM17DemodSettings();
void setM17DemodSettings(SWGM17DemodSettings* m17_demod_settings);
SWGNFMDemodSettings* getNfmDemodSettings();
void setNfmDemodSettings(SWGNFMDemodSettings* nfm_demod_settings);
@ -329,6 +333,9 @@ private:
SWGIEEE_802_15_4_ModSettings* ieee_802_15_4_mod_settings;
bool m_ieee_802_15_4_mod_settings_isSet;
SWGM17DemodSettings* m17_demod_settings;
bool m_m17_demod_settings_isSet;
SWGNFMDemodSettings* nfm_demod_settings;
bool m_nfm_demod_settings_isSet;

View File

@ -0,0 +1,177 @@
/**
* 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: 7.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 "SWGM17DemodReport.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGM17DemodReport::SWGM17DemodReport(QString* json) {
init();
this->fromJson(*json);
}
SWGM17DemodReport::SWGM17DemodReport() {
channel_power_db = 0.0f;
m_channel_power_db_isSet = false;
audio_sample_rate = 0;
m_audio_sample_rate_isSet = false;
channel_sample_rate = 0;
m_channel_sample_rate_isSet = false;
squelch = 0;
m_squelch_isSet = false;
}
SWGM17DemodReport::~SWGM17DemodReport() {
this->cleanup();
}
void
SWGM17DemodReport::init() {
channel_power_db = 0.0f;
m_channel_power_db_isSet = false;
audio_sample_rate = 0;
m_audio_sample_rate_isSet = false;
channel_sample_rate = 0;
m_channel_sample_rate_isSet = false;
squelch = 0;
m_squelch_isSet = false;
}
void
SWGM17DemodReport::cleanup() {
}
SWGM17DemodReport*
SWGM17DemodReport::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGM17DemodReport::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&channel_power_db, pJson["channelPowerDB"], "float", "");
::SWGSDRangel::setValue(&audio_sample_rate, pJson["audioSampleRate"], "qint32", "");
::SWGSDRangel::setValue(&channel_sample_rate, pJson["channelSampleRate"], "qint32", "");
::SWGSDRangel::setValue(&squelch, pJson["squelch"], "qint32", "");
}
QString
SWGM17DemodReport::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGM17DemodReport::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if(m_channel_power_db_isSet){
obj->insert("channelPowerDB", QJsonValue(channel_power_db));
}
if(m_audio_sample_rate_isSet){
obj->insert("audioSampleRate", QJsonValue(audio_sample_rate));
}
if(m_channel_sample_rate_isSet){
obj->insert("channelSampleRate", QJsonValue(channel_sample_rate));
}
if(m_squelch_isSet){
obj->insert("squelch", QJsonValue(squelch));
}
return obj;
}
float
SWGM17DemodReport::getChannelPowerDb() {
return channel_power_db;
}
void
SWGM17DemodReport::setChannelPowerDb(float channel_power_db) {
this->channel_power_db = channel_power_db;
this->m_channel_power_db_isSet = true;
}
qint32
SWGM17DemodReport::getAudioSampleRate() {
return audio_sample_rate;
}
void
SWGM17DemodReport::setAudioSampleRate(qint32 audio_sample_rate) {
this->audio_sample_rate = audio_sample_rate;
this->m_audio_sample_rate_isSet = true;
}
qint32
SWGM17DemodReport::getChannelSampleRate() {
return channel_sample_rate;
}
void
SWGM17DemodReport::setChannelSampleRate(qint32 channel_sample_rate) {
this->channel_sample_rate = channel_sample_rate;
this->m_channel_sample_rate_isSet = true;
}
qint32
SWGM17DemodReport::getSquelch() {
return squelch;
}
void
SWGM17DemodReport::setSquelch(qint32 squelch) {
this->squelch = squelch;
this->m_squelch_isSet = true;
}
bool
SWGM17DemodReport::isSet(){
bool isObjectUpdated = false;
do{
if(m_channel_power_db_isSet){
isObjectUpdated = true; break;
}
if(m_audio_sample_rate_isSet){
isObjectUpdated = true; break;
}
if(m_channel_sample_rate_isSet){
isObjectUpdated = true; break;
}
if(m_squelch_isSet){
isObjectUpdated = true; break;
}
}while(false);
return isObjectUpdated;
}
}

View File

@ -0,0 +1,76 @@
/**
* 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: 7.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.
*/
/*
* SWGM17DemodReport.h
*
* M17Demod
*/
#ifndef SWGM17DemodReport_H_
#define SWGM17DemodReport_H_
#include <QJsonObject>
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGM17DemodReport: public SWGObject {
public:
SWGM17DemodReport();
SWGM17DemodReport(QString* json);
virtual ~SWGM17DemodReport();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGM17DemodReport* fromJson(QString &jsonString) override;
float getChannelPowerDb();
void setChannelPowerDb(float channel_power_db);
qint32 getAudioSampleRate();
void setAudioSampleRate(qint32 audio_sample_rate);
qint32 getChannelSampleRate();
void setChannelSampleRate(qint32 channel_sample_rate);
qint32 getSquelch();
void setSquelch(qint32 squelch);
virtual bool isSet() override;
private:
float channel_power_db;
bool m_channel_power_db_isSet;
qint32 audio_sample_rate;
bool m_audio_sample_rate_isSet;
qint32 channel_sample_rate;
bool m_channel_sample_rate_isSet;
qint32 squelch;
bool m_squelch_isSet;
};
}
#endif /* SWGM17DemodReport_H_ */

View File

@ -0,0 +1,693 @@
/**
* 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: 7.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 "SWGM17DemodSettings.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGM17DemodSettings::SWGM17DemodSettings(QString* json) {
init();
this->fromJson(*json);
}
SWGM17DemodSettings::SWGM17DemodSettings() {
input_frequency_offset = 0L;
m_input_frequency_offset_isSet = false;
rf_bandwidth = 0.0f;
m_rf_bandwidth_isSet = false;
fm_deviation = 0.0f;
m_fm_deviation_isSet = false;
demod_gain = 0.0f;
m_demod_gain_isSet = false;
volume = 0.0f;
m_volume_isSet = false;
baud_rate = 0;
m_baud_rate_isSet = false;
squelch_gate = 0;
m_squelch_gate_isSet = false;
squelch = 0.0f;
m_squelch_isSet = false;
audio_mute = 0;
m_audio_mute_isSet = false;
sync_or_constellation = 0;
m_sync_or_constellation_isSet = false;
pll_lock = 0;
m_pll_lock_isSet = false;
rgb_color = 0;
m_rgb_color_isSet = false;
title = nullptr;
m_title_isSet = false;
audio_device_name = nullptr;
m_audio_device_name_isSet = false;
high_pass_filter = 0;
m_high_pass_filter_isSet = false;
trace_length_mutliplier = 0;
m_trace_length_mutliplier_isSet = false;
trace_stroke = 0;
m_trace_stroke_isSet = false;
trace_decay = 0;
m_trace_decay_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;
channel_marker = nullptr;
m_channel_marker_isSet = false;
rollup_state = nullptr;
m_rollup_state_isSet = false;
}
SWGM17DemodSettings::~SWGM17DemodSettings() {
this->cleanup();
}
void
SWGM17DemodSettings::init() {
input_frequency_offset = 0L;
m_input_frequency_offset_isSet = false;
rf_bandwidth = 0.0f;
m_rf_bandwidth_isSet = false;
fm_deviation = 0.0f;
m_fm_deviation_isSet = false;
demod_gain = 0.0f;
m_demod_gain_isSet = false;
volume = 0.0f;
m_volume_isSet = false;
baud_rate = 0;
m_baud_rate_isSet = false;
squelch_gate = 0;
m_squelch_gate_isSet = false;
squelch = 0.0f;
m_squelch_isSet = false;
audio_mute = 0;
m_audio_mute_isSet = false;
sync_or_constellation = 0;
m_sync_or_constellation_isSet = false;
pll_lock = 0;
m_pll_lock_isSet = false;
rgb_color = 0;
m_rgb_color_isSet = false;
title = new QString("");
m_title_isSet = false;
audio_device_name = new QString("");
m_audio_device_name_isSet = false;
high_pass_filter = 0;
m_high_pass_filter_isSet = false;
trace_length_mutliplier = 0;
m_trace_length_mutliplier_isSet = false;
trace_stroke = 0;
m_trace_stroke_isSet = false;
trace_decay = 0;
m_trace_decay_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;
channel_marker = new SWGChannelMarker();
m_channel_marker_isSet = false;
rollup_state = new SWGRollupState();
m_rollup_state_isSet = false;
}
void
SWGM17DemodSettings::cleanup() {
if(title != nullptr) {
delete title;
}
if(audio_device_name != nullptr) {
delete audio_device_name;
}
if(reverse_api_address != nullptr) {
delete reverse_api_address;
}
if(channel_marker != nullptr) {
delete channel_marker;
}
if(rollup_state != nullptr) {
delete rollup_state;
}
}
SWGM17DemodSettings*
SWGM17DemodSettings::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGM17DemodSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&input_frequency_offset, pJson["inputFrequencyOffset"], "qint64", "");
::SWGSDRangel::setValue(&rf_bandwidth, pJson["rfBandwidth"], "float", "");
::SWGSDRangel::setValue(&fm_deviation, pJson["fmDeviation"], "float", "");
::SWGSDRangel::setValue(&demod_gain, pJson["demodGain"], "float", "");
::SWGSDRangel::setValue(&volume, pJson["volume"], "float", "");
::SWGSDRangel::setValue(&baud_rate, pJson["baudRate"], "qint32", "");
::SWGSDRangel::setValue(&squelch_gate, pJson["squelchGate"], "qint32", "");
::SWGSDRangel::setValue(&squelch, pJson["squelch"], "float", "");
::SWGSDRangel::setValue(&audio_mute, pJson["audioMute"], "qint32", "");
::SWGSDRangel::setValue(&sync_or_constellation, pJson["syncOrConstellation"], "qint32", "");
::SWGSDRangel::setValue(&pll_lock, pJson["pllLock"], "qint32", "");
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
::SWGSDRangel::setValue(&audio_device_name, pJson["audioDeviceName"], "QString", "QString");
::SWGSDRangel::setValue(&high_pass_filter, pJson["highPassFilter"], "qint32", "");
::SWGSDRangel::setValue(&trace_length_mutliplier, pJson["traceLengthMutliplier"], "qint32", "");
::SWGSDRangel::setValue(&trace_stroke, pJson["traceStroke"], "qint32", "");
::SWGSDRangel::setValue(&trace_decay, pJson["traceDecay"], "qint32", "");
::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", "");
::SWGSDRangel::setValue(&channel_marker, pJson["channelMarker"], "SWGChannelMarker", "SWGChannelMarker");
::SWGSDRangel::setValue(&rollup_state, pJson["rollupState"], "SWGRollupState", "SWGRollupState");
}
QString
SWGM17DemodSettings::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGM17DemodSettings::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_fm_deviation_isSet){
obj->insert("fmDeviation", QJsonValue(fm_deviation));
}
if(m_demod_gain_isSet){
obj->insert("demodGain", QJsonValue(demod_gain));
}
if(m_volume_isSet){
obj->insert("volume", QJsonValue(volume));
}
if(m_baud_rate_isSet){
obj->insert("baudRate", QJsonValue(baud_rate));
}
if(m_squelch_gate_isSet){
obj->insert("squelchGate", QJsonValue(squelch_gate));
}
if(m_squelch_isSet){
obj->insert("squelch", QJsonValue(squelch));
}
if(m_audio_mute_isSet){
obj->insert("audioMute", QJsonValue(audio_mute));
}
if(m_sync_or_constellation_isSet){
obj->insert("syncOrConstellation", QJsonValue(sync_or_constellation));
}
if(m_pll_lock_isSet){
obj->insert("pllLock", QJsonValue(pll_lock));
}
if(m_rgb_color_isSet){
obj->insert("rgbColor", QJsonValue(rgb_color));
}
if(title != nullptr && *title != QString("")){
toJsonValue(QString("title"), title, obj, QString("QString"));
}
if(audio_device_name != nullptr && *audio_device_name != QString("")){
toJsonValue(QString("audioDeviceName"), audio_device_name, obj, QString("QString"));
}
if(m_high_pass_filter_isSet){
obj->insert("highPassFilter", QJsonValue(high_pass_filter));
}
if(m_trace_length_mutliplier_isSet){
obj->insert("traceLengthMutliplier", QJsonValue(trace_length_mutliplier));
}
if(m_trace_stroke_isSet){
obj->insert("traceStroke", QJsonValue(trace_stroke));
}
if(m_trace_decay_isSet){
obj->insert("traceDecay", QJsonValue(trace_decay));
}
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));
}
if((channel_marker != nullptr) && (channel_marker->isSet())){
toJsonValue(QString("channelMarker"), channel_marker, obj, QString("SWGChannelMarker"));
}
if((rollup_state != nullptr) && (rollup_state->isSet())){
toJsonValue(QString("rollupState"), rollup_state, obj, QString("SWGRollupState"));
}
return obj;
}
qint64
SWGM17DemodSettings::getInputFrequencyOffset() {
return input_frequency_offset;
}
void
SWGM17DemodSettings::setInputFrequencyOffset(qint64 input_frequency_offset) {
this->input_frequency_offset = input_frequency_offset;
this->m_input_frequency_offset_isSet = true;
}
float
SWGM17DemodSettings::getRfBandwidth() {
return rf_bandwidth;
}
void
SWGM17DemodSettings::setRfBandwidth(float rf_bandwidth) {
this->rf_bandwidth = rf_bandwidth;
this->m_rf_bandwidth_isSet = true;
}
float
SWGM17DemodSettings::getFmDeviation() {
return fm_deviation;
}
void
SWGM17DemodSettings::setFmDeviation(float fm_deviation) {
this->fm_deviation = fm_deviation;
this->m_fm_deviation_isSet = true;
}
float
SWGM17DemodSettings::getDemodGain() {
return demod_gain;
}
void
SWGM17DemodSettings::setDemodGain(float demod_gain) {
this->demod_gain = demod_gain;
this->m_demod_gain_isSet = true;
}
float
SWGM17DemodSettings::getVolume() {
return volume;
}
void
SWGM17DemodSettings::setVolume(float volume) {
this->volume = volume;
this->m_volume_isSet = true;
}
qint32
SWGM17DemodSettings::getBaudRate() {
return baud_rate;
}
void
SWGM17DemodSettings::setBaudRate(qint32 baud_rate) {
this->baud_rate = baud_rate;
this->m_baud_rate_isSet = true;
}
qint32
SWGM17DemodSettings::getSquelchGate() {
return squelch_gate;
}
void
SWGM17DemodSettings::setSquelchGate(qint32 squelch_gate) {
this->squelch_gate = squelch_gate;
this->m_squelch_gate_isSet = true;
}
float
SWGM17DemodSettings::getSquelch() {
return squelch;
}
void
SWGM17DemodSettings::setSquelch(float squelch) {
this->squelch = squelch;
this->m_squelch_isSet = true;
}
qint32
SWGM17DemodSettings::getAudioMute() {
return audio_mute;
}
void
SWGM17DemodSettings::setAudioMute(qint32 audio_mute) {
this->audio_mute = audio_mute;
this->m_audio_mute_isSet = true;
}
qint32
SWGM17DemodSettings::getSyncOrConstellation() {
return sync_or_constellation;
}
void
SWGM17DemodSettings::setSyncOrConstellation(qint32 sync_or_constellation) {
this->sync_or_constellation = sync_or_constellation;
this->m_sync_or_constellation_isSet = true;
}
qint32
SWGM17DemodSettings::getPllLock() {
return pll_lock;
}
void
SWGM17DemodSettings::setPllLock(qint32 pll_lock) {
this->pll_lock = pll_lock;
this->m_pll_lock_isSet = true;
}
qint32
SWGM17DemodSettings::getRgbColor() {
return rgb_color;
}
void
SWGM17DemodSettings::setRgbColor(qint32 rgb_color) {
this->rgb_color = rgb_color;
this->m_rgb_color_isSet = true;
}
QString*
SWGM17DemodSettings::getTitle() {
return title;
}
void
SWGM17DemodSettings::setTitle(QString* title) {
this->title = title;
this->m_title_isSet = true;
}
QString*
SWGM17DemodSettings::getAudioDeviceName() {
return audio_device_name;
}
void
SWGM17DemodSettings::setAudioDeviceName(QString* audio_device_name) {
this->audio_device_name = audio_device_name;
this->m_audio_device_name_isSet = true;
}
qint32
SWGM17DemodSettings::getHighPassFilter() {
return high_pass_filter;
}
void
SWGM17DemodSettings::setHighPassFilter(qint32 high_pass_filter) {
this->high_pass_filter = high_pass_filter;
this->m_high_pass_filter_isSet = true;
}
qint32
SWGM17DemodSettings::getTraceLengthMutliplier() {
return trace_length_mutliplier;
}
void
SWGM17DemodSettings::setTraceLengthMutliplier(qint32 trace_length_mutliplier) {
this->trace_length_mutliplier = trace_length_mutliplier;
this->m_trace_length_mutliplier_isSet = true;
}
qint32
SWGM17DemodSettings::getTraceStroke() {
return trace_stroke;
}
void
SWGM17DemodSettings::setTraceStroke(qint32 trace_stroke) {
this->trace_stroke = trace_stroke;
this->m_trace_stroke_isSet = true;
}
qint32
SWGM17DemodSettings::getTraceDecay() {
return trace_decay;
}
void
SWGM17DemodSettings::setTraceDecay(qint32 trace_decay) {
this->trace_decay = trace_decay;
this->m_trace_decay_isSet = true;
}
qint32
SWGM17DemodSettings::getStreamIndex() {
return stream_index;
}
void
SWGM17DemodSettings::setStreamIndex(qint32 stream_index) {
this->stream_index = stream_index;
this->m_stream_index_isSet = true;
}
qint32
SWGM17DemodSettings::getUseReverseApi() {
return use_reverse_api;
}
void
SWGM17DemodSettings::setUseReverseApi(qint32 use_reverse_api) {
this->use_reverse_api = use_reverse_api;
this->m_use_reverse_api_isSet = true;
}
QString*
SWGM17DemodSettings::getReverseApiAddress() {
return reverse_api_address;
}
void
SWGM17DemodSettings::setReverseApiAddress(QString* reverse_api_address) {
this->reverse_api_address = reverse_api_address;
this->m_reverse_api_address_isSet = true;
}
qint32
SWGM17DemodSettings::getReverseApiPort() {
return reverse_api_port;
}
void
SWGM17DemodSettings::setReverseApiPort(qint32 reverse_api_port) {
this->reverse_api_port = reverse_api_port;
this->m_reverse_api_port_isSet = true;
}
qint32
SWGM17DemodSettings::getReverseApiDeviceIndex() {
return reverse_api_device_index;
}
void
SWGM17DemodSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) {
this->reverse_api_device_index = reverse_api_device_index;
this->m_reverse_api_device_index_isSet = true;
}
qint32
SWGM17DemodSettings::getReverseApiChannelIndex() {
return reverse_api_channel_index;
}
void
SWGM17DemodSettings::setReverseApiChannelIndex(qint32 reverse_api_channel_index) {
this->reverse_api_channel_index = reverse_api_channel_index;
this->m_reverse_api_channel_index_isSet = true;
}
SWGChannelMarker*
SWGM17DemodSettings::getChannelMarker() {
return channel_marker;
}
void
SWGM17DemodSettings::setChannelMarker(SWGChannelMarker* channel_marker) {
this->channel_marker = channel_marker;
this->m_channel_marker_isSet = true;
}
SWGRollupState*
SWGM17DemodSettings::getRollupState() {
return rollup_state;
}
void
SWGM17DemodSettings::setRollupState(SWGRollupState* rollup_state) {
this->rollup_state = rollup_state;
this->m_rollup_state_isSet = true;
}
bool
SWGM17DemodSettings::isSet(){
bool isObjectUpdated = false;
do{
if(m_input_frequency_offset_isSet){
isObjectUpdated = true; break;
}
if(m_rf_bandwidth_isSet){
isObjectUpdated = true; break;
}
if(m_fm_deviation_isSet){
isObjectUpdated = true; break;
}
if(m_demod_gain_isSet){
isObjectUpdated = true; break;
}
if(m_volume_isSet){
isObjectUpdated = true; break;
}
if(m_baud_rate_isSet){
isObjectUpdated = true; break;
}
if(m_squelch_gate_isSet){
isObjectUpdated = true; break;
}
if(m_squelch_isSet){
isObjectUpdated = true; break;
}
if(m_audio_mute_isSet){
isObjectUpdated = true; break;
}
if(m_sync_or_constellation_isSet){
isObjectUpdated = true; break;
}
if(m_pll_lock_isSet){
isObjectUpdated = true; break;
}
if(m_rgb_color_isSet){
isObjectUpdated = true; break;
}
if(title && *title != QString("")){
isObjectUpdated = true; break;
}
if(audio_device_name && *audio_device_name != QString("")){
isObjectUpdated = true; break;
}
if(m_high_pass_filter_isSet){
isObjectUpdated = true; break;
}
if(m_trace_length_mutliplier_isSet){
isObjectUpdated = true; break;
}
if(m_trace_stroke_isSet){
isObjectUpdated = true; break;
}
if(m_trace_decay_isSet){
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;
}
if(channel_marker && channel_marker->isSet()){
isObjectUpdated = true; break;
}
if(rollup_state && rollup_state->isSet()){
isObjectUpdated = true; break;
}
}while(false);
return isObjectUpdated;
}
}

View File

@ -0,0 +1,211 @@
/**
* 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: 7.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.
*/
/*
* SWGM17DemodSettings.h
*
* M17Demod
*/
#ifndef SWGM17DemodSettings_H_
#define SWGM17DemodSettings_H_
#include <QJsonObject>
#include "SWGChannelMarker.h"
#include "SWGRollupState.h"
#include <QString>
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGM17DemodSettings: public SWGObject {
public:
SWGM17DemodSettings();
SWGM17DemodSettings(QString* json);
virtual ~SWGM17DemodSettings();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGM17DemodSettings* fromJson(QString &jsonString) override;
qint64 getInputFrequencyOffset();
void setInputFrequencyOffset(qint64 input_frequency_offset);
float getRfBandwidth();
void setRfBandwidth(float rf_bandwidth);
float getFmDeviation();
void setFmDeviation(float fm_deviation);
float getDemodGain();
void setDemodGain(float demod_gain);
float getVolume();
void setVolume(float volume);
qint32 getBaudRate();
void setBaudRate(qint32 baud_rate);
qint32 getSquelchGate();
void setSquelchGate(qint32 squelch_gate);
float getSquelch();
void setSquelch(float squelch);
qint32 getAudioMute();
void setAudioMute(qint32 audio_mute);
qint32 getSyncOrConstellation();
void setSyncOrConstellation(qint32 sync_or_constellation);
qint32 getPllLock();
void setPllLock(qint32 pll_lock);
qint32 getRgbColor();
void setRgbColor(qint32 rgb_color);
QString* getTitle();
void setTitle(QString* title);
QString* getAudioDeviceName();
void setAudioDeviceName(QString* audio_device_name);
qint32 getHighPassFilter();
void setHighPassFilter(qint32 high_pass_filter);
qint32 getTraceLengthMutliplier();
void setTraceLengthMutliplier(qint32 trace_length_mutliplier);
qint32 getTraceStroke();
void setTraceStroke(qint32 trace_stroke);
qint32 getTraceDecay();
void setTraceDecay(qint32 trace_decay);
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);
SWGChannelMarker* getChannelMarker();
void setChannelMarker(SWGChannelMarker* channel_marker);
SWGRollupState* getRollupState();
void setRollupState(SWGRollupState* rollup_state);
virtual bool isSet() override;
private:
qint64 input_frequency_offset;
bool m_input_frequency_offset_isSet;
float rf_bandwidth;
bool m_rf_bandwidth_isSet;
float fm_deviation;
bool m_fm_deviation_isSet;
float demod_gain;
bool m_demod_gain_isSet;
float volume;
bool m_volume_isSet;
qint32 baud_rate;
bool m_baud_rate_isSet;
qint32 squelch_gate;
bool m_squelch_gate_isSet;
float squelch;
bool m_squelch_isSet;
qint32 audio_mute;
bool m_audio_mute_isSet;
qint32 sync_or_constellation;
bool m_sync_or_constellation_isSet;
qint32 pll_lock;
bool m_pll_lock_isSet;
qint32 rgb_color;
bool m_rgb_color_isSet;
QString* title;
bool m_title_isSet;
QString* audio_device_name;
bool m_audio_device_name_isSet;
qint32 high_pass_filter;
bool m_high_pass_filter_isSet;
qint32 trace_length_mutliplier;
bool m_trace_length_mutliplier_isSet;
qint32 trace_stroke;
bool m_trace_stroke_isSet;
qint32 trace_decay;
bool m_trace_decay_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;
SWGChannelMarker* channel_marker;
bool m_channel_marker_isSet;
SWGRollupState* rollup_state;
bool m_rollup_state_isSet;
};
}
#endif /* SWGM17DemodSettings_H_ */

View File

@ -183,6 +183,8 @@
#include "SWGLocalSourceSettings.h"
#include "SWGLocationInformation.h"
#include "SWGLoggingInfo.h"
#include "SWGM17DemodReport.h"
#include "SWGM17DemodSettings.h"
#include "SWGMapActions.h"
#include "SWGMapAnimation.h"
#include "SWGMapCoordinate.h"
@ -1180,6 +1182,16 @@ namespace SWGSDRangel {
obj->init();
return obj;
}
if(QString("SWGM17DemodReport").compare(type) == 0) {
SWGM17DemodReport *obj = new SWGM17DemodReport();
obj->init();
return obj;
}
if(QString("SWGM17DemodSettings").compare(type) == 0) {
SWGM17DemodSettings *obj = new SWGM17DemodSettings();
obj->init();
return obj;
}
if(QString("SWGMapActions").compare(type) == 0) {
SWGMapActions *obj = new SWGMapActions();
obj->init();