Add packet modulator for transmitting packet radio data packets (AX.25/APRS)

pull/638/head
Jon Beniston 2020-09-18 16:36:27 +01:00
rodzic f22c9fca2c
commit 1dc1b17e73
56 zmienionych plików z 6918 dodań i 3 usunięć

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 17 KiB

Wyświetl plik

@ -4,6 +4,7 @@ add_subdirectory(modam)
add_subdirectory(modnfm)
add_subdirectory(modssb)
add_subdirectory(modwfm)
add_subdirectory(modpacket)
add_subdirectory(udpsource)
add_subdirectory(localsource)
add_subdirectory(filesource)

Wyświetl plik

@ -0,0 +1,64 @@
project(modpacket)
set(modpacket_SOURCES
packetmod.cpp
packetmodbaseband.cpp
packetmodsource.cpp
packetmodplugin.cpp
packetmodsettings.cpp
packetmodwebapiadapter.cpp
)
set(modpacket_HEADERS
packetmod.h
packetmodbaseband.h
packetmodsource.h
packetmodplugin.h
packetmodsettings.h
packetmodwebapiadapter.h
)
include_directories(
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
)
if(NOT SERVER_MODE)
set(modpacket_SOURCES
${modpacket_SOURCES}
packetmodgui.cpp
packetmodgui.ui
packetmodrepeatdialog.cpp
packetmodrepeatdialog.ui
packetmodtxsettingsdialog.cpp
packetmodtxsettingsdialog.ui
)
set(modpacket_HEADERS
${modpacket_HEADERS}
packetmodgui.h
packetmodrepeatdialog.h
packetmodtxsettingsdialog.h
)
set(TARGET_NAME modpacket)
set(TARGET_LIB "Qt5::Widgets")
set(TARGET_LIB_GUI "sdrgui")
set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR})
else()
set(TARGET_NAME modpacketsrv)
set(TARGET_LIB "")
set(TARGET_LIB_GUI "")
set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR})
endif()
add_library(${TARGET_NAME} SHARED
${modpacket_SOURCES}
)
target_link_libraries(${TARGET_NAME}
Qt5::Core
${TARGET_LIB}
sdrbase
${TARGET_LIB_GUI}
swagger
)
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})

Wyświetl plik

@ -0,0 +1,573 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QTime>
#include <QDebug>
#include <QMutexLocker>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QBuffer>
#include <QThread>
#include "SWGChannelSettings.h"
#include "SWGChannelReport.h"
#include "SWGChannelActions.h"
#include "SWGPacketModReport.h"
#include "SWGPacketModActions.h"
#include "SWGPacketModActions_tx.h"
#include <stdio.h>
#include <complex.h>
#include <algorithm>
#include "dsp/dspengine.h"
#include "dsp/dspcommands.h"
#include "device/deviceapi.h"
#include "util/db.h"
#include "util/crc.h"
#include "packetmodbaseband.h"
#include "packetmod.h"
MESSAGE_CLASS_DEFINITION(PacketMod::MsgConfigurePacketMod, Message)
MESSAGE_CLASS_DEFINITION(PacketMod::MsgTXPacketMod, Message)
const QString PacketMod::m_channelIdURI = "sdrangel.channeltx.modpacket";
const QString PacketMod::m_channelId = "PacketMod";
PacketMod::PacketMod(DeviceAPI *deviceAPI) :
ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSource),
m_deviceAPI(deviceAPI),
m_spectrumVis(SDR_TX_SCALEF),
m_settingsMutex(QMutex::Recursive),
m_sampleRate(48000)
{
setObjectName(m_channelId);
m_thread = new QThread(this);
m_basebandSource = new PacketModBaseband();
m_basebandSource->setSpectrumSampleSink(&m_spectrumVis);
m_basebandSource->moveToThread(m_thread);
applySettings(m_settings, true);
m_deviceAPI->addChannelSource(this);
m_deviceAPI->addChannelSourceAPI(this);
m_networkManager = new QNetworkAccessManager();
connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
}
PacketMod::~PacketMod()
{
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
delete m_networkManager;
m_deviceAPI->removeChannelSourceAPI(this);
m_deviceAPI->removeChannelSource(this);
delete m_basebandSource;
delete m_thread;
}
void PacketMod::start()
{
qDebug("PacketMod::start");
m_basebandSource->reset();
m_thread->start();
}
void PacketMod::stop()
{
qDebug("PacketMod::stop");
m_thread->exit();
m_thread->wait();
}
void PacketMod::pull(SampleVector::iterator& begin, unsigned int nbSamples)
{
m_basebandSource->pull(begin, nbSamples);
}
bool PacketMod::handleMessage(const Message& cmd)
{
if (MsgConfigurePacketMod::match(cmd))
{
MsgConfigurePacketMod& cfg = (MsgConfigurePacketMod&) cmd;
qDebug() << "PacketMod::handleMessage: MsgConfigurePacketMod";
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
else if (MsgTXPacketMod::match(cmd))
{
// Forward a copy to baseband
MsgTXPacketMod* rep = new MsgTXPacketMod((MsgTXPacketMod&)cmd);
qDebug() << "PacketMod::handleMessage: MsgTXPacketMod";
m_basebandSource->getInputMessageQueue()->push(rep);
return true;
}
else if (DSPSignalNotification::match(cmd))
{
// Forward to the source
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy
qDebug() << "PacketMod::handleMessage: DSPSignalNotification";
m_basebandSource->getInputMessageQueue()->push(rep);
return true;
}
else
{
return false;
}
}
void PacketMod::applySettings(const PacketModSettings& settings, bool force)
{
qDebug() << "PacketMod::applySettings:"
<< " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset
<< " m_rfBandwidth: " << settings.m_rfBandwidth
<< " m_fmDeviation: " << settings.m_fmDeviation
<< " m_gain: " << settings.m_gain
<< " m_channelMute: " << settings.m_channelMute
<< " m_repeat: " << settings.m_repeat
<< " m_repeatDelay: " << settings.m_repeatDelay
<< " m_repeatCount: " << settings.m_repeatCount
<< " m_ax25PreFlags: " << settings.m_ax25PreFlags
<< " m_ax25PostFlags: " << settings.m_ax25PostFlags
<< " m_preEmphasis: " << settings.m_preEmphasis
<< " m_preEmphasisTau: " << settings.m_preEmphasisTau
<< " m_preEmphasisHighFreq: " << settings.m_preEmphasisHighFreq
<< " m_useReverseAPI: " << settings.m_useReverseAPI
<< " m_reverseAPIAddress: " << settings.m_reverseAPIAddress
<< " m_reverseAPIAddress: " << settings.m_reverseAPIPort
<< " m_reverseAPIDeviceIndex: " << settings.m_reverseAPIDeviceIndex
<< " m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex
<< " force: " << force;
QList<QString> reverseAPIKeys;
if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) {
reverseAPIKeys.append("inputFrequencyOffset");
}
if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) {
reverseAPIKeys.append("rfBandwidth");
}
if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force) {
reverseAPIKeys.append("fmDeviation");
}
if ((settings.m_gain != m_settings.m_gain) || force) {
reverseAPIKeys.append("gain");
}
if ((settings.m_channelMute != m_settings.m_channelMute) || force) {
reverseAPIKeys.append("channelMute");
}
if ((settings.m_repeat != m_settings.m_repeat) || force) {
reverseAPIKeys.append("repeat");
}
if ((settings.m_repeatDelay != m_settings.m_repeatDelay) || force) {
reverseAPIKeys.append("repeatDelay");
}
if ((settings.m_repeatCount != m_settings.m_repeatCount) || force) {
reverseAPIKeys.append("repeatCount");
}
if((settings.m_ax25PreFlags != m_settings.m_ax25PreFlags) || force) {
reverseAPIKeys.append("ax25PreFlags");
}
if((settings.m_ax25PostFlags != m_settings.m_ax25PostFlags) || force) {
reverseAPIKeys.append("ax25PostFlags");
}
if((settings.m_preEmphasis != m_settings.m_preEmphasis) || force) {
reverseAPIKeys.append("preEmphasis");
}
if((settings.m_preEmphasisTau != m_settings.m_preEmphasisTau) || force) {
reverseAPIKeys.append("preEmphasisTau");
}
if((settings.m_preEmphasisHighFreq != m_settings.m_preEmphasisHighFreq) || force) {
reverseAPIKeys.append("preEmphasisHighFreq");
}
if (m_settings.m_streamIndex != settings.m_streamIndex)
{
if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only
{
m_deviceAPI->removeChannelSourceAPI(this);
m_deviceAPI->removeChannelSource(this, m_settings.m_streamIndex);
m_deviceAPI->addChannelSource(this, settings.m_streamIndex);
m_deviceAPI->addChannelSourceAPI(this);
}
reverseAPIKeys.append("streamIndex");
}
PacketModBaseband::MsgConfigurePacketModBaseband *msg = PacketModBaseband::MsgConfigurePacketModBaseband::create(settings, force);
m_basebandSource->getInputMessageQueue()->push(msg);
if (settings.m_useReverseAPI)
{
bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
(m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) ||
(m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) ||
(m_settings.m_reverseAPIDeviceIndex != settings.m_reverseAPIDeviceIndex) ||
(m_settings.m_reverseAPIChannelIndex != settings.m_reverseAPIChannelIndex);
webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
}
m_settings = settings;
}
QByteArray PacketMod::serialize() const
{
return m_settings.serialize();
}
bool PacketMod::deserialize(const QByteArray& data)
{
bool success = true;
if (!m_settings.deserialize(data))
{
m_settings.resetToDefaults();
success = false;
}
MsgConfigurePacketMod *msg = MsgConfigurePacketMod::create(m_settings, true);
m_inputMessageQueue.push(msg);
return success;
}
int PacketMod::webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setPacketModSettings(new SWGSDRangel::SWGPacketModSettings());
response.getPacketModSettings()->init();
webapiFormatChannelSettings(response, m_settings);
return 200;
}
int PacketMod::webapiSettingsPutPatch(
bool force,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) errorMessage;
PacketModSettings settings = m_settings;
webapiUpdateChannelSettings(settings, channelSettingsKeys, response);
MsgConfigurePacketMod *msg = MsgConfigurePacketMod::create(settings, force);
m_inputMessageQueue.push(msg);
if (m_guiMessageQueue) // forward to GUI if any
{
MsgConfigurePacketMod *msgToGUI = MsgConfigurePacketMod::create(settings, force);
m_guiMessageQueue->push(msgToGUI);
}
webapiFormatChannelSettings(response, settings);
return 200;
}
void PacketMod::webapiUpdateChannelSettings(
PacketModSettings& settings,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response)
{
if (channelSettingsKeys.contains("inputFrequencyOffset")) {
settings.m_inputFrequencyOffset = response.getPacketModSettings()->getInputFrequencyOffset();
}
if (channelSettingsKeys.contains("rfBandwidth")) {
settings.m_rfBandwidth = response.getPacketModSettings()->getRfBandwidth();
}
if (channelSettingsKeys.contains("fmDeviation")) {
settings.m_fmDeviation = response.getPacketModSettings()->getFmDeviation();
}
if (channelSettingsKeys.contains("gain")) {
settings.m_gain = response.getPacketModSettings()->getGain();
}
if (channelSettingsKeys.contains("channelMute")) {
settings.m_channelMute = response.getPacketModSettings()->getChannelMute() != 0;
}
if (channelSettingsKeys.contains("repeat")) {
settings.m_repeat = response.getPacketModSettings()->getRepeat() != 0;
}
if (channelSettingsKeys.contains("repeatDelay")) {
settings.m_repeatDelay = response.getPacketModSettings()->getRepeatDelay();
}
if (channelSettingsKeys.contains("repeatCount")) {
settings.m_repeatCount = response.getPacketModSettings()->getRepeatCount();
}
if (channelSettingsKeys.contains("ax25PreFlags")) {
settings.m_ax25PreFlags = response.getPacketModSettings()->getAx25PreFlags();
}
if (channelSettingsKeys.contains("ax25PostFlags")) {
settings.m_ax25PostFlags = response.getPacketModSettings()->getAx25PostFlags();
}
if (channelSettingsKeys.contains("preEmphasis")) {
settings.m_preEmphasis = response.getPacketModSettings()->getPreEmphasis() != 0;
}
if (channelSettingsKeys.contains("preEmphasisTau")) {
settings.m_preEmphasisTau = response.getPacketModSettings()->getPreEmphasisTau();
}
if (channelSettingsKeys.contains("preEmphasisHighFreq")) {
settings.m_preEmphasisHighFreq = response.getPacketModSettings()->getPreEmphasisHighFreq();
}
if (channelSettingsKeys.contains("rgbColor")) {
settings.m_rgbColor = response.getPacketModSettings()->getRgbColor();
}
if (channelSettingsKeys.contains("title")) {
settings.m_title = *response.getPacketModSettings()->getTitle();
}
if (channelSettingsKeys.contains("streamIndex")) {
settings.m_streamIndex = response.getPacketModSettings()->getStreamIndex();
}
if (channelSettingsKeys.contains("useReverseAPI")) {
settings.m_useReverseAPI = response.getPacketModSettings()->getUseReverseApi() != 0;
}
if (channelSettingsKeys.contains("reverseAPIAddress")) {
settings.m_reverseAPIAddress = *response.getPacketModSettings()->getReverseApiAddress();
}
if (channelSettingsKeys.contains("reverseAPIPort")) {
settings.m_reverseAPIPort = response.getPacketModSettings()->getReverseApiPort();
}
if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
settings.m_reverseAPIDeviceIndex = response.getPacketModSettings()->getReverseApiDeviceIndex();
}
if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
settings.m_reverseAPIChannelIndex = response.getPacketModSettings()->getReverseApiChannelIndex();
}
}
int PacketMod::webapiReportGet(
SWGSDRangel::SWGChannelReport& response,
QString& errorMessage)
{
(void) errorMessage;
response.setPacketModReport(new SWGSDRangel::SWGPacketModReport());
response.getPacketModReport()->init();
webapiFormatChannelReport(response);
return 200;
}
int PacketMod::webapiActionsPost(
const QStringList& channelActionsKeys,
SWGSDRangel::SWGChannelActions& query,
QString& errorMessage)
{
SWGSDRangel::SWGPacketModActions *swgPacketModActions = query.getPacketModActions();
if (swgPacketModActions)
{
if (channelActionsKeys.contains("tx"))
{
SWGSDRangel::SWGPacketModActions_tx* tx = swgPacketModActions->getTx();
QString callsign(*tx->getCallsign());
QString to(*tx->getTo());
QString via(*tx->getVia());
QString data(*tx->getData());
PacketMod::MsgTXPacketMod *msg = PacketMod::MsgTXPacketMod::create(callsign, to, via, data);
m_basebandSource->getInputMessageQueue()->push(msg);
}
return 202;
}
else
{
errorMessage = "Missing PacketModActions in query";
return 400;
}
}
void PacketMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const PacketModSettings& settings)
{
response.getPacketModSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
response.getPacketModSettings()->setRfBandwidth(settings.m_rfBandwidth);
response.getPacketModSettings()->setFmDeviation(settings.m_fmDeviation);
response.getPacketModSettings()->setGain(settings.m_gain);
response.getPacketModSettings()->setChannelMute(settings.m_channelMute ? 1 : 0);
response.getPacketModSettings()->setRepeat(settings.m_repeat ? 1 : 0);
response.getPacketModSettings()->setRepeatDelay(settings.m_repeatDelay);
response.getPacketModSettings()->setRepeatCount(settings.m_repeatCount);
response.getPacketModSettings()->setAx25PreFlags(settings.m_ax25PreFlags);
response.getPacketModSettings()->setAx25PostFlags(settings.m_ax25PostFlags);
response.getPacketModSettings()->setPreEmphasis(settings.m_preEmphasis ? 1 : 0);
response.getPacketModSettings()->setPreEmphasisTau(settings.m_preEmphasisTau);
response.getPacketModSettings()->setPreEmphasisHighFreq(settings.m_preEmphasisHighFreq);
response.getPacketModSettings()->setRgbColor(settings.m_rgbColor);
if (response.getPacketModSettings()->getTitle()) {
*response.getPacketModSettings()->getTitle() = settings.m_title;
} else {
response.getPacketModSettings()->setTitle(new QString(settings.m_title));
}
response.getPacketModSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
if (response.getPacketModSettings()->getReverseApiAddress()) {
*response.getPacketModSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress;
} else {
response.getPacketModSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
}
response.getPacketModSettings()->setReverseApiPort(settings.m_reverseAPIPort);
response.getPacketModSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex);
response.getPacketModSettings()->setReverseApiChannelIndex(settings.m_reverseAPIChannelIndex);
}
void PacketMod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response)
{
response.getPacketModReport()->setChannelPowerDb(CalcDb::dbPower(getMagSq()));
response.getPacketModReport()->setChannelSampleRate(m_basebandSource->getChannelSampleRate());
}
void PacketMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const PacketModSettings& settings, bool force)
{
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
swgChannelSettings->setDirection(1); // single source (Tx)
swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet());
swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex());
swgChannelSettings->setChannelType(new QString("PacketMod"));
swgChannelSettings->setPacketModSettings(new SWGSDRangel::SWGPacketModSettings());
SWGSDRangel::SWGPacketModSettings *swgPacketModSettings = swgChannelSettings->getPacketModSettings();
// transfer data that has been modified. When force is on transfer all data except reverse API data
if (channelSettingsKeys.contains("inputFrequencyOffset") || force) {
swgPacketModSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
}
if (channelSettingsKeys.contains("rfBandwidth") || force) {
swgPacketModSettings->setRfBandwidth(settings.m_rfBandwidth);
}
if (channelSettingsKeys.contains("fmDeviation") || force) {
swgPacketModSettings->setFmDeviation(settings.m_fmDeviation);
}
if (channelSettingsKeys.contains("gain") || force) {
swgPacketModSettings->setGain(settings.m_gain);
}
if (channelSettingsKeys.contains("channelMute") || force) {
swgPacketModSettings->setChannelMute(settings.m_channelMute ? 1 : 0);
}
if (channelSettingsKeys.contains("repeat") || force) {
swgPacketModSettings->setRepeat(settings.m_repeat ? 1 : 0);
}
if (channelSettingsKeys.contains("repeatDelay") || force) {
swgPacketModSettings->setRepeatDelay(settings.m_repeatDelay);
}
if (channelSettingsKeys.contains("repeatCount") || force) {
swgPacketModSettings->setRepeatCount(settings.m_repeatCount);
}
if (channelSettingsKeys.contains("ax25PreFlags") || force) {
swgPacketModSettings->setAx25PreFlags(settings.m_ax25PreFlags);
}
if (channelSettingsKeys.contains("ax25PostFlags") || force) {
swgPacketModSettings->setAx25PostFlags(settings.m_ax25PostFlags);
}
if (channelSettingsKeys.contains("preEmphasis") || force) {
swgPacketModSettings->setPreEmphasis(settings.m_preEmphasis);
}
if (channelSettingsKeys.contains("preEmphasisTau") || force) {
swgPacketModSettings->setPreEmphasisTau(settings.m_preEmphasisTau);
}
if (channelSettingsKeys.contains("preEmphasisHighFreq") || force) {
swgPacketModSettings->setPreEmphasisHighFreq(settings.m_preEmphasisHighFreq);
}
if (channelSettingsKeys.contains("rgbColor") || force) {
swgPacketModSettings->setRgbColor(settings.m_rgbColor);
}
if (channelSettingsKeys.contains("title") || force) {
swgPacketModSettings->setTitle(new QString(settings.m_title));
}
if (channelSettingsKeys.contains("streamIndex") || force) {
swgPacketModSettings->setStreamIndex(settings.m_streamIndex);
}
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 PacketMod::networkManagerFinished(QNetworkReply *reply)
{
QNetworkReply::NetworkError replyError = reply->error();
if (replyError)
{
qWarning() << "PacketMod::networkManagerFinished:"
<< " error(" << (int) replyError
<< "): " << replyError
<< ": " << reply->errorString();
}
else
{
QString answer = reply->readAll();
answer.chop(1); // remove last \n
qDebug("PacketMod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
}
reply->deleteLater();
}
double PacketMod::getMagSq() const
{
return m_basebandSource->getMagSq();
}
void PacketMod::setLevelMeter(QObject *levelMeter)
{
connect(m_basebandSource, SIGNAL(levelChanged(qreal, qreal, int)), levelMeter, SLOT(levelChanged(qreal, qreal, int)));
}
uint32_t PacketMod::getNumberOfDeviceStreams() const
{
return m_deviceAPI->getNbSinkStreams();
}

Wyświetl plik

@ -0,0 +1,187 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016-2019 Edouard Griffiths, F4EXB //
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_CHANNELTX_MODPACKET_PACKETMOD_H_
#define PLUGINS_CHANNELTX_MODPACKET_PACKETMOD_H_
#include <vector>
#include <iostream>
#include <fstream>
#include <QMutex>
#include <QNetworkRequest>
#include "dsp/basebandsamplesource.h"
#include "dsp/spectrumvis.h"
#include "channel/channelapi.h"
#include "util/message.h"
#include "packetmodsettings.h"
class QNetworkAccessManager;
class QNetworkReply;
class QThread;
class DeviceAPI;
class PacketModBaseband;
class PacketMod : public BasebandSampleSource, public ChannelAPI {
Q_OBJECT
public:
class MsgConfigurePacketMod : public Message {
MESSAGE_CLASS_DECLARATION
public:
const PacketModSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigurePacketMod* create(const PacketModSettings& settings, bool force)
{
return new MsgConfigurePacketMod(settings, force);
}
private:
PacketModSettings m_settings;
bool m_force;
MsgConfigurePacketMod(const PacketModSettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
class MsgTXPacketMod : public Message {
MESSAGE_CLASS_DECLARATION
public:
static MsgTXPacketMod* create(QString callsign, QString to, QString via, QString data)
{
return new MsgTXPacketMod(callsign, to, via, data);
}
QString m_callsign;
QString m_to;
QString m_via;
QString m_data;
private:
MsgTXPacketMod(QString callsign, QString to, QString via, QString data) :
Message(),
m_callsign(callsign),
m_to(to),
m_via(via),
m_data(data)
{ }
};
//=================================================================
PacketMod(DeviceAPI *deviceAPI);
~PacketMod();
virtual void destroy() { delete this; }
virtual void start();
virtual void stop();
virtual void pull(SampleVector::iterator& begin, unsigned int nbSamples);
virtual bool handleMessage(const Message& cmd);
virtual void getIdentifier(QString& id) { id = objectName(); }
virtual void getTitle(QString& title) { title = m_settings.m_title; }
virtual qint64 getCenterFrequency() const { return m_settings.m_inputFrequencyOffset; }
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 webapiSettingsPutPatch(
bool force,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage);
virtual int webapiReportGet(
SWGSDRangel::SWGChannelReport& response,
QString& errorMessage);
virtual int webapiActionsPost(
const QStringList& channelActionsKeys,
SWGSDRangel::SWGChannelActions& query,
QString& errorMessage);
static void webapiFormatChannelSettings(
SWGSDRangel::SWGChannelSettings& response,
const PacketModSettings& settings);
static void webapiUpdateChannelSettings(
PacketModSettings& settings,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response);
SpectrumVis *getSpectrumVis() { return &m_spectrumVis; }
double getMagSq() const;
void setLevelMeter(QObject *levelMeter);
uint32_t getNumberOfDeviceStreams() const;
static const QString m_channelIdURI;
static const QString m_channelId;
private:
enum RateState {
RSInitialFill,
RSRunning
};
DeviceAPI* m_deviceAPI;
QThread *m_thread;
PacketModBaseband* m_basebandSource;
PacketModSettings m_settings;
SpectrumVis m_spectrumVis;
SampleVector m_sampleBuffer;
QMutex m_settingsMutex;
int m_sampleRate;
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
void applySettings(const PacketModSettings& settings, bool force = false);
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const PacketModSettings& settings, bool force);
private slots:
void networkManagerFinished(QNetworkReply *reply);
};
#endif /* PLUGINS_CHANNELTX_MODPACKET_PACKETMOD_H_ */

Wyświetl plik

@ -0,0 +1,189 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QDebug>
#include "dsp/upchannelizer.h"
#include "dsp/dspengine.h"
#include "dsp/dspcommands.h"
#include "packetmodbaseband.h"
#include "packetmod.h"
MESSAGE_CLASS_DEFINITION(PacketModBaseband::MsgConfigurePacketModBaseband, Message)
PacketModBaseband::PacketModBaseband() :
m_mutex(QMutex::Recursive)
{
m_sampleFifo.resize(SampleSourceFifo::getSizePolicy(48000));
m_channelizer = new UpChannelizer(&m_source);
qDebug("PacketModBaseband::PacketModBaseband");
QObject::connect(
&m_sampleFifo,
&SampleSourceFifo::dataRead,
this,
&PacketModBaseband::handleData,
Qt::QueuedConnection
);
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
}
PacketModBaseband::~PacketModBaseband()
{
delete m_channelizer;
}
void PacketModBaseband::reset()
{
QMutexLocker mutexLocker(&m_mutex);
m_sampleFifo.reset();
}
void PacketModBaseband::pull(const SampleVector::iterator& begin, unsigned int nbSamples)
{
unsigned int part1Begin, part1End, part2Begin, part2End;
m_sampleFifo.read(nbSamples, part1Begin, part1End, part2Begin, part2End);
SampleVector& data = m_sampleFifo.getData();
if (part1Begin != part1End)
{
std::copy(
data.begin() + part1Begin,
data.begin() + part1End,
begin
);
}
unsigned int shift = part1End - part1Begin;
if (part2Begin != part2End)
{
std::copy(
data.begin() + part2Begin,
data.begin() + part2End,
begin + shift
);
}
}
void PacketModBaseband::handleData()
{
QMutexLocker mutexLocker(&m_mutex);
SampleVector& data = m_sampleFifo.getData();
unsigned int ipart1begin;
unsigned int ipart1end;
unsigned int ipart2begin;
unsigned int ipart2end;
qreal rmsLevel, peakLevel;
int numSamples;
unsigned int remainder = m_sampleFifo.remainder();
while ((remainder > 0) && (m_inputMessageQueue.size() == 0))
{
m_sampleFifo.write(remainder, ipart1begin, ipart1end, ipart2begin, ipart2end);
if (ipart1begin != ipart1end) { // first part of FIFO data
processFifo(data, ipart1begin, ipart1end);
}
if (ipart2begin != ipart2end) { // second part of FIFO data (used when block wraps around)
processFifo(data, ipart2begin, ipart2end);
}
remainder = m_sampleFifo.remainder();
}
m_source.getLevels(rmsLevel, peakLevel, numSamples);
emit levelChanged(rmsLevel, peakLevel, numSamples);
}
void PacketModBaseband::processFifo(SampleVector& data, unsigned int iBegin, unsigned int iEnd)
{
m_channelizer->prefetch(iEnd - iBegin);
m_channelizer->pull(data.begin() + iBegin, iEnd - iBegin);
}
void PacketModBaseband::handleInputMessages()
{
Message* message;
while ((message = m_inputMessageQueue.pop()) != nullptr)
{
if (handleMessage(*message)) {
delete message;
}
}
}
bool PacketModBaseband::handleMessage(const Message& cmd)
{
if (MsgConfigurePacketModBaseband::match(cmd))
{
QMutexLocker mutexLocker(&m_mutex);
MsgConfigurePacketModBaseband& cfg = (MsgConfigurePacketModBaseband&) cmd;
qDebug() << "PacketModBaseband::handleMessage: MsgConfigurePacketModBaseband";
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
else if (PacketMod::MsgTXPacketMod::match(cmd))
{
PacketMod::MsgTXPacketMod& tx = (PacketMod::MsgTXPacketMod&) cmd;
m_source.addTXPacket(tx.m_callsign, tx.m_to, tx.m_via, tx.m_data);
return true;
}
else if (DSPSignalNotification::match(cmd))
{
QMutexLocker mutexLocker(&m_mutex);
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
qDebug() << "PacketModBaseband::handleMessage: DSPSignalNotification: basebandSampleRate: " << notif.getSampleRate();
m_sampleFifo.resize(SampleSourceFifo::getSizePolicy(notif.getSampleRate()));
m_channelizer->setBasebandSampleRate(notif.getSampleRate());
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
return true;
}
else
{
qDebug() << "PacketModBaseband - Baseband got unknown message";
return false;
}
}
void PacketModBaseband::applySettings(const PacketModSettings& settings, bool force)
{
if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force)
{
m_channelizer->setChannelization(m_channelizer->getChannelSampleRate(), settings.m_inputFrequencyOffset);
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
}
m_source.applySettings(settings, force);
m_settings = settings;
}
int PacketModBaseband::getChannelSampleRate() const
{
return m_channelizer->getChannelSampleRate();
}

Wyświetl plik

@ -0,0 +1,97 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_PACKETMODBASEBAND_H
#define INCLUDE_PACKETMODBASEBAND_H
#include <QObject>
#include <QMutex>
#include "dsp/samplesourcefifo.h"
#include "util/message.h"
#include "util/messagequeue.h"
#include "packetmodsource.h"
class UpChannelizer;
class PacketModBaseband : public QObject
{
Q_OBJECT
public:
class MsgConfigurePacketModBaseband : public Message {
MESSAGE_CLASS_DECLARATION
public:
const PacketModSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigurePacketModBaseband* create(const PacketModSettings& settings, bool force)
{
return new MsgConfigurePacketModBaseband(settings, force);
}
private:
PacketModSettings m_settings;
bool m_force;
MsgConfigurePacketModBaseband(const PacketModSettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
PacketModBaseband();
~PacketModBaseband();
void reset();
void pull(const SampleVector::iterator& begin, unsigned int nbSamples);
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
double getMagSq() const { return m_source.getMagSq(); }
int getChannelSampleRate() const;
void setSpectrumSampleSink(BasebandSampleSink* sampleSink) { m_source.setSpectrumSink(sampleSink); }
signals:
/**
* Level changed
* \param rmsLevel RMS level in range 0.0 - 1.0
* \param peakLevel Peak level in range 0.0 - 1.0
* \param numSamples Number of audio samples analyzed
*/
void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples);
private:
SampleSourceFifo m_sampleFifo;
UpChannelizer *m_channelizer;
PacketModSource m_source;
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
PacketModSettings m_settings;
QMutex m_mutex;
void processFifo(SampleVector& data, unsigned int iBegin, unsigned int iEnd);
bool handleMessage(const Message& cmd);
void applySettings(const PacketModSettings& settings, bool force = false);
private slots:
void handleInputMessages();
void handleData(); //!< Handle data when samples have to be processed
};
#endif // INCLUDE_PACKETMODBASEBAND_H

Wyświetl plik

@ -0,0 +1,527 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QDockWidget>
#include <QMainWindow>
#include <QFileDialog>
#include <QTime>
#include <QDebug>
#include "dsp/spectrumvis.h"
#include "device/deviceuiset.h"
#include "plugin/pluginapi.h"
#include "util/simpleserializer.h"
#include "util/db.h"
#include "dsp/dspengine.h"
#include "gui/glspectrum.h"
#include "gui/crightclickenabler.h"
#include "gui/basicchannelsettingsdialog.h"
#include "gui/devicestreamselectiondialog.h"
#include "gui/fmpreemphasisdialog.h"
#include "mainwindow.h"
#include "ui_packetmodgui.h"
#include "packetmodgui.h"
#include "packetmodrepeatdialog.h"
#include "packetmodtxsettingsdialog.h"
PacketModGUI* PacketModGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx)
{
PacketModGUI* gui = new PacketModGUI(pluginAPI, deviceUISet, channelTx);
return gui;
}
void PacketModGUI::destroy()
{
delete this;
}
void PacketModGUI::setName(const QString& name)
{
setObjectName(name);
}
QString PacketModGUI::getName() const
{
return objectName();
}
qint64 PacketModGUI::getCenterFrequency() const {
return m_channelMarker.getCenterFrequency();
}
void PacketModGUI::setCenterFrequency(qint64 centerFrequency)
{
m_channelMarker.setCenterFrequency(centerFrequency);
applySettings();
}
void PacketModGUI::resetToDefaults()
{
m_settings.resetToDefaults();
displaySettings();
applySettings(true);
}
QByteArray PacketModGUI::serialize() const
{
return m_settings.serialize();
}
bool PacketModGUI::deserialize(const QByteArray& data)
{
if(m_settings.deserialize(data)) {
displaySettings();
applySettings(true);
return true;
} else {
resetToDefaults();
return false;
}
}
bool PacketModGUI::handleMessage(const Message& message)
{
if (PacketMod::MsgConfigurePacketMod::match(message))
{
const PacketMod::MsgConfigurePacketMod& cfg = (PacketMod::MsgConfigurePacketMod&) message;
m_settings = cfg.getSettings();
blockApplySettings(true);
displaySettings();
blockApplySettings(false);
return true;
}
else
{
return false;
}
}
void PacketModGUI::channelMarkerChangedByCursor()
{
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
applySettings();
}
void PacketModGUI::handleSourceMessages()
{
Message* message;
while ((message = getInputMessageQueue()->pop()) != 0)
{
if (handleMessage(*message))
{
delete message;
}
}
}
void PacketModGUI::on_deltaFrequency_changed(qint64 value)
{
m_channelMarker.setCenterFrequency(value);
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
applySettings();
}
void PacketModGUI::on_rfBW_valueChanged(int value)
{
float bw = value * 100.0f;
ui->rfBWText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1));
m_channelMarker.setBandwidth(bw);
m_settings.m_rfBandwidth = bw;
applySettings();
}
void PacketModGUI::on_fmDev_valueChanged(int value)
{
ui->fmDevText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1));
m_settings.m_fmDeviation = value * 100.0;
applySettings();
}
void PacketModGUI::on_gain_valueChanged(int value)
{
ui->gainText->setText(QString("%1dB").arg(value));
m_settings.m_gain = value;
applySettings();
}
void PacketModGUI::on_channelMute_toggled(bool checked)
{
m_settings.m_channelMute = checked;
applySettings();
}
void PacketModGUI::on_txButton_clicked(bool checked)
{
transmit();
}
void PacketModGUI::on_packet_returnPressed()
{
transmit();
}
void PacketModGUI::on_callsign_editingFinished()
{
m_settings.m_callsign = ui->callsign->text();
applySettings();
}
void PacketModGUI::on_to_currentTextChanged(const QString &text)
{
m_settings.m_to = text;
applySettings();
}
void PacketModGUI::on_via_currentTextChanged(const QString &text)
{
m_settings.m_via = text;
applySettings();
}
void PacketModGUI::on_packet_editingFinished()
{
m_settings.m_data = ui->packet->text();
applySettings();
}
void PacketModGUI::on_insertPosition_clicked(bool checked)
{
float latitude = MainWindow::getInstance()->getMainSettings().getLatitude();
float longitude = MainWindow::getInstance()->getMainSettings().getLongitude();
int latDeg, latMin, latFrac, latNorth;
int longDeg, longMin, longFrac, longEast;
char latBuf[10];
char longBuf[11];
// Convert decimal latitude to degrees, min and hundreths of a minute
latNorth = latitude >= 0.0f;
latitude = abs(latitude);
latDeg = (int)latitude;
latitude -= (float)latDeg;
latitude *= 60.0f;
latMin = (int)latitude;
latitude -= (float)latMin;
latitude *= 100.0f;
latFrac = round(latitude);
// Convert decimal longitude
longEast = longitude >= 0.0f;
longitude = abs(longitude);
longDeg = (int)longitude;
longitude -= (float)longDeg;
longitude *= 60.0f;
longMin = (int)longitude;
longitude -= (float)longMin;
longitude *= 100.0f;
longFrac = round(longitude);
// Insert position with house symbol (-) in to data field
sprintf(latBuf, "%02d%02d.%02d%c", latDeg, latMin, latFrac, latNorth ? 'N' : 'S');
sprintf(longBuf, "%03d%02d.%02d%c", longDeg, longMin, longFrac, longEast ? 'E' : 'W');
QString packet = QString("%1/%2-").arg(latBuf).arg(longBuf);
ui->packet->insert(packet);
}
void PacketModGUI::on_repeat_toggled(bool checked)
{
m_settings.m_repeat = checked;
applySettings();
}
void PacketModGUI::on_preEmphasis_toggled(bool checked)
{
m_settings.m_preEmphasis = checked;
applySettings();
}
void PacketModGUI::preEmphasisSelect()
{
FMPreemphasisDialog dialog(m_settings.m_preEmphasisTau, m_settings.m_preEmphasisHighFreq);
if (dialog.exec() == QDialog::Accepted)
{
m_settings.m_preEmphasisTau = dialog.m_tau;
m_settings.m_preEmphasisHighFreq = dialog.m_highFreq;
applySettings();
}
}
void PacketModGUI::repeatSelect()
{
PacketModRepeatDialog dialog(m_settings.m_repeatDelay, m_settings.m_repeatCount);
if (dialog.exec() == QDialog::Accepted)
{
m_settings.m_repeatDelay = dialog.m_repeatDelay;
m_settings.m_repeatCount = dialog.m_repeatCount;
applySettings();
}
}
void PacketModGUI::txSettingsSelect()
{
PacketModTXSettingsDialog dialog(m_settings.m_rampUpBits, m_settings.m_rampDownBits,
m_settings.m_rampRange, m_settings.m_modulateWhileRamping,
m_settings.m_markFrequency, m_settings.m_spaceFrequency,
m_settings.m_ax25PreFlags, m_settings.m_ax25PostFlags,
m_settings.m_ax25Control, m_settings.m_ax25PID,
m_settings.m_lpfTaps,
m_settings.m_bbNoise, m_settings.m_rfNoise,
m_settings.m_writeToFile);
if (dialog.exec() == QDialog::Accepted)
{
m_settings.m_rampUpBits = dialog.m_rampUpBits;
m_settings.m_rampDownBits = dialog.m_rampDownBits;
m_settings.m_rampRange = dialog.m_rampRange;
m_settings.m_modulateWhileRamping = dialog.m_modulateWhileRamping;
m_settings.m_markFrequency = dialog.m_markFrequency;
m_settings.m_spaceFrequency = dialog.m_spaceFrequency;
m_settings.m_ax25PreFlags = dialog.m_ax25PreFlags;
m_settings.m_ax25PostFlags = dialog.m_ax25PostFlags;
m_settings.m_ax25Control = dialog.m_ax25Control;
m_settings.m_ax25PID = dialog.m_ax25PID;
m_settings.m_lpfTaps = dialog.m_lpfTaps;
m_settings.m_bbNoise = dialog.m_bbNoise;
m_settings.m_rfNoise = dialog.m_rfNoise;
m_settings.m_writeToFile = dialog.m_writeToFile;
applySettings();
}
}
void PacketModGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
(void) widget;
(void) rollDown;
}
void PacketModGUI::onMenuDialogCalled(const QPoint &p)
{
if (m_contextMenuType == ContextMenuChannelSettings)
{
BasicChannelSettingsDialog dialog(&m_channelMarker, this);
dialog.setUseReverseAPI(m_settings.m_useReverseAPI);
dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress);
dialog.setReverseAPIPort(m_settings.m_reverseAPIPort);
dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex);
dialog.setReverseAPIChannelIndex(m_settings.m_reverseAPIChannelIndex);
dialog.move(p);
dialog.exec();
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
m_settings.m_rgbColor = m_channelMarker.getColor().rgb();
m_settings.m_title = m_channelMarker.getTitle();
m_settings.m_useReverseAPI = dialog.useReverseAPI();
m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress();
m_settings.m_reverseAPIPort = dialog.getReverseAPIPort();
m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex();
m_settings.m_reverseAPIChannelIndex = dialog.getReverseAPIChannelIndex();
setWindowTitle(m_settings.m_title);
setTitleColor(m_settings.m_rgbColor);
applySettings();
}
else if ((m_contextMenuType == ContextMenuStreamSettings) && (m_deviceUISet->m_deviceMIMOEngine))
{
DeviceStreamSelectionDialog dialog(this);
dialog.setNumberOfStreams(m_packetMod->getNumberOfDeviceStreams());
dialog.setStreamIndex(m_settings.m_streamIndex);
dialog.move(p);
dialog.exec();
m_settings.m_streamIndex = dialog.getSelectedStreamIndex();
m_channelMarker.clearStreamIndexes();
m_channelMarker.addStreamIndex(m_settings.m_streamIndex);
displayStreamIndex();
applySettings();
}
resetContextMenuType();
}
PacketModGUI::PacketModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx, QWidget* parent) :
RollupWidget(parent),
ui(new Ui::PacketModGUI),
m_pluginAPI(pluginAPI),
m_deviceUISet(deviceUISet),
m_channelMarker(this),
m_doApplySettings(true)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose, true);
connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
m_packetMod = (PacketMod*) channelTx;
m_packetMod->setMessageQueueToGUI(getInputMessageQueue());
connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
m_spectrumVis = m_packetMod->getSpectrumVis();
m_spectrumVis->setGLSpectrum(ui->glSpectrum);
// Extra /2 here because SSB?
ui->glSpectrum->setCenterFrequency(m_settings.m_spectrumRate/4);
ui->glSpectrum->setSampleRate(m_settings.m_spectrumRate/2);
ui->glSpectrum->setSsbSpectrum(true);
ui->glSpectrum->setDisplayCurrent(true);
ui->glSpectrum->setLsbDisplay(false);
ui->glSpectrum->setDisplayWaterfall(false);
ui->glSpectrum->setDisplayMaxHold(false);
ui->glSpectrum->setDisplayHistogram(false);
ui->glSpectrum->connectTimer(MainWindow::getInstance()->getMasterTimer());
CRightClickEnabler *repeatRightClickEnabler = new CRightClickEnabler(ui->repeat);
connect(repeatRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(repeatSelect()));
CRightClickEnabler *txRightClickEnabler = new CRightClickEnabler(ui->txButton);
connect(txRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(txSettingsSelect()));
CRightClickEnabler *preempRightClickEnabler = new CRightClickEnabler(ui->preEmphasis);
connect(preempRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(preEmphasisSelect()));
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
m_channelMarker.blockSignals(true);
m_channelMarker.setColor(Qt::red);
m_channelMarker.setBandwidth(12500);
m_channelMarker.setCenterFrequency(0);
m_channelMarker.setTitle("Packet Modulator");
m_channelMarker.setSourceOrSinkStream(false);
m_channelMarker.blockSignals(false);
m_channelMarker.setVisible(true); // activate signal on the last setting only
m_deviceUISet->registerTxChannelInstance(PacketMod::m_channelIdURI, this);
m_deviceUISet->addChannelMarker(&m_channelMarker);
m_deviceUISet->addRollupWidget(this);
connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor()));
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
m_packetMod->setLevelMeter(ui->volumeMeter);
m_settings.setChannelMarker(&m_channelMarker);
ui->spectrumGUI->setBuddies(m_spectrumVis, ui->glSpectrum);
displaySettings();
applySettings();
}
PacketModGUI::~PacketModGUI()
{
m_deviceUISet->removeTxChannelInstance(this);
delete m_packetMod; // TODO: check this: when the GUI closes it has to delete the modulator
delete ui;
}
void PacketModGUI::transmit()
{
QString callsign = ui->callsign->text();
QString to = ui->to->currentText();
QString via = ui->via->currentText();
QString data = ui->packet->text();
// TODO: Any validation?
QString str = callsign + ">" + to + "," + via + ":" + data;
ui->transmittedText->appendPlainText(str + "\n");
PacketMod::MsgTXPacketMod *msg = PacketMod::MsgTXPacketMod::create(callsign, to, via, data);
m_packetMod->getInputMessageQueue()->push(msg);
}
void PacketModGUI::blockApplySettings(bool block)
{
m_doApplySettings = !block;
}
void PacketModGUI::applySettings(bool force)
{
if (m_doApplySettings)
{
PacketMod::MsgConfigurePacketMod *msg = PacketMod::MsgConfigurePacketMod::create(m_settings, force);
m_packetMod->getInputMessageQueue()->push(msg);
}
}
void PacketModGUI::displaySettings()
{
m_channelMarker.blockSignals(true);
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
m_channelMarker.setTitle(m_settings.m_title);
m_channelMarker.setBandwidth(m_settings.m_rfBandwidth);
m_channelMarker.blockSignals(false);
m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only
setTitleColor(m_settings.m_rgbColor);
setWindowTitle(m_channelMarker.getTitle());
displayStreamIndex();
blockApplySettings(true);
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
ui->rfBWText->setText(QString("%1k").arg(m_settings.m_rfBandwidth / 1000.0, 0, 'f', 1));
ui->rfBW->setValue(m_settings.m_rfBandwidth / 100.0);
ui->fmDevText->setText(QString("%1k").arg(m_settings.m_fmDeviation / 1000.0, 0, 'f', 1));
ui->fmDev->setValue(m_settings.m_fmDeviation / 100.0);
ui->gainText->setText(QString("%1").arg((double)m_settings.m_gain, 0, 'f', 1));
ui->gain->setValue(m_settings.m_gain);
ui->channelMute->setChecked(m_settings.m_channelMute);
ui->repeat->setChecked(m_settings.m_repeat);
ui->callsign->setText(m_settings.m_callsign);
ui->to->lineEdit()->setText(m_settings.m_to);
ui->via->lineEdit()->setText(m_settings.m_via);
ui->packet->setText(m_settings.m_data);
blockApplySettings(false);
}
void PacketModGUI::displayStreamIndex()
{
if (m_deviceUISet->m_deviceMIMOEngine) {
setStreamIndicator(tr("%1").arg(m_settings.m_streamIndex));
} else {
setStreamIndicator("S"); // single channel indicator
}
}
void PacketModGUI::leaveEvent(QEvent*)
{
m_channelMarker.setHighlighted(false);
}
void PacketModGUI::enterEvent(QEvent*)
{
m_channelMarker.setHighlighted(true);
}
void PacketModGUI::tick()
{
double powDb = CalcDb::dbPower(m_packetMod->getMagSq());
m_channelPowerDbAvg(powDb);
ui->channelPower->setText(tr("%1 dB").arg(m_channelPowerDbAvg.asDouble(), 0, 'f', 1));
}

Wyświetl plik

@ -0,0 +1,114 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_CHANNELTX_MODPACKET_PACKETMODGUI_H_
#define PLUGINS_CHANNELTX_MODPACKET_PACKETMODGUI_H_
#include <plugin/plugininstancegui.h>
#include "gui/rollupwidget.h"
#include "dsp/channelmarker.h"
#include "util/movingaverage.h"
#include "util/messagequeue.h"
#include "packetmod.h"
#include "packetmodsettings.h"
class PluginAPI;
class DeviceUISet;
class BasebandSampleSource;
class SpectrumVis;
namespace Ui {
class PacketModGUI;
}
class PacketModGUI : public RollupWidget, public PluginInstanceGUI {
Q_OBJECT
public:
static PacketModGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx);
virtual void destroy();
void setName(const QString& name);
QString getName() const;
virtual qint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
virtual bool handleMessage(const Message& message);
public slots:
void channelMarkerChangedByCursor();
private:
Ui::PacketModGUI* ui;
PluginAPI* m_pluginAPI;
DeviceUISet* m_deviceUISet;
ChannelMarker m_channelMarker;
PacketModSettings m_settings;
bool m_doApplySettings;
SpectrumVis* m_spectrumVis;
PacketMod* m_packetMod;
MovingAverageUtil<double, double, 2> m_channelPowerDbAvg; // Less than other mods, as packets are short
MessageQueue m_inputMessageQueue;
explicit PacketModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx, QWidget* parent = 0);
virtual ~PacketModGUI();
void transmit();
void blockApplySettings(bool block);
void applySettings(bool force = false);
void displaySettings();
void displayStreamIndex();
void leaveEvent(QEvent*);
void enterEvent(QEvent*);
private slots:
void handleSourceMessages();
void on_deltaFrequency_changed(qint64 value);
void on_rfBW_valueChanged(int index);
void on_fmDev_valueChanged(int value);
void on_gain_valueChanged(int value);
void on_channelMute_toggled(bool checked);
void on_txButton_clicked(bool checked);
void on_callsign_editingFinished();
void on_to_currentTextChanged(const QString &text);
void on_via_currentTextChanged(const QString &text);
void on_packet_editingFinished();
void on_insertPosition_clicked(bool checked);
void on_packet_returnPressed();
void on_repeat_toggled(bool checked);
void on_preEmphasis_toggled(bool checked);
void preEmphasisSelect();
void repeatSelect();
void txSettingsSelect();
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDialogCalled(const QPoint& p);
void tick();
};
#endif /* PLUGINS_CHANNELTX_MODPACKET_PACKETMODGUI_H_ */

Wyświetl plik

@ -0,0 +1,817 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PacketModGUI</class>
<widget class="RollupWidget" name="PacketModGUI">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>363</width>
<height>610</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="windowTitle">
<string>Packet Modulator</string>
</property>
<widget class="QWidget" name="settingsContainer" native="true">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>2</x>
<y>2</y>
<width>341</width>
<height>181</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>280</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<layout class="QHBoxLayout" name="deltaFreqPowLayout">
<property name="topMargin">
<number>2</number>
</property>
<item>
<layout class="QHBoxLayout" name="deltaFrequencyLayout">
<item>
<widget class="QLabel" name="deltaFrequencyLabel">
<property name="minimumSize">
<size>
<width>16</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Df</string>
</property>
</widget>
</item>
<item>
<widget class="ValueDialZ" name="deltaFrequency" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>16</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Mono</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>Demod shift frequency from center in Hz</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="deltaUnits">
<property name="text">
<string>Hz </string>
</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>
<item>
<widget class="QLabel" name="channelPower">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Channel power</string>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>-100.0 dB</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QToolButton" name="channelMute">
<property name="toolTip">
<string>Mute/Unmute channel</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/txon.png</normaloff>
<normalon>:/txoff.png</normalon>:/txon.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="rfBandwidthLayout">
<item>
<widget class="QComboBox" name="mode">
<property name="minimumSize">
<size>
<width>90</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Baud rate and modulation</string>
</property>
<item>
<property name="text">
<string>1200 AFSK</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="rfBWLabel">
<property name="text">
<string>BW</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="rfBW">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>RF bandwidth</string>
</property>
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>400</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="rfBWText">
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>10.0k</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="fmDevLabel">
<property name="text">
<string>Dev</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="fmDev">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Frequency deviation</string>
</property>
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>60</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="fmDevText">
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>5.0k</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="volumeLayout">
<item>
<widget class="QLabel" name="gainLabel">
<property name="text">
<string>Gain</string>
</property>
</widget>
</item>
<item>
<widget class="QDial" name="gain">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>Gain</string>
</property>
<property name="minimum">
<number>-60</number>
</property>
<property name="maximum">
<number>0</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="gainText">
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Audio input gain value</string>
</property>
<property name="statusTip">
<string/>
</property>
<property name="text">
<string>-80.0dB</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="LevelMeterVU" name="volumeMeter" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Liberation Mono</family>
<pointsize>8</pointsize>
</font>
</property>
<property name="toolTip">
<string>Level (% full range) top trace: average, bottom trace: instantaneous peak, tip: peak hold</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="callsignLayout">
<item>
<widget class="QLabel" name="callsignLabel">
<property name="text">
<string>Callsign</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="callsign">
<property name="toolTip">
<string>Enter your amateur radio callsign and optionally a SSID. E.g. M7RCE or M7RCE-1</string>
</property>
<property name="text">
<string>MYCALL</string>
</property>
<property name="maxLength">
<number>10</number>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="preEmphasis">
<property name="toolTip">
<string>Preemphasis filter. Right click for additional settings.</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/filter_highpass.png</normaloff>:/filter_highpass.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="repeat">
<property name="toolTip">
<string>Repeatedly transmit the packet. Right click for additional settings.</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/playloop.png</normaloff>:/playloop.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="insertPosition">
<property name="toolTip">
<string>Insert position (latitude and longitude)</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset>
<normalon>:/gps.png</normalon>
</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="routingLayout">
<item>
<widget class="QLabel" name="toLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>To</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="to">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Enter destination</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
<property name="currentText">
<string>APRS</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<item>
<property name="text">
<string>APRS</string>
</property>
</item>
<item>
<property name="text">
<string>APZ</string>
</property>
</item>
<item>
<property name="text">
<string>CQ</string>
</property>
</item>
<item>
<property name="text">
<string>BEACON</string>
</property>
</item>
<item>
<property name="text">
<string>CALLSIGN-SSID</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="viaLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Via</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="via">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>160</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Enter routing</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string>WIDE2-2</string>
</property>
</item>
<item>
<property name="text">
<string>ARISS</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="packetDataLayout">
<item>
<widget class="QLabel" name="label">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Data</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="packet">
<property name="toolTip">
<string>Enter data to transmit.
APRS examples:
&gt;Status
:Addressee:Message
!Position</string>
</property>
<property name="text">
<string>&gt;Using SDRangel</string>
</property>
<property name="maxLength">
<number>256</number>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="txButton">
<property name="toolTip">
<string>Press to transmit the packet</string>
</property>
<property name="text">
<string>TX</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="logContainer" native="true">
<property name="geometry">
<rect>
<x>0</x>
<y>190</y>
<width>351</width>
<height>141</height>
</rect>
</property>
<property name="windowTitle">
<string>Transmitted Packets</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>2</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QPlainTextEdit" name="transmittedText">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="spectrumContainer" native="true">
<property name="geometry">
<rect>
<x>0</x>
<y>340</y>
<width>351</width>
<height>284</height>
</rect>
</property>
<property name="windowTitle">
<string>Baseband Spectrum</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>2</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="GLSpectrum" name="glSpectrum" native="true">
<property name="minimumSize">
<size>
<width>200</width>
<height>250</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Mono</family>
<pointsize>8</pointsize>
</font>
</property>
</widget>
</item>
<item>
<widget class="GLSpectrumGUI" name="spectrumGUI" native="true"/>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>RollupWidget</class>
<extends>QWidget</extends>
<header>gui/rollupwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>GLSpectrum</class>
<extends>QWidget</extends>
<header>gui/glspectrum.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>GLSpectrumGUI</class>
<extends>QWidget</extends>
<header>gui/glspectrumgui.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LevelMeterVU</class>
<extends>QWidget</extends>
<header>gui/levelmeter.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ButtonSwitch</class>
<extends>QToolButton</extends>
<header>gui/buttonswitch.h</header>
</customwidget>
<customwidget>
<class>ValueDialZ</class>
<extends>QWidget</extends>
<header>gui/valuedialz.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>deltaFrequency</tabstop>
<tabstop>channelMute</tabstop>
<tabstop>mode</tabstop>
<tabstop>rfBW</tabstop>
<tabstop>fmDev</tabstop>
<tabstop>gain</tabstop>
<tabstop>callsign</tabstop>
<tabstop>preEmphasis</tabstop>
<tabstop>repeat</tabstop>
<tabstop>insertPosition</tabstop>
<tabstop>to</tabstop>
<tabstop>via</tabstop>
<tabstop>packet</tabstop>
<tabstop>txButton</tabstop>
<tabstop>transmittedText</tabstop>
</tabstops>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections/>
</ui>

Wyświetl plik

@ -0,0 +1,84 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QtPlugin>
#include "plugin/pluginapi.h"
#ifndef SERVER_MODE
#include "packetmodgui.h"
#endif
#include "packetmod.h"
#include "packetmodwebapiadapter.h"
#include "packetmodplugin.h"
const PluginDescriptor PacketModPlugin::m_pluginDescriptor = {
PacketMod::m_channelId,
QString("Packet Modulator"),
QString("4.16.1"),
QString("(c) Jon Beniston, M7RCE"),
QString("https://github.com/f4exb/sdrangel"),
true,
QString("https://github.com/f4exb/sdrangel")
};
PacketModPlugin::PacketModPlugin(QObject* parent) :
QObject(parent),
m_pluginAPI(0)
{
}
const PluginDescriptor& PacketModPlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void PacketModPlugin::initPlugin(PluginAPI* pluginAPI)
{
m_pluginAPI = pluginAPI;
m_pluginAPI->registerTxChannel(PacketMod::m_channelIdURI, PacketMod::m_channelId, this);
}
#ifdef SERVER_MODE
PluginInstanceGUI* PacketModPlugin::createTxChannelGUI(
DeviceUISet *deviceUISet,
BasebandSampleSource *txChannel) const
{
return 0;
}
#else
PluginInstanceGUI* PacketModPlugin::createTxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSource *txChannel) const
{
return PacketModGUI::create(m_pluginAPI, deviceUISet, txChannel);
}
#endif
BasebandSampleSource* PacketModPlugin::createTxChannelBS(DeviceAPI *deviceAPI) const
{
return new PacketMod(deviceAPI);
}
ChannelAPI* PacketModPlugin::createTxChannelCS(DeviceAPI *deviceAPI) const
{
return new PacketMod(deviceAPI);
}
ChannelWebAPIAdapter* PacketModPlugin::createChannelWebAPIAdapter() const
{
return new PacketModWebAPIAdapter();
}

Wyświetl plik

@ -0,0 +1,50 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_PACKETMODPLUGIN_H
#define INCLUDE_PACKETMODPLUGIN_H
#include <QObject>
#include "plugin/plugininterface.h"
class DeviceUISet;
class BasebandSampleSource;
class PacketModPlugin : public QObject, PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID "sdrangel.channeltx.packetmod")
public:
explicit PacketModPlugin(QObject* parent = 0);
const PluginDescriptor& getPluginDescriptor() const;
void initPlugin(PluginAPI* pluginAPI);
virtual PluginInstanceGUI* createTxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSource *rxChannel) const;
virtual BasebandSampleSource* createTxChannelBS(DeviceAPI *deviceAPI) const;
virtual ChannelAPI* createTxChannelCS(DeviceAPI *deviceAPI) const;
virtual ChannelWebAPIAdapter* createChannelWebAPIAdapter() const;
private:
static const PluginDescriptor m_pluginDescriptor;
PluginAPI* m_pluginAPI;
};
#endif // INCLUDE_PACKETMODPLUGIN_H

Wyświetl plik

@ -0,0 +1,52 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "packetmodrepeatdialog.h"
#include "packetmodsettings.h"
#include <QLineEdit>
PacketModRepeatDialog::PacketModRepeatDialog(float repeatDelay, int repeatCount, QWidget* parent) :
QDialog(parent),
ui(new Ui::PacketModRepeatDialog)
{
ui->setupUi(this);
ui->repeatDelay->setValue(repeatDelay);
QLineEdit *edit = ui->repeatCount->lineEdit();
if (edit)
{
if (repeatCount == PacketModSettings::infinitePackets)
edit->setText("Infinite");
else
edit->setText(QString("%1").arg(repeatCount));
}
}
PacketModRepeatDialog::~PacketModRepeatDialog()
{
delete ui;
}
void PacketModRepeatDialog::accept()
{
m_repeatDelay = ui->repeatDelay->value();
QString text = ui->repeatCount->currentText();
if (!text.compare(QString("Infinite"), Qt::CaseInsensitive))
m_repeatCount = PacketModSettings::infinitePackets;
else
m_repeatCount = text.toUInt();
QDialog::accept();
}

Wyświetl plik

@ -0,0 +1,40 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_PACKETMODREPEATDIALOG_H
#define INCLUDE_PACKETMODREPEATDIALOG_H
#include "ui_packetmodrepeatdialog.h"
class PacketModRepeatDialog : public QDialog {
Q_OBJECT
public:
explicit PacketModRepeatDialog(float repeatDelay, int repeatCount, QWidget* parent = 0);
~PacketModRepeatDialog();
float m_repeatDelay; // Delay in seconds between packets
int m_repeatCount; // Number of packets to transmit (-1 = infinite)
private slots:
void accept();
private:
Ui::PacketModRepeatDialog* ui;
};
#endif // INCLUDE_PACKETMODREPEATDIALOG_H

Wyświetl plik

@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PacketModRepeatDialog</class>
<widget class="QDialog" name="PacketModRepeatDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>351</width>
<height>115</height>
</rect>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Packet Repeat Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="repeatDelayLabel">
<property name="text">
<string>Delay between packets (s)</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="repeatCountLabel">
<property name="text">
<string>Packets to transmit</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="repeatCount">
<property name="toolTip">
<string>Number of packets to transmit</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string>Infinite</string>
</property>
</item>
<item>
<property name="text">
<string>10</string>
</property>
</item>
<item>
<property name="text">
<string>100</string>
</property>
</item>
<item>
<property name="text">
<string>1000</string>
</property>
</item>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="repeatDelay">
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>repeatDelay</tabstop>
<tabstop>repeatCount</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>PacketModRepeatDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>PacketModRepeatDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

Wyświetl plik

@ -0,0 +1,204 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017 Edouard Griffiths, F4EXB //
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QColor>
#include <QDebug>
#include "dsp/dspengine.h"
#include "util/simpleserializer.h"
#include "settings/serializable.h"
#include "packetmodsettings.h"
PacketModSettings::PacketModSettings()
{
resetToDefaults();
}
void PacketModSettings::resetToDefaults()
{
m_inputFrequencyOffset = 0;
m_baud = 1200;
m_rfBandwidth = 10000.0f;
m_fmDeviation = 2500.0f;
m_gain = -2.0f; // To avoid overflow, which results in out-of-band RF
m_channelMute = false;
m_repeat = false;
m_repeatDelay = 1.0f;
m_repeatCount = infinitePackets;
m_rampUpBits = 8;
m_rampDownBits = 8;
m_rampRange = 60;
m_modulateWhileRamping = true;
m_markFrequency = 2200;
m_spaceFrequency = 1200;
m_ax25PreFlags = 5;
m_ax25PostFlags = 2;
m_ax25Control = 3;
m_ax25PID = 0xf0;
m_preEmphasis = false;
m_preEmphasisTau = 50e-6f;
m_preEmphasisHighFreq = 12000.0f;
m_lpfTaps = 301;
m_bbNoise = false;
m_rfNoise = false;
m_writeToFile = false;
m_spectrumRate = 8000;
m_callsign = "MYCALL";
m_to = "APRS";
m_via = "WIDE2-2";
m_data = ">Using SDRangel";
m_rgbColor = QColor(255, 0, 0).rgb();
m_title = "Packet Modulator";
m_streamIndex = 0;
m_useReverseAPI = false;
m_reverseAPIAddress = "127.0.0.1";
m_reverseAPIPort = 8888;
m_reverseAPIDeviceIndex = 0;
m_reverseAPIChannelIndex = 0;
}
QByteArray PacketModSettings::serialize() const
{
SimpleSerializer s(1);
s.writeS32(1, m_inputFrequencyOffset);
s.writeS32(2, m_baud);
s.writeReal(3, m_rfBandwidth);
s.writeReal(4, m_fmDeviation);
s.writeReal(5, m_gain);
s.writeBool(6, m_channelMute);
s.writeBool(7, m_repeat);
s.writeReal(8, m_repeatDelay);
s.writeS32(9, m_repeatCount);
s.writeS32(10, m_rampUpBits);
s.writeS32(11, m_rampDownBits);
s.writeS32(12, m_rampRange);
s.writeBool(13, m_modulateWhileRamping);
s.writeS32(14, m_markFrequency);
s.writeS32(15, m_spaceFrequency);
s.writeS32(16, m_ax25PreFlags);
s.writeS32(17, m_ax25PostFlags);
s.writeS32(18, m_ax25Control);
s.writeS32(19, m_ax25PID);
s.writeBool(20, m_preEmphasis);
s.writeReal(21, m_preEmphasisTau);
s.writeReal(22, m_preEmphasisHighFreq);
s.writeS32(23, m_lpfTaps);
s.writeBool(24, m_bbNoise);
s.writeBool(25, m_rfNoise);
s.writeBool(26, m_writeToFile);
s.writeString(27, m_callsign);
s.writeString(28, m_to);
s.writeString(29, m_via);
s.writeString(30, m_data);
s.writeU32(31, m_rgbColor);
s.writeString(32, m_title);
if (m_channelMarker) {
s.writeBlob(33, m_channelMarker->serialize());
}
s.writeS32(34, m_streamIndex);
s.writeBool(35, m_useReverseAPI);
s.writeString(36, m_reverseAPIAddress);
s.writeU32(37, m_reverseAPIPort);
s.writeU32(38, m_reverseAPIDeviceIndex);
s.writeU32(39, m_reverseAPIChannelIndex);
return s.final();
}
bool PacketModSettings::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if(!d.isValid())
{
resetToDefaults();
return false;
}
if(d.getVersion() == 1)
{
QByteArray bytetmp;
qint32 tmp;
uint32_t utmp;
d.readS32(1, &tmp, 0);
m_inputFrequencyOffset = tmp;
d.readS32(2, &m_baud, 1200);
d.readReal(3, &m_rfBandwidth, 12500.0f);
d.readReal(4, &m_fmDeviation, 2500.0f);
d.readReal(5, &m_gain, 0.0f);
d.readBool(6, &m_channelMute, false);
d.readBool(7, &m_repeat, false);
d.readReal(8, &m_repeatDelay, 1.0f);
d.readS32(9, &m_repeatCount, -1);
d.readS32(10, &m_rampUpBits, 8);
d.readS32(11, &m_rampDownBits, 8);
d.readS32(12, &m_rampRange, 8);
d.readBool(13, &m_modulateWhileRamping, true);
d.readS32(14, &m_markFrequency, 5);
d.readS32(15, &m_spaceFrequency, 5);
d.readS32(16, &m_ax25PreFlags, 5);
d.readS32(17, &m_ax25PostFlags, 2);
d.readS32(18, &m_ax25Control, 3);
d.readS32(19, &m_ax25PID, 0xf0);
d.readBool(20, &m_preEmphasis, false);
d.readReal(21, &m_preEmphasisTau, 50e-6f);
d.readReal(22, &m_preEmphasisHighFreq, 12000.0f);
d.readS32(23, &m_lpfTaps, 301);
d.readBool(24, &m_bbNoise, false);
d.readBool(25, &m_rfNoise, false);
d.readBool(26, &m_writeToFile, false);
d.readString(27, &m_callsign, "MYCALL");
d.readString(28, &m_to, "APRS");
d.readString(29, &m_via, "WIDE2-2");
d.readString(30, &m_data, ">Using SDRangel");
d.readU32(31, &m_rgbColor);
d.readString(32, &m_title, "Packet Modulator");
if (m_channelMarker) {
d.readBlob(33, &bytetmp);
m_channelMarker->deserialize(bytetmp);
}
d.readS32(34, &m_streamIndex, 0);
d.readBool(35, &m_useReverseAPI, false);
d.readString(36, &m_reverseAPIAddress, "127.0.0.1");
d.readU32(37, &utmp, 0);
if ((utmp > 1023) && (utmp < 65535)) {
m_reverseAPIPort = utmp;
} else {
m_reverseAPIPort = 8888;
}
d.readU32(38, &utmp, 0);
m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp;
d.readU32(39, &utmp, 0);
m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp;
return true;
}
else
{
qDebug() << "PacketModSettings::deserialize: ERROR";
resetToDefaults();
return false;
}
}

Wyświetl plik

@ -0,0 +1,80 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017 Edouard Griffiths, F4EXB //
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_CHANNELTX_MODPACKET_PACKETMODSETTINGS_H
#define PLUGINS_CHANNELTX_MODPACKET_PACKETMODSETTINGS_H
#include <QByteArray>
#include <stdint.h>
#include "dsp/dsptypes.h"
class Serializable;
struct PacketModSettings
{
static const int infinitePackets = -1;
qint64 m_inputFrequencyOffset;
int m_baud;
Real m_rfBandwidth;
Real m_fmDeviation;
Real m_gain;
bool m_channelMute;
bool m_repeat;
Real m_repeatDelay;
int m_repeatCount;
int m_rampUpBits;
int m_rampDownBits;
int m_rampRange;
bool m_modulateWhileRamping;
int m_markFrequency;
int m_spaceFrequency;
int m_ax25PreFlags;
int m_ax25PostFlags;
int m_ax25Control;
int m_ax25PID;
bool m_preEmphasis;
float m_preEmphasisTau;
float m_preEmphasisHighFreq;
int m_lpfTaps;
bool m_bbNoise;
bool m_rfNoise;
bool m_writeToFile;
int m_spectrumRate;
QString m_callsign;
QString m_to;
QString m_via;
QString m_data;
quint32 m_rgbColor;
QString m_title;
Serializable *m_channelMarker;
int m_streamIndex;
bool m_useReverseAPI;
QString m_reverseAPIAddress;
uint16_t m_reverseAPIPort;
uint16_t m_reverseAPIDeviceIndex;
uint16_t m_reverseAPIChannelIndex;
PacketModSettings();
void resetToDefaults();
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
};
#endif /* PLUGINS_CHANNELTX_MODPACKET_PACKETMODSETTINGS_H */

Wyświetl plik

@ -0,0 +1,482 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <cctype>
#include <QDebug>
#include "dsp/basebandsamplesink.h"
#include "packetmodsource.h"
#include "util/crc.h"
PacketModSource::PacketModSource() :
m_channelSampleRate(48000),
m_preemphasisFilter(48000, FMPREEMPHASIS_TAU_US),
m_channelFrequencyOffset(0),
m_magsq(0.0),
m_audioPhase(0.0f),
m_fmPhase(0.0f),
m_levelCalcCount(0),
m_peakLevel(0.0f),
m_levelSum(0.0f),
m_bitCount(0),
m_byteIdx(0),
m_bitIdx(0),
m_last5Bits(0),
m_state(idle)
{
m_lowpass.create(301, m_channelSampleRate, 22000.0 / 2.0);
applySettings(m_settings, true);
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
}
PacketModSource::~PacketModSource()
{
}
void PacketModSource::pull(SampleVector::iterator begin, unsigned int nbSamples)
{
std::for_each(
begin,
begin + nbSamples,
[this](Sample& s) {
pullOne(s);
}
);
}
void PacketModSource::pullOne(Sample& sample)
{
if (m_settings.m_channelMute)
{
sample.m_real = 0.0f;
sample.m_imag = 0.0f;
return;
}
// Calculate next sample
modulateSample();
// Shift to carrier frequency
Complex ci = m_modSample;
ci *= m_carrierNco.nextIQ();
// Calculate power
double magsq = ci.real() * ci.real() + ci.imag() * ci.imag();
m_movingAverage(magsq);
m_magsq = m_movingAverage.asDouble();
// Convert from float to fixed point
sample.m_real = (FixReal) (ci.real() * SDR_TX_SCALEF);
sample.m_imag = (FixReal) (ci.imag() * SDR_TX_SCALEF);
}
void PacketModSource::prefetch(unsigned int nbSamples)
{
}
void PacketModSource::sampleToSpectrum(Real sample)
{
if (m_spectrumSink)
{
Complex out;
Complex in;
in.real(sample);
in.imag(0.0f);
if (m_interpolator.decimate(&m_interpolatorDistanceRemain, in, &out))
{
sample = std::real(out);
m_sampleBuffer.push_back(Sample(sample * 0.891235351562f * SDR_TX_SCALEF, 0.0f));
m_spectrumSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), true);
m_sampleBuffer.clear();
m_interpolatorDistanceRemain += m_interpolatorDistance;
}
}
}
void PacketModSource::modulateSample()
{
Real audioMod;
Real theta;
Real f_delta;
Real linearGain;
Real linearRampGain;
Real emphasis;
if ((m_state == idle) || (m_state == wait))
{
audioMod = 0.0f;
m_modSample.real(audioMod);
m_modSample.imag(0);
calculateLevel(audioMod);
sampleToSpectrum(audioMod);
if (m_state == wait)
{
m_waitCounter--;
if (m_waitCounter == 0)
initTX();
}
}
else
{
// Bell 202 AFSK
if (m_sampleIdx == 0)
{
if (bitsValid())
{
// NRZI encoding - encode 0 as change of freq, 1 no change
if (getBit() == 0)
m_f = m_f == m_settings.m_markFrequency ? m_settings.m_spaceFrequency : m_settings.m_markFrequency;
}
// Should we start ramping down power?
if ((m_bitCount < m_settings.m_rampDownBits) || ((m_bitCount == 0) && !m_settings.m_rampDownBits))
{
m_state = ramp_down;
if (m_settings.m_rampDownBits > 0)
m_powRamp = -m_settings.m_rampRange/(m_settings.m_rampDownBits * (Real)m_samplesPerSymbol);
}
}
m_sampleIdx++;
if (m_sampleIdx > m_samplesPerSymbol)
m_sampleIdx = 0;
if (!m_settings.m_bbNoise)
audioMod = sin(m_audioPhase);
else
audioMod = (Real)rand()/((Real)RAND_MAX)-0.5; // Noise to test filter frequency response
if ((m_state == tx) || m_settings.m_modulateWhileRamping)
m_audioPhase += (M_PI * 2.0f * m_f) / (m_channelSampleRate);
if (m_audioPhase > M_PI)
m_audioPhase -= (2.0f * M_PI);
// Preemphasis filter
if (m_settings.m_preEmphasis)
audioMod = m_preemphasisFilter.filter(audioMod);
if (m_audioFile.is_open())
m_audioFile << audioMod << "\n";
// Display baseband audio in spectrum analyser
sampleToSpectrum(audioMod);
// FM
m_fmPhase += audioMod;
if (m_fmPhase > M_PI)
m_fmPhase -= (2.0f * M_PI);
f_delta = m_settings.m_fmDeviation / m_channelSampleRate;
theta = 2.0f * M_PI * f_delta * m_fmPhase;
linearRampGain = powf(10.0f, m_pow/20.0f);
linearGain = powf(10.0f, m_settings.m_gain/20.0f);
if (!m_settings.m_rfNoise)
{
m_modSample.real(linearGain * linearRampGain * cos(theta));
m_modSample.imag(linearGain * linearRampGain * sin(theta));
}
else
{
// Noise to test filter frequency response
m_modSample.real(linearGain * ((Real)rand()/((Real)RAND_MAX)-0.5f));
m_modSample.imag(linearGain * ((Real)rand()/((Real)RAND_MAX)-0.5f));
}
// Apply low pass filter to limit RF BW
m_modSample = m_lowpass.filter(m_modSample);
// Ramp up/down power at start/end of packet
if ((m_state == ramp_up) || (m_state == ramp_down))
{
m_pow += m_powRamp;
if ((m_state == ramp_up) && (m_pow >= 0.0f))
{
// Finished ramp up, transmit at full gain
m_state = tx;
m_pow = 0.0f;
}
else if ((m_state == ramp_down) && ( (m_settings.m_rampRange == 0)
|| (m_settings.m_rampDownBits == 0)
|| (m_pow <= -(Real)m_settings.m_rampRange)
))
{
m_state = idle;
// Do we need to retransmit the packet?
if (m_settings.m_repeat)
{
if (m_packetRepeatCount > 0)
m_packetRepeatCount--;
if ((m_packetRepeatCount == PacketModSettings::infinitePackets) || (m_packetRepeatCount > 0))
{
if (m_settings.m_repeatDelay > 0.0f)
{
// Wait before retransmitting
m_state = wait;
m_waitCounter = m_settings.m_repeatDelay * m_channelSampleRate;
}
else
{
// Retransmit immediately
initTX();
}
}
}
}
}
Real s = std::real(m_modSample);
calculateLevel(s);
}
}
void PacketModSource::calculateLevel(Real& sample)
{
if (m_levelCalcCount < m_levelNbSamples)
{
m_peakLevel = std::max(std::fabs(m_peakLevel), sample);
m_levelSum += sample * sample;
m_levelCalcCount++;
}
else
{
m_rmsLevel = sqrt(m_levelSum / m_levelNbSamples);
m_peakLevelOut = m_peakLevel;
m_peakLevel = 0.0f;
m_levelSum = 0.0f;
m_levelCalcCount = 0;
}
}
void PacketModSource::applySettings(const PacketModSettings& settings, bool force)
{
if ((settings.m_lpfTaps != m_settings.m_lpfTaps) || (settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force)
{
qDebug() << "PacketModSource::applySettings: Creating new lpf with taps " << settings.m_lpfTaps << " rfBW " << settings.m_rfBandwidth;
m_lowpass.create(settings.m_lpfTaps, m_channelSampleRate, settings.m_rfBandwidth / 2.0);
}
if ((settings.m_preEmphasisTau != m_settings.m_preEmphasisTau) || (settings.m_preEmphasisHighFreq != m_settings.m_preEmphasisHighFreq) || force)
{
qDebug() << "PacketModSource::applySettings: Creating new preemphasis filter with tau " << settings.m_preEmphasisTau << " highFreq " << settings.m_preEmphasisHighFreq << " sampleRate " << m_channelSampleRate;
m_preemphasisFilter.configure(m_channelSampleRate, settings.m_preEmphasisTau, settings.m_preEmphasisHighFreq);
}
m_settings = settings;
}
void PacketModSource::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force)
{
qDebug() << "PacketModSource::applyChannelSettings:"
<< " channelSampleRate: " << channelSampleRate
<< " channelFrequencyOffset: " << channelFrequencyOffset
<< " rfBandwidth: " << m_settings.m_rfBandwidth
<< " spectrumRate: " << m_settings.m_spectrumRate;
if ((channelFrequencyOffset != m_channelFrequencyOffset)
|| (channelSampleRate != m_channelSampleRate) || force)
{
m_carrierNco.setFreq(channelFrequencyOffset, channelSampleRate);
}
if ((m_channelSampleRate != channelSampleRate) || force)
{
m_preemphasisFilter.configure(channelSampleRate, m_settings.m_preEmphasisTau);
m_lowpass.create(m_settings.m_lpfTaps, channelSampleRate, m_settings.m_rfBandwidth / 2.0);
m_interpolatorDistanceRemain = 0;
m_interpolatorConsumed = false;
m_interpolatorDistance = (Real) channelSampleRate / (Real) m_settings.m_spectrumRate;
m_interpolator.create(48, m_settings.m_spectrumRate, m_settings.m_spectrumRate / 2.2, 3.0);
}
m_channelSampleRate = channelSampleRate;
m_channelFrequencyOffset = channelFrequencyOffset;
}
static uint8_t *ax25_address(uint8_t *p, QString address, uint8_t crrl)
{
int len;
int i;
QByteArray b;
int ssid;
len = address.length();
b = address.toUtf8();
ssid = 0;
for (i = 0; i < 6; i++)
{
if ((i < len) && (ssid == 0))
{
if (b[i] == '-')
{
if (len > i + 1)
{
ssid = b[i+1] - '0';
if ((len > i + 2) && isdigit(b[i+2])) {
ssid = (ssid*10) + (b[i+1] - '0');
}
if (ssid >= 16)
qDebug() << "ax25_address: SSID greater than 15 not supported";
}
else
qDebug() << "ax25_address: SSID number missing";
*p++ = ' ' << 1;
}
else
{
*p++ = b[i] << 1;
}
}
else
{
*p++ = ' ' << 1;
}
}
*p++ = crrl | (ssid << 1);
return p;
}
bool PacketModSource::bitsValid()
{
return m_bitCount > 0;
}
int PacketModSource::getBit()
{
int bit;
if (m_bitCount > 0)
{
bit = (m_bits[m_byteIdx] >> m_bitIdx) & 1;
m_bitIdx++;
m_bitCount--;
if (m_bitIdx == 8)
{
m_byteIdx++;
m_bitIdx = 0;
}
}
else
bit = 0;
return bit;
}
void PacketModSource::addBit(int bit)
{
// Transmit LSB first
m_bits[m_byteIdx] |= bit << m_bitIdx;
m_bitIdx++;
m_bitCount++;
m_bitCountTotal++;
if (m_bitIdx == 8)
{
m_byteIdx++;
m_bits[m_byteIdx] = 0;
m_bitIdx = 0;
}
m_last5Bits = ((m_last5Bits << 1) | bit) & 0x1f;
}
void PacketModSource::initTX()
{
m_byteIdx = 0;
m_bitIdx = 0;
m_bitCount = m_bitCountTotal; // Reset to allow retransmission
m_f = m_settings.m_spaceFrequency;
if (m_settings.m_rampUpBits == 0)
{
m_state = tx;
m_pow = 0.0f;
}
else
{
m_state = ramp_up;
m_pow = -(Real)m_settings.m_rampRange;
m_powRamp = m_settings.m_rampRange/(m_settings.m_rampUpBits * (Real)m_samplesPerSymbol);
}
}
void PacketModSource::addTXPacket(QString callsign, QString to, QString via, QString data)
{
uint8_t packet[AX25_MAX_BYTES];
uint8_t *crc_start;
uint8_t *p;
crc16x25 crc;
uint16_t crcValue;
int len;
int packet_length;
// Create AX.25 packet
p = packet;
// Flag
for (int i = 0; i < std::min(m_settings.m_ax25PreFlags, AX25_MAX_FLAGS); i++)
*p++ = AX25_FLAG;
crc_start = p;
// Dest
p = ax25_address(p, to, 0xe0);
// From
p = ax25_address(p, callsign, 0x60);
// Via
p = ax25_address(p, via, 0x61);
// Control
*p++ = m_settings.m_ax25Control;
// PID
*p++ = m_settings.m_ax25PID;
// Data
len = data.length();
memcpy(p, data.toUtf8(), len);
p += len;
// CRC (do not include flags)
crc.calculate(crc_start, p-crc_start);
crcValue = crc.get();
*p++ = crcValue & 0xff;
*p++ = (crcValue >> 8);
// Flag
for (int i = 0; i < std::min(m_settings.m_ax25PostFlags, AX25_MAX_FLAGS); i++)
*p++ = AX25_FLAG;
packet_length = p-&packet[0];
// HDLC bit stuffing
m_byteIdx = 0;
m_bitIdx = 0;
m_last5Bits = 0;
m_bitCount = 0;
m_bitCountTotal = 0;
for (int i = 0; i < packet_length; i++)
{
for (int j = 0; j < 8; j++)
{
int tx_bit = (packet[i] >> j) & 1;
// Stuff 0 if last 5 bits are 1s
if ((packet[i] != AX25_FLAG) && (m_last5Bits == 0x1f))
addBit(0);
addBit(tx_bit);
}
}
m_samplesPerSymbol = m_channelSampleRate / m_settings.m_baud;
m_packetRepeatCount = m_settings.m_repeatCount;
initTX();
// Only reset phases at start of new packet TX, not in initTX(), so that
// there isn't a discontinuity in phase when repeatedly transmitting a
// single tone
m_sampleIdx = 0;
m_audioPhase = 0.0f;
m_fmPhase = 0.0f;
if (m_settings.m_writeToFile)
m_audioFile.open("packetmod.csv", std::ofstream::out);
}

Wyświetl plik

@ -0,0 +1,131 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_PACKETMODSOURCE_H
#define INCLUDE_PACKETMODSOURCE_H
#include <QMutex>
#include <QDebug>
#include <iostream>
#include <fstream>
#include "dsp/channelsamplesource.h"
#include "dsp/nco.h"
#include "dsp/ncof.h"
#include "dsp/interpolator.h"
#include "dsp/lowpass.h"
#include "dsp/bandpass.h"
#include "dsp/fmpreemphasis.h"
#include "util/movingaverage.h"
#include "packetmodsettings.h"
#define AX25_MAX_FLAGS 1024
#define AX25_MAX_BYTES (2*AX25_MAX_FLAGS+1+28+2+256+2+1)
#define AX25_MAX_BITS (AX25_MAX_BYTES*2)
#define AX25_FLAG 0x7e
#define AX25_NO_L3 0xf0
class BasebandSampleSink;
class PacketModSource : public ChannelSampleSource
{
public:
PacketModSource();
virtual ~PacketModSource();
virtual void pull(SampleVector::iterator begin, unsigned int nbSamples);
virtual void pullOne(Sample& sample);
virtual void prefetch(unsigned int nbSamples);
double getMagSq() const { return m_magsq; }
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
{
rmsLevel = m_rmsLevel;
peakLevel = m_peakLevelOut;
numSamples = m_levelNbSamples;
}
void setSpectrumSink(BasebandSampleSink *sampleSink) { m_spectrumSink = sampleSink; }
void applySettings(const PacketModSettings& settings, bool force = false);
void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false);
void addTXPacket(QString callsign, QString to, QString via, QString data);
private:
int m_channelSampleRate;
int m_channelFrequencyOffset;
PacketModSettings m_settings;
NCO m_carrierNco;
Real m_audioPhase;
Real m_fmPhase;
Complex m_modSample;
Lowpass<Complex> m_lowpass; // Low pass filter to limit RF bandwidth
FMPreemphasis m_preemphasisFilter; // FM preemphasis filter to amplify high frequencies
BasebandSampleSink* m_spectrumSink; // Spectrum GUI to display baseband waveform
SampleVector m_sampleBuffer;
Interpolator m_interpolator; // Interpolator to downsample to 4k in spectrum
Real m_interpolatorDistance;
Real m_interpolatorDistanceRemain;
bool m_interpolatorConsumed;
double m_magsq;
MovingAverageUtil<double, double, 16> m_movingAverage;
quint32 m_levelCalcCount;
qreal m_rmsLevel;
qreal m_peakLevelOut;
Real m_peakLevel;
Real m_levelSum;
static const int m_levelNbSamples = 480; // every 10ms assuming 48k Sa/s
int m_f; // Current frequency
int m_sampleIdx; // Sample index in to symbol
int m_samplesPerSymbol; // Number of samples per symbol
Real m_pow; // In dB
Real m_powRamp; // In dB
enum PacketModState {
idle, ramp_up, tx, ramp_down, wait
} m_state; // States for sample modulation
int m_packetRepeatCount;
uint64_t m_waitCounter; // Samples to wait before retransmission
uint8_t m_bits[AX25_MAX_BITS]; // HDLC encoded bits to transmit
int m_byteIdx; // Index in to m_bits
int m_bitIdx; // Index in to current byte of m_bits
int m_last5Bits; // Last 5 bits to be HDLC encoded
int m_bitCount; // Count of number of valid bits in m_bits
int m_bitCountTotal;
std::ofstream m_audioFile; // For debug output of baseband waveform
bool bitsValid(); // Are there and bits to transmit
int getBit(); // Get bit from m_bits
void addBit(int bit); // Add bit to m_bits, with zero stuffing
void initTX();
void calculateLevel(Real& sample);
void modulateSample();
void sampleToSpectrum(Real sample);
};
#endif // INCLUDE_PACKETMODSOURCE_H

Wyświetl plik

@ -0,0 +1,70 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "packetmodtxsettingsdialog.h"
PacketModTXSettingsDialog::PacketModTXSettingsDialog(int rampUpBits, int rampDownBits,
int rampRange, bool modulateWhileRamping,
int markFrequency, int spaceFrequency,
int ax25PreFlags, int ax25PostFlags,
int ax25Control, int ax25PID,
int lpfTaps, bool bbNoise, bool rfNoise, bool writeToFile,
QWidget* parent) :
QDialog(parent),
ui(new Ui::PacketModTXSettingsDialog)
{
ui->setupUi(this);
ui->rampUp->setValue(rampUpBits);
ui->rampDown->setValue(rampDownBits);
ui->rampRange->setValue(rampRange);
ui->modulateWhileRamping->setChecked(modulateWhileRamping);
ui->markFrequency->setValue(markFrequency);
ui->spaceFrequency->setValue(spaceFrequency);
ui->ax25PreFlags->setValue(ax25PreFlags);
ui->ax25PostFlags->setValue(ax25PostFlags);
ui->ax25Control->setValue(ax25Control);
ui->ax25PID->setValue(ax25PID);
ui->lpfTaps->setValue(lpfTaps);
ui->bbNoise->setChecked(bbNoise);
ui->rfNoise->setChecked(rfNoise);
ui->writeToFile->setChecked(writeToFile);
}
PacketModTXSettingsDialog::~PacketModTXSettingsDialog()
{
delete ui;
}
void PacketModTXSettingsDialog::accept()
{
m_rampUpBits = ui->rampUp->value();
m_rampDownBits = ui->rampDown->value();
m_rampRange = ui->rampRange->value();
m_modulateWhileRamping = ui->modulateWhileRamping->isChecked();
m_markFrequency = ui->markFrequency->value();
m_spaceFrequency = ui->spaceFrequency->value();
m_ax25PreFlags = ui->ax25PreFlags->value();
m_ax25PostFlags = ui->ax25PostFlags->value();
m_ax25Control = ui->ax25Control->value();
m_ax25PID = ui->ax25PID->value();
m_lpfTaps = ui->lpfTaps->value();
m_bbNoise = ui->bbNoise->isChecked();
m_rfNoise = ui->rfNoise->isChecked();
m_writeToFile = ui->writeToFile->isChecked();
QDialog::accept();
}

Wyświetl plik

@ -0,0 +1,58 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_PACKETMODTXSETTINGSDIALOG_H
#define INCLUDE_PACKETMODTXSETTINGSDIALOG_H
#include "ui_packetmodtxsettingsdialog.h"
class PacketModTXSettingsDialog : public QDialog {
Q_OBJECT
public:
explicit PacketModTXSettingsDialog(int rampUpBits, int rampDownBits, int rampRange,
bool modulateWhileRamping,
int markFrequency, int spaceFrequency,
int ax25PreFlags, int ax25PostFlags,
int ax25Control, int ax25PID,
int lpfTaps, bool bbNoise, bool rfNoise, bool writeToFile,
QWidget* parent = 0);
~PacketModTXSettingsDialog();
int m_rampUpBits;
int m_rampDownBits;
int m_rampRange;
bool m_modulateWhileRamping;
int m_markFrequency;
int m_spaceFrequency;
int m_ax25PreFlags;
int m_ax25PostFlags;
int m_ax25Control;
int m_ax25PID;
int m_lpfTaps;
bool m_bbNoise;
bool m_rfNoise;
bool m_writeToFile;
private slots:
void accept();
private:
Ui::PacketModTXSettingsDialog* ui;
};
#endif // INCLUDE_PACKETMODTXSETTINGSDIALOG_H

Wyświetl plik

@ -0,0 +1,332 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PacketModTXSettingsDialog</class>
<widget class="QDialog" name="PacketModTXSettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>351</width>
<height>449</height>
</rect>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Packet TX Extra Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="rampUpLabel">
<property name="text">
<string>Ramp up bits</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="rampUp">
<property name="toolTip">
<string>Number of bits at start of frame during which output power is ramped up.</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="rampDownLabel">
<property name="text">
<string>Ramp down bits</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="rampDown">
<property name="toolTip">
<string>Number of bits at end of frame during which output power is ramped down.</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="rampRangeLabel">
<property name="text">
<string>Ramp range (dB)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="rampRange">
<property name="toolTip">
<string>Range in dB over which power is ramped up or down. E.g. a value of 60 causes power to be ramped from -60dB to 0dB.</string>
</property>
<property name="maximum">
<number>120</number>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="modulateWhileRamping">
<property name="toolTip">
<string>Modulate during ramping.</string>
</property>
<property name="text">
<string>Modulate while ramping</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="markFrequencyLabel">
<property name="text">
<string>Mark frequency (Hz)</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="markFrequency">
<property name="toolTip">
<string>Frequency of tone to generate for a mark (1).</string>
</property>
<property name="maximum">
<number>24000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="spaceFrequencyLabel">
<property name="text">
<string>Space frequency (Hz)</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="spaceFrequency">
<property name="toolTip">
<string>Frequency of tone to generate for a space (0).</string>
</property>
<property name="maximum">
<number>24000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="ax25PreFlagsLabel">
<property name="text">
<string>AX.25 preamble flags</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSpinBox" name="ax25PreFlags">
<property name="toolTip">
<string>Number of flags to be transmitted before the frame. This gives more time for a receiver to unmute.</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1024</number>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="ax25PostFlagsLabel">
<property name="text">
<string>AX.25 postamble flags</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QSpinBox" name="ax25PostFlags">
<property name="toolTip">
<string>Number of flags to be transmitted after the frame.</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1024</number>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="ax25ControlLabel">
<property name="text">
<string>AX.25 control</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QSpinBox" name="ax25Control">
<property name="toolTip">
<string>Value of control field in AX.25 frame.</string>
</property>
<property name="prefix">
<string>0x</string>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>3</number>
</property>
<property name="displayIntegerBase">
<number>16</number>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="ax25PIDLabel">
<property name="text">
<string>AX.25 PID</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QSpinBox" name="ax25PID">
<property name="toolTip">
<string>Value of PID field in AX.25 frame. Use 0xf0 for no L3.</string>
</property>
<property name="prefix">
<string>0x</string>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>240</number>
</property>
<property name="displayIntegerBase">
<number>16</number>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="lpfTapsLabel">
<property name="text">
<string>Lowpass taps</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QSpinBox" name="lpfTaps">
<property name="toolTip">
<string>Number of taps in LPF for RF BW filter.</string>
</property>
<property name="maximum">
<number>10000</number>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QCheckBox" name="rfNoise">
<property name="toolTip">
<string>Generate white noise as RF signal.</string>
</property>
<property name="text">
<string>Generate RF noise</string>
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QCheckBox" name="writeToFile">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Write baseband signal to a CSV file named packetmod.csv</string>
</property>
<property name="text">
<string>Write baseband to CSV</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QCheckBox" name="bbNoise">
<property name="toolTip">
<string>Generate white noise as baseband signal.</string>
</property>
<property name="text">
<string>Generate BB noise</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>rampUp</tabstop>
<tabstop>rampDown</tabstop>
<tabstop>rampRange</tabstop>
<tabstop>modulateWhileRamping</tabstop>
<tabstop>markFrequency</tabstop>
<tabstop>spaceFrequency</tabstop>
<tabstop>ax25PreFlags</tabstop>
<tabstop>ax25PostFlags</tabstop>
<tabstop>ax25Control</tabstop>
<tabstop>ax25PID</tabstop>
<tabstop>lpfTaps</tabstop>
<tabstop>bbNoise</tabstop>
<tabstop>rfNoise</tabstop>
<tabstop>writeToFile</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>PacketModTXSettingsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>PacketModTXSettingsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -0,0 +1,85 @@
<h1>Packet radio modulator plugin</h1>
<h2>Introduction</h2>
This plugin can be used to modulate packet radio (APRS/AX.25) data packets.
<h2>Interface</h2>
![Packet Modulator plugin GUI](../../../doc/img/PacketMod_plugin.png)
<h3>1: Frequency shift from center frequency of transmission</h3>
Use the wheels to adjust the frequency shift in Hz from the center frequency of transmission. Left click on a digit sets the cursor position at this digit. Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position. Wheels are moved with the mousewheel while pointing at the wheel or by selecting the wheel with the left mouse click and using the keyboard arrows. Pressing shift simultaneously moves digit by 5 and pressing control moves it by 2.
<h3>2: Channel power</h3>
Average total power in dB relative to a +/- 1.0 amplitude signal generated in the pass band.
<h3>3: Channel mute</h3>
Use this button to toggle mute for this channel.
<h3>4: Modulation</h3>
This specifies the baud rate and modulation that is used for the packet transmission. Currently 1200 baud AFSK is supported.
<h3>5: RF Bandwidth</h3>
This specifies the bandwidth of a LPF that is applied to the output signal to limit the RF bandwidth.
<h3>6: Frequency deviation</h3>
Adjusts the frequency deviation in 0.1 kHz steps from 1 to 6 kHz. Typical values are 2.5 kHz and 5 kHz.
<h3>7: Gain</h3>
Adjusts the gain in dB from -60 to 0dB. The gain should be set to ensure the level meter remains below 100%.
<h3>8: Level meter in %</h3>
- top bar (beige): average value
- bottom bar (brown): instantaneous peak value
- tip vertical bar (bright red): peak hold value
<h3>9: Callsign</h3>
Enter your amateur radio callsign and optionally a sub-station ID (SSID). E.g. M7RCE or M7RCE-1
<h3>10: Preemphaisis Filter</h3>
Check this button to enable a FM preemphasis filter, which amplifiers higher frequencies. Right click to open the dialog to adjust settings for the filter.
<h3>11: Repeat</h3>
Check this button to repeated transmit a packet. Right click to open the dialog to adjust the delay between retransmission and number of times the packet should be repeated.
<h3>12: Insertion position</h3>
Inserts position as APRS formatted latitude and longitude in to the current cursor position within the data field. Lattitude and longitude can be specified under Preferences > My position.
<h3>13: To</h3>
Enter the destination for the packet. To send the packet to the APRS network, use APRS or APZ.
<h3>14: Via</h3>
Enter the routing for the packet. To have the packet repeated by digipeaters, use WIDE2-2. To have the packet repeated by the International Space Station (ISS), use ARISS.
<h3>15: Data</h3>
The packet of data to send. To send an APRS status message, use the format <tt>>Status</tt>. APRS messages can be tracked on https://aprs.fi
<h3>16: TX</h3>
Transmits a packet based on the current values in callsign, to, via and data.
<h2>API</h2>
Full details of the API can be found in the Swagger documentation. Here is a quick example of how to transmit a packet from the command line:
curl -X POST "http://127.0.0.1:8091/sdrangel/deviceset/1/channel/0/actions" -d '{"channelType": "PacketMod", "direction": 1, "PacketModActions": { "tx": { "callsign": "MYCALL", "to": "APRS", "via": "WIDE2-2", "data": ">Using SDRangel API to transmit" }}}'
Or to set the frequency deviation:
curl -X PATCH "http://127.0.0.1:8091/sdrangel/deviceset/1/channel/0/settings" -d '{"channelType": "PacketMod", "direction": 1, "PacketModSettings": {"fmDeviation": 5000}}'

Wyświetl plik

@ -101,6 +101,7 @@ set(sdrbase_SOURCES
dsp/filtermbe.cpp
dsp/filerecord.cpp
dsp/filerecordinterface.cpp
dsp/fmpreemphasis.cpp
dsp/freqlockcomplex.cpp
dsp/interpolator.cpp
dsp/glscopesettings.cpp
@ -142,6 +143,7 @@ set(sdrbase_SOURCES
settings/preset.cpp
settings/mainsettings.cpp
util/crc.cpp
util/CRC64.cpp
util/db.cpp
util/fixedtraits.cpp
@ -232,6 +234,7 @@ set(sdrbase_HEADERS
dsp/filtermbe.h
dsp/filerecord.h
dsp/filerecordinterface.h
dsp/fmpreemphasis.h
dsp/freqlockcomplex.h
dsp/gfft.h
dsp/glscopesettings.h

Wyświetl plik

@ -0,0 +1,80 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2005,2007,2012 Free Software Foundation, Inc.
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#define _USE_MATH_DEFINES
#include <cmath>
#include <QDebug>
#include "dsp/fmpreemphasis.h"
FMPreemphasis::FMPreemphasis(int sampleRate, Real tau, Real highFreq)
{
configure(sampleRate, tau, highFreq);
}
void FMPreemphasis::configure(int sampleRate, Real tau, Real highFreq)
{
// Based on: https://github.com/gnuradio/gnuradio/blob/master/gr-analog/python/analog/fm_emph.py
// Compare to freq response in https://www.mathworks.com/help/comm/ref/comm.fmbroadcastmodulator-system-object.html
// High frequency corner at which to flatten the gain
double fh = std::min((double)highFreq, 0.925 * sampleRate/2.0);
// Digital corner frequencies
double w_cl = 1.0 / tau;
double w_ch = 2.0 * M_PI * fh;
// Prewarped analog corner frequencies
double w_cla = 2.0 * sampleRate * std::tan(w_cl / (2.0 * sampleRate));
double w_cha = 2.0 * sampleRate * std::tan(w_ch / (2.0 * sampleRate));
// Resulting digital pole, zero, and gain term from the bilinear
// transformation of H(s) = (s + w_cla) / (s + w_cha) to
// H(z) = b0 (1 - z1 z^-1)/(1 - p1 z^-1)
double kl = -w_cla / (2.0 * sampleRate);
double kh = -w_cha / (2.0 * sampleRate);
double z1 = (1.0 + kl) / (1.0 - kl);
double p1 = (1.0 + kh) / (1.0 - kh);
double b0 = (1.0 - kl) / (1.0 - kh);
// Adjust with a gain, g, so 0 dB gain at DC
double g = std::abs(1.0 - p1) / (b0 * std::abs(1.0 - z1));
// Caclulate IIR taps
m_b0 = (Real)(g * b0 * 1.0);
m_b1 = (Real)(g * b0 * -z1);
m_a1 = (Real)-p1;
// Zero delay line so we get reproducible results
m_z = 0;
qDebug() << "FMPreemphasis::configure: tau: " << tau
<< " sampleRate: " << sampleRate
<< " b0: " << m_b0
<< " b1: " << m_b1
<< " a1: " << m_a1;
}
Real FMPreemphasis::filter(const Real sampleIn)
{
Real sampleOut;
// See Transposed Direct form 2 - https://en.wikipedia.org/wiki/Digital_biquad_filter
sampleOut = sampleIn * m_b0 + m_z;
m_z = sampleIn * m_b1 + sampleOut * -m_a1;
return sampleOut;
}

Wyświetl plik

@ -0,0 +1,55 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_DSP_FMPREEMPHASIS_H_
#define INCLUDE_DSP_FMPREEMPHASIS_H_
#include "dsp/dsptypes.h"
#include "export.h"
#define FMPREEMPHASIS_TAU_EU 50e-6f
#define FMPREEMPHASIS_TAU_US 75e-6f
/** FM preemphasis filter.
* Amplifies frequencies above ~3.2k (tau=50e-6 in EU) or ~2.1k (tau=75e-6 in US)
* at ~6dB per octave, and then flattens at 12k (highFreq).
* Frequency response:
* highFreq
* -------
* /
* /
* -------/
* 1/(2*pi*tau)
*/
class SDRBASE_API FMPreemphasis
{
public:
FMPreemphasis(int sampleRate, Real tau = FMPREEMPHASIS_TAU_EU, Real highFreq = 12000.0);
void configure(int sampleRate, Real tau = FMPREEMPHASIS_TAU_EU, Real highFreq = 12000.0);
Real filter(Real sampleIn);
private:
Real m_z; // Delay element
Real m_b0; // IIR numerator taps
Real m_b1;
Real m_a1; // IIR denominator taps
};
#endif /* INCLUDE_DSP_FMPREEMPHASIS_H_ */

Wyświetl plik

@ -2036,6 +2036,9 @@ margin-bottom: 20px;
},
"FileSourceActions" : {
"$ref" : "#/definitions/FileSourceActions"
},
"PacketModActions" : {
"$ref" : "#/definitions/PacketModActions"
}
},
"description" : "Base channel actions. Only the channel actions corresponding to the channel specified in the channelType field is or should be present."
@ -2192,6 +2195,9 @@ margin-bottom: 20px;
"NFMModReport" : {
"$ref" : "#/definitions/NFMModReport"
},
"PacketModReport" : {
"$ref" : "#/definitions/PacketModReport"
},
"SSBDemodReport" : {
"$ref" : "#/definitions/SSBDemodReport"
},
@ -2287,6 +2293,9 @@ margin-bottom: 20px;
"LocalSourceSettings" : {
"$ref" : "#/definitions/LocalSourceSettings"
},
"PacketModSettings" : {
"$ref" : "#/definitions/PacketModSettings"
},
"RemoteSinkSettings" : {
"$ref" : "#/definitions/RemoteSinkSettings"
},
@ -4875,6 +4884,124 @@ margin-bottom: 20px;
}
},
"description" : "Enumeration with name for values"
};
defs.PacketModActions = {
"properties" : {
"tx" : {
"$ref" : "#/definitions/PacketModActions_tx"
}
},
"description" : "PacketMod"
};
defs.PacketModActions_tx = {
"properties" : {
"callsign" : {
"type" : "string"
},
"to" : {
"type" : "string"
},
"via" : {
"type" : "string"
},
"data" : {
"type" : "string"
}
},
"description" : "Transmit a packet\n"
};
defs.PacketModReport = {
"properties" : {
"channelPowerDB" : {
"type" : "number",
"format" : "float",
"description" : "power transmitted in channel (dB)"
},
"audioSampleRate" : {
"type" : "integer"
},
"channelSampleRate" : {
"type" : "integer"
}
},
"description" : "PacketMod"
};
defs.PacketModSettings = {
"properties" : {
"inputFrequencyOffset" : {
"type" : "integer",
"format" : "int64"
},
"rfBandwidth" : {
"type" : "number",
"format" : "float"
},
"fmDeviation" : {
"type" : "number",
"format" : "float"
},
"gain" : {
"type" : "number",
"format" : "float"
},
"channelMute" : {
"type" : "integer"
},
"repeat" : {
"type" : "integer"
},
"repeatDelay" : {
"type" : "number",
"format" : "float"
},
"repeatCount" : {
"type" : "integer"
},
"ax25PreFlags" : {
"type" : "integer"
},
"ax25PostFlags" : {
"type" : "integer"
},
"preEmphasis" : {
"type" : "integer"
},
"preEmphasisTau" : {
"type" : "number",
"format" : "float"
},
"preEmphasisHighFreq" : {
"type" : "number",
"format" : "float"
},
"rgbColor" : {
"type" : "integer"
},
"title" : {
"type" : "string"
},
"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"
}
},
"description" : "PacketMod"
};
defs.PerseusReport = {
"properties" : {
@ -33327,7 +33454,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2020-09-14T23:30:27.272+02:00
Generated 2020-09-18T15:59:26.503+02:00
</div>
</div>
</div>

Wyświetl plik

@ -0,0 +1,61 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "crc.h"
#include "QDebug.h"
// Reverse bit ordering
uint32_t crc::reverse(uint32_t val, int bits)
{
uint32_t temp;
int i;
temp = 0;
for (i = 0; i < bits; i++)
temp |= ((val >> i) & 1) << (bits - 1 - i);
return temp;
}
// Calculate CRC for specified number of bits
void crc::calculate(uint32_t data, int data_bits)
{
uint32_t tmp;
uint32_t mask;
int bit, i;
// Reverse data order.
if (m_msb_first)
data = reverse (data, data_bits);
// Compute CRC.
tmp = m_crc;
for (i = 0; i < data_bits; i++) {
bit = ((data >> i) & 1) ^ (tmp & 1);
if (bit)
tmp = (tmp >> 1) ^ m_polynomial_rev;
else
tmp = tmp >> 1;
}
m_crc = tmp;
}
// Calculate CRC for specified array
void crc::calculate(const uint8_t *data, int length)
{
for(int i = 0; i < length; i++)
calculate(data[i], 8);
}

108
sdrbase/util/crc.h 100644
Wyświetl plik

@ -0,0 +1,108 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_CRC_H
#define INCLUDE_CRC_H
#include <stdint.h>
#include "export.h"
// Class to calculate arbitrary CRCs (up to 32-bits)
class SDRBASE_API crc
{
public:
// Create and initialise CRC with specified polynomial and parameters
crc(int poly_bits, uint32_t polynomial, bool msb_first, uint32_t init_value, uint32_t final_xor) :
m_poly_bits(poly_bits),
m_polynomial(polynomial),
m_msb_first(msb_first),
m_init_value(init_value),
m_final_xor(final_xor)
{
int shift;
shift = 32 - m_poly_bits;
m_polynomial_rev = reverse (m_polynomial << shift, 32);
init();
}
// Initialise CRC state
void init()
{
m_crc = m_init_value;
}
// Calculate CRC for supplied data
void calculate(uint32_t data, int data_bits);
void calculate(const uint8_t *data, int length);
// Get final CRC
uint32_t get()
{
uint32_t t;
t = m_final_xor ^ m_crc;
if (m_msb_first)
return reverse(t, m_poly_bits);
else
return t;
}
private:
static uint32_t reverse(uint32_t val, int bits);
uint32_t m_crc;
uint32_t m_polynomial;
uint32_t m_polynomial_rev;
uint32_t m_poly_bits;
bool m_msb_first;
uint32_t m_init_value;
uint32_t m_final_xor;
};
class SDRBASE_API crc16ansi : public crc
{
public:
crc16ansi() : crc(16, 0x8005, false, 0x0000, 0) {}
};
class SDRBASE_API crc16ccitt : public crc
{
public:
crc16ccitt() : crc(16, 0x1021, true, 0xffff, 0) {}
};
class SDRBASE_API crc16x25 : public crc
{
public:
crc16x25() : crc(16, 0x1021, false, 0xffff, 0xffff) {}
};
class SDRBASE_API crc32 : public crc
{
public:
crc32() : crc(32, 0x04C11DB7, false, 0xffffffff, 0xffffffff) {}
};
class SDRBASE_API crc32c : public crc
{
public:
crc32c() : crc(32, 0x1EDC6F41, false, 0xffffffff, 0) {}
};
#endif

Wyświetl plik

@ -75,6 +75,7 @@ const QMap<QString, QString> WebAPIRequestMapper::m_channelURIToSettingsKey = {
{"sdrangel.demod.localsink", "LocalSinkSettings"},
{"sdrangel.channel.localsink", "LocalSinkSettings"}, // remap
{"sdrangel.channel.localsource", "LocalSourceSettings"},
{"sdrangel.channeltx.modpacket", "PacketModSettings"},
{"sdrangel.demod.remotesink", "RemoteSinkSettings"},
{"sdrangel.channeltx.remotesource", "RemoteSourceSettings"},
{"sdrangel.channeltx.modssb", "SSBModSettings"},
@ -143,6 +144,7 @@ const QMap<QString, QString> WebAPIRequestMapper::m_channelTypeToSettingsKey = {
{"FreqTracker", "FreqTrackerSettings"},
{"NFMDemod", "NFMDemodSettings"},
{"NFMMod", "NFMModSettings"},
{"PacketMod", "PacketModSettings"},
{"LocalSink", "LocalSinkSettings"},
{"LocalSource", "LocalSourceSettings"},
{"RemoteSink", "RemoteSinkSettings"},
@ -157,7 +159,8 @@ const QMap<QString, QString> WebAPIRequestMapper::m_channelTypeToSettingsKey = {
const QMap<QString, QString> WebAPIRequestMapper::m_channelTypeToActionsKey = {
{"FileSink", "FileSinkActions"},
{"FileSource", "FileSourceActions"}
{"FileSource", "FileSourceActions"},
{"PacketMod", "PacketModActions"}
};
const QMap<QString, QString> WebAPIRequestMapper::m_sourceDeviceHwIdToSettingsKey = {
@ -3173,6 +3176,11 @@ bool WebAPIRequestMapper::getChannelSettings(
channelSettings->setLocalSourceSettings(new SWGSDRangel::SWGLocalSourceSettings());
channelSettings->getLocalSourceSettings()->fromJsonObject(settingsJsonObject);
}
else if (channelSettingsKey == "PacketModSettings")
{
channelSettings->setPacketModSettings(new SWGSDRangel::SWGPacketModSettings());
channelSettings->getPacketModSettings()->fromJsonObject(settingsJsonObject);
}
else if (channelSettingsKey == "RemoteSinkSettings")
{
channelSettings->setRemoteSinkSettings(new SWGSDRangel::SWGRemoteSinkSettings());
@ -3250,6 +3258,11 @@ bool WebAPIRequestMapper::getChannelActions(
channelActions->setFileSourceActions(new SWGSDRangel::SWGFileSourceActions());
channelActions->getFileSourceActions()->fromJsonObject(actionsJsonObject);
}
else if (channelActionsKey == "PacketModActions")
{
channelActions->setPacketModActions(new SWGSDRangel::SWGPacketModActions());
channelActions->getPacketModActions()->fromJsonObject(actionsJsonObject);
}
else
{
return false;
@ -3608,6 +3621,7 @@ void WebAPIRequestMapper::resetChannelSettings(SWGSDRangel::SWGChannelSettings&
channelSettings.setDsdDemodSettings(nullptr);
channelSettings.setNfmDemodSettings(nullptr);
channelSettings.setNfmModSettings(nullptr);
channelSettings.setPacketModSettings(nullptr);
channelSettings.setRemoteSinkSettings(nullptr);
channelSettings.setRemoteSourceSettings(nullptr);
channelSettings.setSsbDemodSettings(nullptr);
@ -3629,6 +3643,7 @@ void WebAPIRequestMapper::resetChannelReport(SWGSDRangel::SWGChannelReport& chan
channelReport.setDsdDemodReport(nullptr);
channelReport.setNfmDemodReport(nullptr);
channelReport.setNfmModReport(nullptr);
channelReport.setPacketModReport(nullptr);
channelReport.setRemoteSourceReport(nullptr);
channelReport.setSsbDemodReport(nullptr);
channelReport.setSsbModReport(nullptr);
@ -3643,6 +3658,7 @@ void WebAPIRequestMapper::resetChannelActions(SWGSDRangel::SWGChannelActions& ch
channelActions.cleanup();
channelActions.setChannelType(nullptr);
channelActions.setFileSourceActions(nullptr);
channelActions.setPacketModActions(nullptr);
}
void WebAPIRequestMapper::resetAudioInputDevice(SWGSDRangel::SWGAudioInputDevice& audioInputDevice)

Wyświetl plik

@ -30,6 +30,7 @@ set(sdrgui_SOURCES
gui/editcommanddialog.cpp
gui/externalclockbutton.cpp
gui/externalclockdialog.cpp
gui/fmpreemphasisdialog.cpp
gui/glscope.cpp
gui/glscopegui.cpp
gui/glshadercolors.cpp
@ -104,6 +105,7 @@ set(sdrgui_HEADERS
gui/editcommanddialog.h
gui/externalclockbutton.h
gui/externalclockdialog.h
gui/fmpreemphasisdialog.h
gui/glscope.h
gui/glscopegui.h
gui/glshadercolors.h
@ -165,6 +167,7 @@ set(sdrgui_FORMS
gui/deviceuserargsdialog.ui
gui/editcommanddialog.ui
gui/externalclockdialog.ui
gui/fmpreemphasisdialog.ui
gui/glscopegui.ui
gui/glspectrumgui.ui
gui/pluginsdialog.ui

Wyświetl plik

@ -0,0 +1,63 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#define _USE_MATH_DEFINES
#include <cmath>
#include "fmpreemphasisdialog.h"
#include "ui_fmpreemphasisdialog.h"
// Convert from s to us
#define TAU_SCALE 1000000.0
FMPreemphasisDialog::FMPreemphasisDialog(float tau, float highFreq, QWidget* parent) :
QDialog(parent),
ui(new Ui::FMPreemphasisDialog)
{
ui->setupUi(this);
ui->tau->setValue(tau*TAU_SCALE);
ui->lowFreq->setValue(1.0/(2.0*M_PI*tau));
ui->highFreq->setValue(highFreq);
}
FMPreemphasisDialog::~FMPreemphasisDialog()
{
delete ui;
}
void FMPreemphasisDialog::accept()
{
m_tau = ui->tau->value()/TAU_SCALE;
m_highFreq = ui->highFreq->value();
QDialog::accept();
}
void FMPreemphasisDialog::on_tau_valueChanged(double value)
{
// Set corresponding low frequency
ui->lowFreq->blockSignals(true);
ui->lowFreq->setValue(1.0/(2.0*M_PI*(value/TAU_SCALE)));
ui->lowFreq->blockSignals(false);
}
void FMPreemphasisDialog::on_lowFreq_valueChanged(double value)
{
// Set corresponding tau
ui->tau->blockSignals(true);
ui->tau->setValue(TAU_SCALE*1.0/(2.0*M_PI*value));
ui->tau->blockSignals(false);
}

Wyświetl plik

@ -0,0 +1,48 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_FMPREEMPHASISTDIALOG_H
#define INCLUDE_FMPREEMPHASISTDIALOG_H
#include <QDialog>
#include "export.h"
namespace Ui {
class FMPreemphasisDialog;
}
class SDRGUI_API FMPreemphasisDialog : public QDialog {
Q_OBJECT
public:
explicit FMPreemphasisDialog(float tau, float highFreq, QWidget* parent = 0);
~FMPreemphasisDialog();
float m_tau;
float m_highFreq;
private slots:
void accept();
void on_tau_valueChanged(double value);
void on_lowFreq_valueChanged(double value);
private:
Ui::FMPreemphasisDialog* ui;
};
#endif // INCLUDE_FMPREEMPHASISTDIALOG_H

Wyświetl plik

@ -0,0 +1,144 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FMPreemphasisDialog</class>
<widget class="QDialog" name="FMPreemphasisDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>351</width>
<height>142</height>
</rect>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>FM Preemphasis Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="tauLabel">
<property name="text">
<string>Time constant (Tau) (us)</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lowFreqLabel">
<property name="text">
<string>Low frequency corner (Hz)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="lowFreq">
<property name="toolTip">
<string>Low frequency corner. Automatically calculated based on tau.</string>
</property>
<property name="maximum">
<double>10000.000000000000000</double>
</property>
<property name="singleStep">
<double>1000.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="highFreqLabel">
<property name="text">
<string>High frequency corner (Hz)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="highFreq">
<property name="toolTip">
<string>High frequency corner.</string>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
<property name="singleStep">
<double>1000.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="tau">
<property name="toolTip">
<string>Time constant in us. 50 for EU. 75 for USA.</string>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>5000.000000000000000</double>
</property>
<property name="singleStep">
<double>10.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>tau</tabstop>
<tabstop>lowFreq</tabstop>
<tabstop>highFreq</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>FMPreemphasisDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>FMPreemphasisDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

Wyświetl plik

@ -21,3 +21,5 @@ ChannelActions:
$ref: "http://swgserver:8081/api/swagger/include/FileSink.yaml#/FileSinkActions"
FileSourceActions:
$ref: "http://swgserver:8081/api/swagger/include/FileSource.yaml#/FileSourceActions"
PacketModActions:
$ref: "http://swgserver:8081/api/swagger/include/PacketMod.yaml#/PacketModActions"

Wyświetl plik

@ -51,6 +51,8 @@ ChannelSettings:
$ref: "http://swgserver:8081/api/swagger/include/LocalSink.yaml#/LocalSinkSettings"
LocalSourceSettings:
$ref: "http://swgserver:8081/api/swagger/include/LocalSource.yaml#/LocalSourceSettings"
PacketModSettings:
$ref: "http://swgserver:8081/api/swagger/include/PacketMod.yaml#/PacketModSettings"
RemoteSinkSettings:
$ref: "http://swgserver:8081/api/swagger/include/RemoteSink.yaml#/RemoteSinkSettings"
RemoteSourceSettings:

Wyświetl plik

@ -0,0 +1,83 @@
PacketModSettings:
description: PacketMod
properties:
inputFrequencyOffset:
type: integer
format: int64
rfBandwidth:
type: number
format: float
fmDeviation:
type: number
format: float
gain:
type: number
format: float
channelMute:
type: integer
repeat:
type: integer
repeatDelay:
type: number
format: float
repeatCount:
type: integer
ax25PreFlags:
type: integer
ax25PostFlags:
type: integer
preEmphasis:
type: integer
preEmphasisTau:
type: number
format: float
preEmphasisHighFreq:
type: number
format: float
rgbColor:
type: integer
title:
type: string
streamIndex:
description: MIMO channel. Not relevant when connected to SI (single Rx).
type: integer
useReverseAPI:
description: Synchronize with reverse API (1 for yes, 0 for no)
type: integer
reverseAPIAddress:
type: string
reverseAPIPort:
type: integer
reverseAPIDeviceIndex:
type: integer
reverseAPIChannelIndex:
type: integer
PacketModReport:
description: PacketMod
properties:
channelPowerDB:
description: power transmitted in channel (dB)
type: number
format: float
audioSampleRate:
type: integer
channelSampleRate:
type: integer
PacketModActions:
description: PacketMod
properties:
tx:
type: object
properties:
callsign:
type: string
to:
type: string
via:
type: string
data:
type: string
description: >
Transmit a packet

Wyświetl plik

@ -2356,6 +2356,8 @@ definitions:
$ref: "http://swgserver:8081/api/swagger/include/NFMDemod.yaml#/NFMDemodReport"
NFMModReport:
$ref: "http://swgserver:8081/api/swagger/include/NFMMod.yaml#/NFMModReport"
PacketModReport:
$ref: "http://swgserver:8081/api/swagger/include/PacketMod.yaml#/PacketModReport"
SSBDemodReport:
$ref: "http://swgserver:8081/api/swagger/include/SSBDemod.yaml#/SSBDemodReport"
RemoteSourceReport:

Wyświetl plik

@ -2036,6 +2036,9 @@ margin-bottom: 20px;
},
"FileSourceActions" : {
"$ref" : "#/definitions/FileSourceActions"
},
"PacketModActions" : {
"$ref" : "#/definitions/PacketModActions"
}
},
"description" : "Base channel actions. Only the channel actions corresponding to the channel specified in the channelType field is or should be present."
@ -2192,6 +2195,9 @@ margin-bottom: 20px;
"NFMModReport" : {
"$ref" : "#/definitions/NFMModReport"
},
"PacketModReport" : {
"$ref" : "#/definitions/PacketModReport"
},
"SSBDemodReport" : {
"$ref" : "#/definitions/SSBDemodReport"
},
@ -2287,6 +2293,9 @@ margin-bottom: 20px;
"LocalSourceSettings" : {
"$ref" : "#/definitions/LocalSourceSettings"
},
"PacketModSettings" : {
"$ref" : "#/definitions/PacketModSettings"
},
"RemoteSinkSettings" : {
"$ref" : "#/definitions/RemoteSinkSettings"
},
@ -4875,6 +4884,124 @@ margin-bottom: 20px;
}
},
"description" : "Enumeration with name for values"
};
defs.PacketModActions = {
"properties" : {
"tx" : {
"$ref" : "#/definitions/PacketModActions_tx"
}
},
"description" : "PacketMod"
};
defs.PacketModActions_tx = {
"properties" : {
"callsign" : {
"type" : "string"
},
"to" : {
"type" : "string"
},
"via" : {
"type" : "string"
},
"data" : {
"type" : "string"
}
},
"description" : "Transmit a packet\n"
};
defs.PacketModReport = {
"properties" : {
"channelPowerDB" : {
"type" : "number",
"format" : "float",
"description" : "power transmitted in channel (dB)"
},
"audioSampleRate" : {
"type" : "integer"
},
"channelSampleRate" : {
"type" : "integer"
}
},
"description" : "PacketMod"
};
defs.PacketModSettings = {
"properties" : {
"inputFrequencyOffset" : {
"type" : "integer",
"format" : "int64"
},
"rfBandwidth" : {
"type" : "number",
"format" : "float"
},
"fmDeviation" : {
"type" : "number",
"format" : "float"
},
"gain" : {
"type" : "number",
"format" : "float"
},
"channelMute" : {
"type" : "integer"
},
"repeat" : {
"type" : "integer"
},
"repeatDelay" : {
"type" : "number",
"format" : "float"
},
"repeatCount" : {
"type" : "integer"
},
"ax25PreFlags" : {
"type" : "integer"
},
"ax25PostFlags" : {
"type" : "integer"
},
"preEmphasis" : {
"type" : "integer"
},
"preEmphasisTau" : {
"type" : "number",
"format" : "float"
},
"preEmphasisHighFreq" : {
"type" : "number",
"format" : "float"
},
"rgbColor" : {
"type" : "integer"
},
"title" : {
"type" : "string"
},
"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"
}
},
"description" : "PacketMod"
};
defs.PerseusReport = {
"properties" : {
@ -33327,7 +33454,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2020-09-14T23:30:27.272+02:00
Generated 2020-09-18T15:59:26.503+02:00
</div>
</div>
</div>

Wyświetl plik

@ -40,6 +40,8 @@ SWGChannelActions::SWGChannelActions() {
m_file_sink_actions_isSet = false;
file_source_actions = nullptr;
m_file_source_actions_isSet = false;
packet_mod_actions = nullptr;
m_packet_mod_actions_isSet = false;
}
SWGChannelActions::~SWGChannelActions() {
@ -60,6 +62,8 @@ SWGChannelActions::init() {
m_file_sink_actions_isSet = false;
file_source_actions = new SWGFileSourceActions();
m_file_source_actions_isSet = false;
packet_mod_actions = new SWGPacketModActions();
m_packet_mod_actions_isSet = false;
}
void
@ -76,6 +80,9 @@ SWGChannelActions::cleanup() {
if(file_source_actions != nullptr) {
delete file_source_actions;
}
if(packet_mod_actions != nullptr) {
delete packet_mod_actions;
}
}
SWGChannelActions*
@ -101,6 +108,8 @@ SWGChannelActions::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&file_source_actions, pJson["FileSourceActions"], "SWGFileSourceActions", "SWGFileSourceActions");
::SWGSDRangel::setValue(&packet_mod_actions, pJson["PacketModActions"], "SWGPacketModActions", "SWGPacketModActions");
}
QString
@ -135,6 +144,9 @@ SWGChannelActions::asJsonObject() {
if((file_source_actions != nullptr) && (file_source_actions->isSet())){
toJsonValue(QString("FileSourceActions"), file_source_actions, obj, QString("SWGFileSourceActions"));
}
if((packet_mod_actions != nullptr) && (packet_mod_actions->isSet())){
toJsonValue(QString("PacketModActions"), packet_mod_actions, obj, QString("SWGPacketModActions"));
}
return obj;
}
@ -199,6 +211,16 @@ SWGChannelActions::setFileSourceActions(SWGFileSourceActions* file_source_action
this->m_file_source_actions_isSet = true;
}
SWGPacketModActions*
SWGChannelActions::getPacketModActions() {
return packet_mod_actions;
}
void
SWGChannelActions::setPacketModActions(SWGPacketModActions* packet_mod_actions) {
this->packet_mod_actions = packet_mod_actions;
this->m_packet_mod_actions_isSet = true;
}
bool
SWGChannelActions::isSet(){
@ -222,6 +244,9 @@ SWGChannelActions::isSet(){
if(file_source_actions && file_source_actions->isSet()){
isObjectUpdated = true; break;
}
if(packet_mod_actions && packet_mod_actions->isSet()){
isObjectUpdated = true; break;
}
}while(false);
return isObjectUpdated;
}

Wyświetl plik

@ -24,6 +24,7 @@
#include "SWGFileSinkActions.h"
#include "SWGFileSourceActions.h"
#include "SWGPacketModActions.h"
#include <QString>
#include "SWGObject.h"
@ -62,6 +63,9 @@ public:
SWGFileSourceActions* getFileSourceActions();
void setFileSourceActions(SWGFileSourceActions* file_source_actions);
SWGPacketModActions* getPacketModActions();
void setPacketModActions(SWGPacketModActions* packet_mod_actions);
virtual bool isSet() override;
@ -84,6 +88,9 @@ private:
SWGFileSourceActions* file_source_actions;
bool m_file_source_actions_isSet;
SWGPacketModActions* packet_mod_actions;
bool m_packet_mod_actions_isSet;
};
}

Wyświetl plik

@ -56,6 +56,8 @@ SWGChannelReport::SWGChannelReport() {
m_nfm_demod_report_isSet = false;
nfm_mod_report = nullptr;
m_nfm_mod_report_isSet = false;
packet_mod_report = nullptr;
m_packet_mod_report_isSet = false;
ssb_demod_report = nullptr;
m_ssb_demod_report_isSet = false;
remote_source_report = nullptr;
@ -106,6 +108,8 @@ SWGChannelReport::init() {
m_nfm_demod_report_isSet = false;
nfm_mod_report = new SWGNFMModReport();
m_nfm_mod_report_isSet = false;
packet_mod_report = new SWGPacketModReport();
m_packet_mod_report_isSet = false;
ssb_demod_report = new SWGSSBDemodReport();
m_ssb_demod_report_isSet = false;
remote_source_report = new SWGRemoteSourceReport();
@ -164,6 +168,9 @@ SWGChannelReport::cleanup() {
if(nfm_mod_report != nullptr) {
delete nfm_mod_report;
}
if(packet_mod_report != nullptr) {
delete packet_mod_report;
}
if(ssb_demod_report != nullptr) {
delete ssb_demod_report;
}
@ -226,6 +233,8 @@ SWGChannelReport::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&nfm_mod_report, pJson["NFMModReport"], "SWGNFMModReport", "SWGNFMModReport");
::SWGSDRangel::setValue(&packet_mod_report, pJson["PacketModReport"], "SWGPacketModReport", "SWGPacketModReport");
::SWGSDRangel::setValue(&ssb_demod_report, pJson["SSBDemodReport"], "SWGSSBDemodReport", "SWGSSBDemodReport");
::SWGSDRangel::setValue(&remote_source_report, pJson["RemoteSourceReport"], "SWGRemoteSourceReport", "SWGRemoteSourceReport");
@ -298,6 +307,9 @@ SWGChannelReport::asJsonObject() {
if((nfm_mod_report != nullptr) && (nfm_mod_report->isSet())){
toJsonValue(QString("NFMModReport"), nfm_mod_report, obj, QString("SWGNFMModReport"));
}
if((packet_mod_report != nullptr) && (packet_mod_report->isSet())){
toJsonValue(QString("PacketModReport"), packet_mod_report, obj, QString("SWGPacketModReport"));
}
if((ssb_demod_report != nullptr) && (ssb_demod_report->isSet())){
toJsonValue(QString("SSBDemodReport"), ssb_demod_report, obj, QString("SWGSSBDemodReport"));
}
@ -463,6 +475,16 @@ SWGChannelReport::setNfmModReport(SWGNFMModReport* nfm_mod_report) {
this->m_nfm_mod_report_isSet = true;
}
SWGPacketModReport*
SWGChannelReport::getPacketModReport() {
return packet_mod_report;
}
void
SWGChannelReport::setPacketModReport(SWGPacketModReport* packet_mod_report) {
this->packet_mod_report = packet_mod_report;
this->m_packet_mod_report_isSet = true;
}
SWGSSBDemodReport*
SWGChannelReport::getSsbDemodReport() {
return ssb_demod_report;
@ -580,6 +602,9 @@ SWGChannelReport::isSet(){
if(nfm_mod_report && nfm_mod_report->isSet()){
isObjectUpdated = true; break;
}
if(packet_mod_report && packet_mod_report->isSet()){
isObjectUpdated = true; break;
}
if(ssb_demod_report && ssb_demod_report->isSet()){
isObjectUpdated = true; break;
}

Wyświetl plik

@ -34,6 +34,7 @@
#include "SWGFreqTrackerReport.h"
#include "SWGNFMDemodReport.h"
#include "SWGNFMModReport.h"
#include "SWGPacketModReport.h"
#include "SWGRemoteSourceReport.h"
#include "SWGSSBDemodReport.h"
#include "SWGSSBModReport.h"
@ -103,6 +104,9 @@ public:
SWGNFMModReport* getNfmModReport();
void setNfmModReport(SWGNFMModReport* nfm_mod_report);
SWGPacketModReport* getPacketModReport();
void setPacketModReport(SWGPacketModReport* packet_mod_report);
SWGSSBDemodReport* getSsbDemodReport();
void setSsbDemodReport(SWGSSBDemodReport* ssb_demod_report);
@ -170,6 +174,9 @@ private:
SWGNFMModReport* nfm_mod_report;
bool m_nfm_mod_report_isSet;
SWGPacketModReport* packet_mod_report;
bool m_packet_mod_report_isSet;
SWGSSBDemodReport* ssb_demod_report;
bool m_ssb_demod_report_isSet;

Wyświetl plik

@ -70,6 +70,8 @@ SWGChannelSettings::SWGChannelSettings() {
m_local_sink_settings_isSet = false;
local_source_settings = nullptr;
m_local_source_settings_isSet = false;
packet_mod_settings = nullptr;
m_packet_mod_settings_isSet = false;
remote_sink_settings = nullptr;
m_remote_sink_settings_isSet = false;
remote_source_settings = nullptr;
@ -136,6 +138,8 @@ SWGChannelSettings::init() {
m_local_sink_settings_isSet = false;
local_source_settings = new SWGLocalSourceSettings();
m_local_source_settings_isSet = false;
packet_mod_settings = new SWGPacketModSettings();
m_packet_mod_settings_isSet = false;
remote_sink_settings = new SWGRemoteSinkSettings();
m_remote_sink_settings_isSet = false;
remote_source_settings = new SWGRemoteSourceSettings();
@ -213,6 +217,9 @@ SWGChannelSettings::cleanup() {
if(local_source_settings != nullptr) {
delete local_source_settings;
}
if(packet_mod_settings != nullptr) {
delete packet_mod_settings;
}
if(remote_sink_settings != nullptr) {
delete remote_sink_settings;
}
@ -292,6 +299,8 @@ SWGChannelSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&local_source_settings, pJson["LocalSourceSettings"], "SWGLocalSourceSettings", "SWGLocalSourceSettings");
::SWGSDRangel::setValue(&packet_mod_settings, pJson["PacketModSettings"], "SWGPacketModSettings", "SWGPacketModSettings");
::SWGSDRangel::setValue(&remote_sink_settings, pJson["RemoteSinkSettings"], "SWGRemoteSinkSettings", "SWGRemoteSinkSettings");
::SWGSDRangel::setValue(&remote_source_settings, pJson["RemoteSourceSettings"], "SWGRemoteSourceSettings", "SWGRemoteSourceSettings");
@ -387,6 +396,9 @@ SWGChannelSettings::asJsonObject() {
if((local_source_settings != nullptr) && (local_source_settings->isSet())){
toJsonValue(QString("LocalSourceSettings"), local_source_settings, obj, QString("SWGLocalSourceSettings"));
}
if((packet_mod_settings != nullptr) && (packet_mod_settings->isSet())){
toJsonValue(QString("PacketModSettings"), packet_mod_settings, obj, QString("SWGPacketModSettings"));
}
if((remote_sink_settings != nullptr) && (remote_sink_settings->isSet())){
toJsonValue(QString("RemoteSinkSettings"), remote_sink_settings, obj, QString("SWGRemoteSinkSettings"));
}
@ -625,6 +637,16 @@ SWGChannelSettings::setLocalSourceSettings(SWGLocalSourceSettings* local_source_
this->m_local_source_settings_isSet = true;
}
SWGPacketModSettings*
SWGChannelSettings::getPacketModSettings() {
return packet_mod_settings;
}
void
SWGChannelSettings::setPacketModSettings(SWGPacketModSettings* packet_mod_settings) {
this->packet_mod_settings = packet_mod_settings;
this->m_packet_mod_settings_isSet = true;
}
SWGRemoteSinkSettings*
SWGChannelSettings::getRemoteSinkSettings() {
return remote_sink_settings;
@ -773,6 +795,9 @@ SWGChannelSettings::isSet(){
if(local_source_settings && local_source_settings->isSet()){
isObjectUpdated = true; break;
}
if(packet_mod_settings && packet_mod_settings->isSet()){
isObjectUpdated = true; break;
}
if(remote_sink_settings && remote_sink_settings->isSet()){
isObjectUpdated = true; break;
}

Wyświetl plik

@ -39,6 +39,7 @@
#include "SWGLocalSourceSettings.h"
#include "SWGNFMDemodSettings.h"
#include "SWGNFMModSettings.h"
#include "SWGPacketModSettings.h"
#include "SWGRemoteSinkSettings.h"
#include "SWGRemoteSourceSettings.h"
#include "SWGSSBDemodSettings.h"
@ -130,6 +131,9 @@ public:
SWGLocalSourceSettings* getLocalSourceSettings();
void setLocalSourceSettings(SWGLocalSourceSettings* local_source_settings);
SWGPacketModSettings* getPacketModSettings();
void setPacketModSettings(SWGPacketModSettings* packet_mod_settings);
SWGRemoteSinkSettings* getRemoteSinkSettings();
void setRemoteSinkSettings(SWGRemoteSinkSettings* remote_sink_settings);
@ -221,6 +225,9 @@ private:
SWGLocalSourceSettings* local_source_settings;
bool m_local_source_settings_isSet;
SWGPacketModSettings* packet_mod_settings;
bool m_packet_mod_settings_isSet;
SWGRemoteSinkSettings* remote_sink_settings;
bool m_remote_sink_settings_isSet;

Wyświetl plik

@ -118,6 +118,10 @@
#include "SWGNFMModReport.h"
#include "SWGNFMModSettings.h"
#include "SWGNamedEnum.h"
#include "SWGPacketModActions.h"
#include "SWGPacketModActions_tx.h"
#include "SWGPacketModReport.h"
#include "SWGPacketModSettings.h"
#include "SWGPerseusReport.h"
#include "SWGPerseusSettings.h"
#include "SWGPlutoSdrInputReport.h"
@ -491,6 +495,18 @@ namespace SWGSDRangel {
if(QString("SWGNamedEnum").compare(type) == 0) {
return new SWGNamedEnum();
}
if(QString("SWGPacketModActions").compare(type) == 0) {
return new SWGPacketModActions();
}
if(QString("SWGPacketModActions_tx").compare(type) == 0) {
return new SWGPacketModActions_tx();
}
if(QString("SWGPacketModReport").compare(type) == 0) {
return new SWGPacketModReport();
}
if(QString("SWGPacketModSettings").compare(type) == 0) {
return new SWGPacketModSettings();
}
if(QString("SWGPerseusReport").compare(type) == 0) {
return new SWGPerseusReport();
}

Wyświetl plik

@ -0,0 +1,110 @@
/**
* 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: 4.15.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 "SWGPacketModActions.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGPacketModActions::SWGPacketModActions(QString* json) {
init();
this->fromJson(*json);
}
SWGPacketModActions::SWGPacketModActions() {
tx = nullptr;
m_tx_isSet = false;
}
SWGPacketModActions::~SWGPacketModActions() {
this->cleanup();
}
void
SWGPacketModActions::init() {
tx = new SWGPacketModActions_tx();
m_tx_isSet = false;
}
void
SWGPacketModActions::cleanup() {
if(tx != nullptr) {
delete tx;
}
}
SWGPacketModActions*
SWGPacketModActions::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGPacketModActions::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&tx, pJson["tx"], "SWGPacketModActions_tx", "SWGPacketModActions_tx");
}
QString
SWGPacketModActions::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGPacketModActions::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if((tx != nullptr) && (tx->isSet())){
toJsonValue(QString("tx"), tx, obj, QString("SWGPacketModActions_tx"));
}
return obj;
}
SWGPacketModActions_tx*
SWGPacketModActions::getTx() {
return tx;
}
void
SWGPacketModActions::setTx(SWGPacketModActions_tx* tx) {
this->tx = tx;
this->m_tx_isSet = true;
}
bool
SWGPacketModActions::isSet(){
bool isObjectUpdated = false;
do{
if(tx && tx->isSet()){
isObjectUpdated = true; break;
}
}while(false);
return isObjectUpdated;
}
}

Wyświetl plik

@ -0,0 +1,59 @@
/**
* 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: 4.15.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.
*/
/*
* SWGPacketModActions.h
*
* PacketMod
*/
#ifndef SWGPacketModActions_H_
#define SWGPacketModActions_H_
#include <QJsonObject>
#include "SWGPacketModActions_tx.h"
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGPacketModActions: public SWGObject {
public:
SWGPacketModActions();
SWGPacketModActions(QString* json);
virtual ~SWGPacketModActions();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGPacketModActions* fromJson(QString &jsonString) override;
SWGPacketModActions_tx* getTx();
void setTx(SWGPacketModActions_tx* tx);
virtual bool isSet() override;
private:
SWGPacketModActions_tx* tx;
bool m_tx_isSet;
};
}
#endif /* SWGPacketModActions_H_ */

Wyświetl plik

@ -0,0 +1,185 @@
/**
* 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: 4.15.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 "SWGPacketModActions_tx.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGPacketModActions_tx::SWGPacketModActions_tx(QString* json) {
init();
this->fromJson(*json);
}
SWGPacketModActions_tx::SWGPacketModActions_tx() {
callsign = nullptr;
m_callsign_isSet = false;
to = nullptr;
m_to_isSet = false;
via = nullptr;
m_via_isSet = false;
data = nullptr;
m_data_isSet = false;
}
SWGPacketModActions_tx::~SWGPacketModActions_tx() {
this->cleanup();
}
void
SWGPacketModActions_tx::init() {
callsign = new QString("");
m_callsign_isSet = false;
to = new QString("");
m_to_isSet = false;
via = new QString("");
m_via_isSet = false;
data = new QString("");
m_data_isSet = false;
}
void
SWGPacketModActions_tx::cleanup() {
if(callsign != nullptr) {
delete callsign;
}
if(to != nullptr) {
delete to;
}
if(via != nullptr) {
delete via;
}
if(data != nullptr) {
delete data;
}
}
SWGPacketModActions_tx*
SWGPacketModActions_tx::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGPacketModActions_tx::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&callsign, pJson["callsign"], "QString", "QString");
::SWGSDRangel::setValue(&to, pJson["to"], "QString", "QString");
::SWGSDRangel::setValue(&via, pJson["via"], "QString", "QString");
::SWGSDRangel::setValue(&data, pJson["data"], "QString", "QString");
}
QString
SWGPacketModActions_tx::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGPacketModActions_tx::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if(callsign != nullptr && *callsign != QString("")){
toJsonValue(QString("callsign"), callsign, obj, QString("QString"));
}
if(to != nullptr && *to != QString("")){
toJsonValue(QString("to"), to, obj, QString("QString"));
}
if(via != nullptr && *via != QString("")){
toJsonValue(QString("via"), via, obj, QString("QString"));
}
if(data != nullptr && *data != QString("")){
toJsonValue(QString("data"), data, obj, QString("QString"));
}
return obj;
}
QString*
SWGPacketModActions_tx::getCallsign() {
return callsign;
}
void
SWGPacketModActions_tx::setCallsign(QString* callsign) {
this->callsign = callsign;
this->m_callsign_isSet = true;
}
QString*
SWGPacketModActions_tx::getTo() {
return to;
}
void
SWGPacketModActions_tx::setTo(QString* to) {
this->to = to;
this->m_to_isSet = true;
}
QString*
SWGPacketModActions_tx::getVia() {
return via;
}
void
SWGPacketModActions_tx::setVia(QString* via) {
this->via = via;
this->m_via_isSet = true;
}
QString*
SWGPacketModActions_tx::getData() {
return data;
}
void
SWGPacketModActions_tx::setData(QString* data) {
this->data = data;
this->m_data_isSet = true;
}
bool
SWGPacketModActions_tx::isSet(){
bool isObjectUpdated = false;
do{
if(callsign && *callsign != QString("")){
isObjectUpdated = true; break;
}
if(to && *to != QString("")){
isObjectUpdated = true; break;
}
if(via && *via != QString("")){
isObjectUpdated = true; break;
}
if(data && *data != QString("")){
isObjectUpdated = true; break;
}
}while(false);
return isObjectUpdated;
}
}

Wyświetl plik

@ -0,0 +1,77 @@
/**
* SDRangel
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
*
* OpenAPI spec version: 4.15.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.
*/
/*
* SWGPacketModActions_tx.h
*
* Transmit a packet
*/
#ifndef SWGPacketModActions_tx_H_
#define SWGPacketModActions_tx_H_
#include <QJsonObject>
#include <QString>
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGPacketModActions_tx: public SWGObject {
public:
SWGPacketModActions_tx();
SWGPacketModActions_tx(QString* json);
virtual ~SWGPacketModActions_tx();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGPacketModActions_tx* fromJson(QString &jsonString) override;
QString* getCallsign();
void setCallsign(QString* callsign);
QString* getTo();
void setTo(QString* to);
QString* getVia();
void setVia(QString* via);
QString* getData();
void setData(QString* data);
virtual bool isSet() override;
private:
QString* callsign;
bool m_callsign_isSet;
QString* to;
bool m_to_isSet;
QString* via;
bool m_via_isSet;
QString* data;
bool m_data_isSet;
};
}
#endif /* SWGPacketModActions_tx_H_ */

Wyświetl plik

@ -0,0 +1,154 @@
/**
* 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: 4.15.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 "SWGPacketModReport.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGPacketModReport::SWGPacketModReport(QString* json) {
init();
this->fromJson(*json);
}
SWGPacketModReport::SWGPacketModReport() {
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;
}
SWGPacketModReport::~SWGPacketModReport() {
this->cleanup();
}
void
SWGPacketModReport::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;
}
void
SWGPacketModReport::cleanup() {
}
SWGPacketModReport*
SWGPacketModReport::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGPacketModReport::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", "");
}
QString
SWGPacketModReport::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGPacketModReport::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));
}
return obj;
}
float
SWGPacketModReport::getChannelPowerDb() {
return channel_power_db;
}
void
SWGPacketModReport::setChannelPowerDb(float channel_power_db) {
this->channel_power_db = channel_power_db;
this->m_channel_power_db_isSet = true;
}
qint32
SWGPacketModReport::getAudioSampleRate() {
return audio_sample_rate;
}
void
SWGPacketModReport::setAudioSampleRate(qint32 audio_sample_rate) {
this->audio_sample_rate = audio_sample_rate;
this->m_audio_sample_rate_isSet = true;
}
qint32
SWGPacketModReport::getChannelSampleRate() {
return channel_sample_rate;
}
void
SWGPacketModReport::setChannelSampleRate(qint32 channel_sample_rate) {
this->channel_sample_rate = channel_sample_rate;
this->m_channel_sample_rate_isSet = true;
}
bool
SWGPacketModReport::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;
}
}while(false);
return isObjectUpdated;
}
}

Wyświetl plik

@ -0,0 +1,70 @@
/**
* 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: 4.15.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.
*/
/*
* SWGPacketModReport.h
*
* PacketMod
*/
#ifndef SWGPacketModReport_H_
#define SWGPacketModReport_H_
#include <QJsonObject>
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGPacketModReport: public SWGObject {
public:
SWGPacketModReport();
SWGPacketModReport(QString* json);
virtual ~SWGPacketModReport();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGPacketModReport* 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);
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;
};
}
#endif /* SWGPacketModReport_H_ */

Wyświetl plik

@ -0,0 +1,572 @@
/**
* 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: 4.15.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 "SWGPacketModSettings.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGPacketModSettings::SWGPacketModSettings(QString* json) {
init();
this->fromJson(*json);
}
SWGPacketModSettings::SWGPacketModSettings() {
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;
gain = 0.0f;
m_gain_isSet = false;
channel_mute = 0;
m_channel_mute_isSet = false;
repeat = 0;
m_repeat_isSet = false;
repeat_delay = 0.0f;
m_repeat_delay_isSet = false;
repeat_count = 0;
m_repeat_count_isSet = false;
ax25_pre_flags = 0;
m_ax25_pre_flags_isSet = false;
ax25_post_flags = 0;
m_ax25_post_flags_isSet = false;
pre_emphasis = 0;
m_pre_emphasis_isSet = false;
pre_emphasis_tau = 0.0f;
m_pre_emphasis_tau_isSet = false;
pre_emphasis_high_freq = 0.0f;
m_pre_emphasis_high_freq_isSet = false;
rgb_color = 0;
m_rgb_color_isSet = false;
title = nullptr;
m_title_isSet = false;
stream_index = 0;
m_stream_index_isSet = false;
use_reverse_api = 0;
m_use_reverse_api_isSet = false;
reverse_api_address = nullptr;
m_reverse_api_address_isSet = false;
reverse_api_port = 0;
m_reverse_api_port_isSet = false;
reverse_api_device_index = 0;
m_reverse_api_device_index_isSet = false;
reverse_api_channel_index = 0;
m_reverse_api_channel_index_isSet = false;
}
SWGPacketModSettings::~SWGPacketModSettings() {
this->cleanup();
}
void
SWGPacketModSettings::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;
gain = 0.0f;
m_gain_isSet = false;
channel_mute = 0;
m_channel_mute_isSet = false;
repeat = 0;
m_repeat_isSet = false;
repeat_delay = 0.0f;
m_repeat_delay_isSet = false;
repeat_count = 0;
m_repeat_count_isSet = false;
ax25_pre_flags = 0;
m_ax25_pre_flags_isSet = false;
ax25_post_flags = 0;
m_ax25_post_flags_isSet = false;
pre_emphasis = 0;
m_pre_emphasis_isSet = false;
pre_emphasis_tau = 0.0f;
m_pre_emphasis_tau_isSet = false;
pre_emphasis_high_freq = 0.0f;
m_pre_emphasis_high_freq_isSet = false;
rgb_color = 0;
m_rgb_color_isSet = false;
title = new QString("");
m_title_isSet = false;
stream_index = 0;
m_stream_index_isSet = false;
use_reverse_api = 0;
m_use_reverse_api_isSet = false;
reverse_api_address = new QString("");
m_reverse_api_address_isSet = false;
reverse_api_port = 0;
m_reverse_api_port_isSet = false;
reverse_api_device_index = 0;
m_reverse_api_device_index_isSet = false;
reverse_api_channel_index = 0;
m_reverse_api_channel_index_isSet = false;
}
void
SWGPacketModSettings::cleanup() {
if(title != nullptr) {
delete title;
}
if(reverse_api_address != nullptr) {
delete reverse_api_address;
}
}
SWGPacketModSettings*
SWGPacketModSettings::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGPacketModSettings::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(&gain, pJson["gain"], "float", "");
::SWGSDRangel::setValue(&channel_mute, pJson["channelMute"], "qint32", "");
::SWGSDRangel::setValue(&repeat, pJson["repeat"], "qint32", "");
::SWGSDRangel::setValue(&repeat_delay, pJson["repeatDelay"], "float", "");
::SWGSDRangel::setValue(&repeat_count, pJson["repeatCount"], "qint32", "");
::SWGSDRangel::setValue(&ax25_pre_flags, pJson["ax25PreFlags"], "qint32", "");
::SWGSDRangel::setValue(&ax25_post_flags, pJson["ax25PostFlags"], "qint32", "");
::SWGSDRangel::setValue(&pre_emphasis, pJson["preEmphasis"], "qint32", "");
::SWGSDRangel::setValue(&pre_emphasis_tau, pJson["preEmphasisTau"], "float", "");
::SWGSDRangel::setValue(&pre_emphasis_high_freq, pJson["preEmphasisHighFreq"], "float", "");
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
::SWGSDRangel::setValue(&stream_index, pJson["streamIndex"], "qint32", "");
::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString");
::SWGSDRangel::setValue(&reverse_api_port, pJson["reverseAPIPort"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_device_index, pJson["reverseAPIDeviceIndex"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_channel_index, pJson["reverseAPIChannelIndex"], "qint32", "");
}
QString
SWGPacketModSettings::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGPacketModSettings::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_gain_isSet){
obj->insert("gain", QJsonValue(gain));
}
if(m_channel_mute_isSet){
obj->insert("channelMute", QJsonValue(channel_mute));
}
if(m_repeat_isSet){
obj->insert("repeat", QJsonValue(repeat));
}
if(m_repeat_delay_isSet){
obj->insert("repeatDelay", QJsonValue(repeat_delay));
}
if(m_repeat_count_isSet){
obj->insert("repeatCount", QJsonValue(repeat_count));
}
if(m_ax25_pre_flags_isSet){
obj->insert("ax25PreFlags", QJsonValue(ax25_pre_flags));
}
if(m_ax25_post_flags_isSet){
obj->insert("ax25PostFlags", QJsonValue(ax25_post_flags));
}
if(m_pre_emphasis_isSet){
obj->insert("preEmphasis", QJsonValue(pre_emphasis));
}
if(m_pre_emphasis_tau_isSet){
obj->insert("preEmphasisTau", QJsonValue(pre_emphasis_tau));
}
if(m_pre_emphasis_high_freq_isSet){
obj->insert("preEmphasisHighFreq", QJsonValue(pre_emphasis_high_freq));
}
if(m_rgb_color_isSet){
obj->insert("rgbColor", QJsonValue(rgb_color));
}
if(title != nullptr && *title != QString("")){
toJsonValue(QString("title"), title, obj, QString("QString"));
}
if(m_stream_index_isSet){
obj->insert("streamIndex", QJsonValue(stream_index));
}
if(m_use_reverse_api_isSet){
obj->insert("useReverseAPI", QJsonValue(use_reverse_api));
}
if(reverse_api_address != nullptr && *reverse_api_address != QString("")){
toJsonValue(QString("reverseAPIAddress"), reverse_api_address, obj, QString("QString"));
}
if(m_reverse_api_port_isSet){
obj->insert("reverseAPIPort", QJsonValue(reverse_api_port));
}
if(m_reverse_api_device_index_isSet){
obj->insert("reverseAPIDeviceIndex", QJsonValue(reverse_api_device_index));
}
if(m_reverse_api_channel_index_isSet){
obj->insert("reverseAPIChannelIndex", QJsonValue(reverse_api_channel_index));
}
return obj;
}
qint64
SWGPacketModSettings::getInputFrequencyOffset() {
return input_frequency_offset;
}
void
SWGPacketModSettings::setInputFrequencyOffset(qint64 input_frequency_offset) {
this->input_frequency_offset = input_frequency_offset;
this->m_input_frequency_offset_isSet = true;
}
float
SWGPacketModSettings::getRfBandwidth() {
return rf_bandwidth;
}
void
SWGPacketModSettings::setRfBandwidth(float rf_bandwidth) {
this->rf_bandwidth = rf_bandwidth;
this->m_rf_bandwidth_isSet = true;
}
float
SWGPacketModSettings::getFmDeviation() {
return fm_deviation;
}
void
SWGPacketModSettings::setFmDeviation(float fm_deviation) {
this->fm_deviation = fm_deviation;
this->m_fm_deviation_isSet = true;
}
float
SWGPacketModSettings::getGain() {
return gain;
}
void
SWGPacketModSettings::setGain(float gain) {
this->gain = gain;
this->m_gain_isSet = true;
}
qint32
SWGPacketModSettings::getChannelMute() {
return channel_mute;
}
void
SWGPacketModSettings::setChannelMute(qint32 channel_mute) {
this->channel_mute = channel_mute;
this->m_channel_mute_isSet = true;
}
qint32
SWGPacketModSettings::getRepeat() {
return repeat;
}
void
SWGPacketModSettings::setRepeat(qint32 repeat) {
this->repeat = repeat;
this->m_repeat_isSet = true;
}
float
SWGPacketModSettings::getRepeatDelay() {
return repeat_delay;
}
void
SWGPacketModSettings::setRepeatDelay(float repeat_delay) {
this->repeat_delay = repeat_delay;
this->m_repeat_delay_isSet = true;
}
qint32
SWGPacketModSettings::getRepeatCount() {
return repeat_count;
}
void
SWGPacketModSettings::setRepeatCount(qint32 repeat_count) {
this->repeat_count = repeat_count;
this->m_repeat_count_isSet = true;
}
qint32
SWGPacketModSettings::getAx25PreFlags() {
return ax25_pre_flags;
}
void
SWGPacketModSettings::setAx25PreFlags(qint32 ax25_pre_flags) {
this->ax25_pre_flags = ax25_pre_flags;
this->m_ax25_pre_flags_isSet = true;
}
qint32
SWGPacketModSettings::getAx25PostFlags() {
return ax25_post_flags;
}
void
SWGPacketModSettings::setAx25PostFlags(qint32 ax25_post_flags) {
this->ax25_post_flags = ax25_post_flags;
this->m_ax25_post_flags_isSet = true;
}
qint32
SWGPacketModSettings::getPreEmphasis() {
return pre_emphasis;
}
void
SWGPacketModSettings::setPreEmphasis(qint32 pre_emphasis) {
this->pre_emphasis = pre_emphasis;
this->m_pre_emphasis_isSet = true;
}
float
SWGPacketModSettings::getPreEmphasisTau() {
return pre_emphasis_tau;
}
void
SWGPacketModSettings::setPreEmphasisTau(float pre_emphasis_tau) {
this->pre_emphasis_tau = pre_emphasis_tau;
this->m_pre_emphasis_tau_isSet = true;
}
float
SWGPacketModSettings::getPreEmphasisHighFreq() {
return pre_emphasis_high_freq;
}
void
SWGPacketModSettings::setPreEmphasisHighFreq(float pre_emphasis_high_freq) {
this->pre_emphasis_high_freq = pre_emphasis_high_freq;
this->m_pre_emphasis_high_freq_isSet = true;
}
qint32
SWGPacketModSettings::getRgbColor() {
return rgb_color;
}
void
SWGPacketModSettings::setRgbColor(qint32 rgb_color) {
this->rgb_color = rgb_color;
this->m_rgb_color_isSet = true;
}
QString*
SWGPacketModSettings::getTitle() {
return title;
}
void
SWGPacketModSettings::setTitle(QString* title) {
this->title = title;
this->m_title_isSet = true;
}
qint32
SWGPacketModSettings::getStreamIndex() {
return stream_index;
}
void
SWGPacketModSettings::setStreamIndex(qint32 stream_index) {
this->stream_index = stream_index;
this->m_stream_index_isSet = true;
}
qint32
SWGPacketModSettings::getUseReverseApi() {
return use_reverse_api;
}
void
SWGPacketModSettings::setUseReverseApi(qint32 use_reverse_api) {
this->use_reverse_api = use_reverse_api;
this->m_use_reverse_api_isSet = true;
}
QString*
SWGPacketModSettings::getReverseApiAddress() {
return reverse_api_address;
}
void
SWGPacketModSettings::setReverseApiAddress(QString* reverse_api_address) {
this->reverse_api_address = reverse_api_address;
this->m_reverse_api_address_isSet = true;
}
qint32
SWGPacketModSettings::getReverseApiPort() {
return reverse_api_port;
}
void
SWGPacketModSettings::setReverseApiPort(qint32 reverse_api_port) {
this->reverse_api_port = reverse_api_port;
this->m_reverse_api_port_isSet = true;
}
qint32
SWGPacketModSettings::getReverseApiDeviceIndex() {
return reverse_api_device_index;
}
void
SWGPacketModSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) {
this->reverse_api_device_index = reverse_api_device_index;
this->m_reverse_api_device_index_isSet = true;
}
qint32
SWGPacketModSettings::getReverseApiChannelIndex() {
return reverse_api_channel_index;
}
void
SWGPacketModSettings::setReverseApiChannelIndex(qint32 reverse_api_channel_index) {
this->reverse_api_channel_index = reverse_api_channel_index;
this->m_reverse_api_channel_index_isSet = true;
}
bool
SWGPacketModSettings::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_gain_isSet){
isObjectUpdated = true; break;
}
if(m_channel_mute_isSet){
isObjectUpdated = true; break;
}
if(m_repeat_isSet){
isObjectUpdated = true; break;
}
if(m_repeat_delay_isSet){
isObjectUpdated = true; break;
}
if(m_repeat_count_isSet){
isObjectUpdated = true; break;
}
if(m_ax25_pre_flags_isSet){
isObjectUpdated = true; break;
}
if(m_ax25_post_flags_isSet){
isObjectUpdated = true; break;
}
if(m_pre_emphasis_isSet){
isObjectUpdated = true; break;
}
if(m_pre_emphasis_tau_isSet){
isObjectUpdated = true; break;
}
if(m_pre_emphasis_high_freq_isSet){
isObjectUpdated = true; break;
}
if(m_rgb_color_isSet){
isObjectUpdated = true; break;
}
if(title && *title != QString("")){
isObjectUpdated = true; break;
}
if(m_stream_index_isSet){
isObjectUpdated = true; break;
}
if(m_use_reverse_api_isSet){
isObjectUpdated = true; break;
}
if(reverse_api_address && *reverse_api_address != QString("")){
isObjectUpdated = true; break;
}
if(m_reverse_api_port_isSet){
isObjectUpdated = true; break;
}
if(m_reverse_api_device_index_isSet){
isObjectUpdated = true; break;
}
if(m_reverse_api_channel_index_isSet){
isObjectUpdated = true; break;
}
}while(false);
return isObjectUpdated;
}
}

Wyświetl plik

@ -0,0 +1,179 @@
/**
* 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: 4.15.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.
*/
/*
* SWGPacketModSettings.h
*
* PacketMod
*/
#ifndef SWGPacketModSettings_H_
#define SWGPacketModSettings_H_
#include <QJsonObject>
#include <QString>
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGPacketModSettings: public SWGObject {
public:
SWGPacketModSettings();
SWGPacketModSettings(QString* json);
virtual ~SWGPacketModSettings();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGPacketModSettings* 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 getGain();
void setGain(float gain);
qint32 getChannelMute();
void setChannelMute(qint32 channel_mute);
qint32 getRepeat();
void setRepeat(qint32 repeat);
float getRepeatDelay();
void setRepeatDelay(float repeat_delay);
qint32 getRepeatCount();
void setRepeatCount(qint32 repeat_count);
qint32 getAx25PreFlags();
void setAx25PreFlags(qint32 ax25_pre_flags);
qint32 getAx25PostFlags();
void setAx25PostFlags(qint32 ax25_post_flags);
qint32 getPreEmphasis();
void setPreEmphasis(qint32 pre_emphasis);
float getPreEmphasisTau();
void setPreEmphasisTau(float pre_emphasis_tau);
float getPreEmphasisHighFreq();
void setPreEmphasisHighFreq(float pre_emphasis_high_freq);
qint32 getRgbColor();
void setRgbColor(qint32 rgb_color);
QString* getTitle();
void setTitle(QString* title);
qint32 getStreamIndex();
void setStreamIndex(qint32 stream_index);
qint32 getUseReverseApi();
void setUseReverseApi(qint32 use_reverse_api);
QString* getReverseApiAddress();
void setReverseApiAddress(QString* reverse_api_address);
qint32 getReverseApiPort();
void setReverseApiPort(qint32 reverse_api_port);
qint32 getReverseApiDeviceIndex();
void setReverseApiDeviceIndex(qint32 reverse_api_device_index);
qint32 getReverseApiChannelIndex();
void setReverseApiChannelIndex(qint32 reverse_api_channel_index);
virtual bool isSet() override;
private:
qint64 input_frequency_offset;
bool m_input_frequency_offset_isSet;
float rf_bandwidth;
bool m_rf_bandwidth_isSet;
float fm_deviation;
bool m_fm_deviation_isSet;
float gain;
bool m_gain_isSet;
qint32 channel_mute;
bool m_channel_mute_isSet;
qint32 repeat;
bool m_repeat_isSet;
float repeat_delay;
bool m_repeat_delay_isSet;
qint32 repeat_count;
bool m_repeat_count_isSet;
qint32 ax25_pre_flags;
bool m_ax25_pre_flags_isSet;
qint32 ax25_post_flags;
bool m_ax25_post_flags_isSet;
qint32 pre_emphasis;
bool m_pre_emphasis_isSet;
float pre_emphasis_tau;
bool m_pre_emphasis_tau_isSet;
float pre_emphasis_high_freq;
bool m_pre_emphasis_high_freq_isSet;
qint32 rgb_color;
bool m_rgb_color_isSet;
QString* title;
bool m_title_isSet;
qint32 stream_index;
bool m_stream_index_isSet;
qint32 use_reverse_api;
bool m_use_reverse_api_isSet;
QString* reverse_api_address;
bool m_reverse_api_address_isSet;
qint32 reverse_api_port;
bool m_reverse_api_port_isSet;
qint32 reverse_api_device_index;
bool m_reverse_api_device_index_isSet;
qint32 reverse_api_channel_index;
bool m_reverse_api_channel_index_isSet;
};
}
#endif /* SWGPacketModSettings_H_ */