mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-02-03 09:44:01 -05:00
Merge pull request #2005 from srcejon/freq_scanner
Add End-of-Train demodulator
This commit is contained in:
commit
d48e9620df
@ -93,6 +93,7 @@ option(ENABLE_CHANNELRX_DEMODILS "Enable channelrx demodils plugin" ON)
|
||||
option(ENABLE_CHANNELRX_DEMODDSC "Enable channelrx demoddsc plugin" ON)
|
||||
option(ENABLE_CHANNELRX_HEATMAP "Enable channelrx heatmap plugin" ON)
|
||||
option(ENABLE_CHANNELRX_FREQSCANNER "Enable channelrx freqscanner plugin" ON)
|
||||
option(ENABLE_CHANNELRX_ENDOFTRAIN "Enable channelrx end-of-train plugin" ON)
|
||||
|
||||
# Channel Tx enablers
|
||||
option(ENABLE_CHANNELTX "Enable channeltx plugins" ON)
|
||||
|
BIN
doc/img/EndOfTrainDemod_plugin.png
Normal file
BIN
doc/img/EndOfTrainDemod_plugin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
@ -1,5 +1,9 @@
|
||||
project(demod)
|
||||
|
||||
if (ENABLE_CHANNELRX_ENDOFTRAIN)
|
||||
add_subdirectory(demodendoftrain)
|
||||
endif()
|
||||
|
||||
if (ENABLE_CHANNELRX_FREQSCANNER)
|
||||
add_subdirectory(freqscanner)
|
||||
endif()
|
||||
|
@ -310,6 +310,9 @@ void AISDemod::applySettings(const AISDemodSettings& settings, bool force)
|
||||
if ((settings.m_logEnabled != m_settings.m_logEnabled) || force) {
|
||||
reverseAPIKeys.append("logEnabled");
|
||||
}
|
||||
if ((settings.m_useFileTime != m_settings.m_useFileTime) || force) {
|
||||
reverseAPIKeys.append("useFileTime");
|
||||
}
|
||||
if (m_settings.m_streamIndex != settings.m_streamIndex)
|
||||
{
|
||||
if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only
|
||||
@ -495,6 +498,9 @@ void AISDemod::webapiUpdateChannelSettings(
|
||||
if (channelSettingsKeys.contains("logEnabled")) {
|
||||
settings.m_logEnabled = response.getAisDemodSettings()->getLogEnabled();
|
||||
}
|
||||
if (channelSettingsKeys.contains("useFileTime")) {
|
||||
settings.m_useFileTime = response.getAisDemodSettings()->getUseFileTime();
|
||||
}
|
||||
if (channelSettingsKeys.contains("rgbColor")) {
|
||||
settings.m_rgbColor = response.getAisDemodSettings()->getRgbColor();
|
||||
}
|
||||
@ -543,6 +549,7 @@ void AISDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& resp
|
||||
response.getAisDemodSettings()->setUdpFormat((int)settings.m_udpFormat);
|
||||
response.getAisDemodSettings()->setLogFilename(new QString(settings.m_logFilename));
|
||||
response.getAisDemodSettings()->setLogEnabled(settings.m_logEnabled);
|
||||
response.getAisDemodSettings()->setUseFileTime(settings.m_useFileTime);
|
||||
|
||||
response.getAisDemodSettings()->setRgbColor(settings.m_rgbColor);
|
||||
if (response.getAisDemodSettings()->getTitle()) {
|
||||
@ -681,6 +688,9 @@ void AISDemod::webapiFormatChannelSettings(
|
||||
if (channelSettingsKeys.contains("logEnabled") || force) {
|
||||
swgAISDemodSettings->setLogEnabled(settings.m_logEnabled);
|
||||
}
|
||||
if (channelSettingsKeys.contains("useFileTime") || force) {
|
||||
swgAISDemodSettings->setUseFileTime(settings.m_useFileTime);
|
||||
}
|
||||
if (channelSettingsKeys.contains("rgbColor") || force) {
|
||||
swgAISDemodSettings->setRgbColor(settings.m_rgbColor);
|
||||
}
|
||||
|
@ -916,6 +916,8 @@ void AISDemodGUI::displaySettings()
|
||||
ui->showSlotMap->setChecked(m_settings.m_showSlotMap);
|
||||
ui->slotMapWidget->setVisible(m_settings.m_showSlotMap);
|
||||
|
||||
ui->useFileTime->setChecked(m_settings.m_useFileTime);
|
||||
|
||||
// Order and size columns
|
||||
QHeaderView *header = ui->messages->horizontalHeader();
|
||||
for (int i = 0; i < AISDEMOD_MESSAGE_COLUMNS; i++)
|
||||
@ -1088,6 +1090,12 @@ void AISDemodGUI::on_logOpen_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
void AISDemodGUI::on_useFileTime_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_useFileTime = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void AISDemodGUI::makeUIConnections()
|
||||
{
|
||||
QObject::connect(ui->deltaFrequency, &ValueDialZ::changed, this, &AISDemodGUI::on_deltaFrequency_changed);
|
||||
@ -1105,6 +1113,7 @@ void AISDemodGUI::makeUIConnections()
|
||||
QObject::connect(ui->logFilename, &QToolButton::clicked, this, &AISDemodGUI::on_logFilename_clicked);
|
||||
QObject::connect(ui->logOpen, &QToolButton::clicked, this, &AISDemodGUI::on_logOpen_clicked);
|
||||
QObject::connect(ui->showSlotMap, &ButtonSwitch::clicked, this, &AISDemodGUI::on_showSlotMap_clicked);
|
||||
QObject::connect(ui->useFileTime, &ButtonSwitch::toggled, this, &AISDemodGUI::on_useFileTime_toggled);
|
||||
}
|
||||
|
||||
void AISDemodGUI::updateAbsoluteCenterFrequency()
|
||||
|
@ -159,6 +159,7 @@ private slots:
|
||||
void on_logFilename_clicked();
|
||||
void on_logOpen_clicked();
|
||||
void on_showSlotMap_clicked(bool checked=false);
|
||||
void on_useFileTime_toggled(bool checked=false);
|
||||
void filterRow(int row);
|
||||
void filter();
|
||||
void messages_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex);
|
||||
|
@ -557,6 +557,27 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="useFileTime">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Check to use date and time from input file. Uncheck to use date and time from clock.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/clockcurrent.png</normaloff>
|
||||
<normalon>:/clockfile.png</normalon>:/clockcurrent.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="showSlotMap">
|
||||
<property name="maximumSize">
|
||||
@ -958,18 +979,18 @@
|
||||
<extends>QToolButton</extends>
|
||||
<header>gui/buttonswitch.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RollupContents</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupcontents.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ValueDialZ</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/valuedialz.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RollupContents</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupcontents.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LevelMeterSignalDB</class>
|
||||
<extends>QWidget</extends>
|
||||
|
@ -48,6 +48,7 @@ void AISDemodSettings::resetToDefaults()
|
||||
m_logFilename = "ais_log.csv";
|
||||
m_logEnabled = false;
|
||||
m_showSlotMap = false;
|
||||
m_useFileTime = false;
|
||||
m_rgbColor = QColor(102, 0, 0).rgb();
|
||||
m_title = "AIS Demodulator";
|
||||
m_streamIndex = 0;
|
||||
@ -105,6 +106,7 @@ QByteArray AISDemodSettings::serialize() const
|
||||
s.writeBlob(27, m_geometryBytes);
|
||||
s.writeBool(28, m_hidden);
|
||||
s.writeBool(29, m_showSlotMap);
|
||||
s.writeBool(30, m_useFileTime);
|
||||
|
||||
for (int i = 0; i < AISDEMOD_MESSAGE_COLUMNS; i++)
|
||||
s.writeS32(100 + i, m_messageColumnIndexes[i]);
|
||||
@ -191,6 +193,7 @@ bool AISDemodSettings::deserialize(const QByteArray& data)
|
||||
d.readBlob(27, &m_geometryBytes);
|
||||
d.readBool(28, &m_hidden, false);
|
||||
d.readBool(29, &m_showSlotMap, false);
|
||||
d.readBool(30, &m_useFileTime, false);
|
||||
|
||||
for (int i = 0; i < AISDEMOD_MESSAGE_COLUMNS; i++) {
|
||||
d.readS32(100 + i, &m_messageColumnIndexes[i], i);
|
||||
|
@ -50,6 +50,7 @@ struct AISDemodSettings
|
||||
QString m_logFilename;
|
||||
bool m_logEnabled;
|
||||
bool m_showSlotMap;
|
||||
bool m_useFileTime;
|
||||
|
||||
quint32 m_rgbColor;
|
||||
QString m_title;
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/datafifo.h"
|
||||
#include "dsp/scopevis.h"
|
||||
#include "device/deviceapi.h"
|
||||
#include "channel/channelwebapiutils.h"
|
||||
#include "util/db.h"
|
||||
#include "util/stepfunctions.h"
|
||||
#include "maincore.h"
|
||||
@ -264,6 +266,21 @@ void AISDemodSink::processOneSample(Complex &ci)
|
||||
// This is unlikely to be accurate in absolute terms, given we don't know latency from SDR or buffering within SDRangel
|
||||
// But can be used to get an idea of congestion
|
||||
QDateTime currentTime = QDateTime::currentDateTime();
|
||||
if (m_settings.m_useFileTime)
|
||||
{
|
||||
QString hardwareId = m_aisDemod->getDeviceAPI()->getHardwareId();
|
||||
|
||||
if ((hardwareId == "FileInput") || (hardwareId == "SigMFFileInput"))
|
||||
{
|
||||
QString dateTimeStr;
|
||||
int deviceIdx = m_aisDemod->getDeviceSetIndex();
|
||||
|
||||
if (ChannelWebAPIUtils::getDeviceReportValue(deviceIdx, "absoluteTime", dateTimeStr)) {
|
||||
currentTime = QDateTime::fromString(dateTimeStr, Qt::ISODateWithMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int txTimeMs = (totalBitCount + 8 + 24 + 8) * (1000.0 / m_settings.m_baud); // Add ramp up, preamble and start-flag
|
||||
QDateTime startDateTime = currentTime.addMSecs(-txTimeMs);
|
||||
int ms = startDateTime.time().second() * 1000 + startDateTime.time().msec();
|
||||
|
@ -56,7 +56,7 @@ Pressing this button clears all messages from the table.
|
||||
|
||||
<h3>9: UDP</h3>
|
||||
|
||||
When checked, received messages are forwarded to the specified UDP address (12) and port (13).
|
||||
When checked, received messages are forwarded to the specified UDP address (10) and port (11).
|
||||
|
||||
<h3>10: UDP address</h3>
|
||||
|
||||
@ -70,17 +70,22 @@ UDP port number to forward received messages to.
|
||||
|
||||
The format the messages are forwarded via UDP in. This can be either binary (which is useful for SDRangel's PERTester feature) or NMEA (which is useful for 3rd party applications such as OpenCPN).
|
||||
|
||||
<h3>13: Start/stop Logging Messages to .csv File</h3>
|
||||
<h3>13: Use Date and Time from File</h3>
|
||||
|
||||
When checked, if the source device is a File Input device, the date and time used for
|
||||
packet reception time is taken from the file playback time. Otherwise, the current system clock time is used.
|
||||
|
||||
<h3>14: Start/stop Logging Messages to .csv File</h3>
|
||||
|
||||
When checked, writes all received AIS messages to a .csv file.
|
||||
|
||||
<h3>14: .csv Log Filename</h3>
|
||||
<h3>15: .csv Log Filename</h3>
|
||||
|
||||
Click to specify the name of the .csv file which received AIS messages are logged to.
|
||||
|
||||
<h3>15: Read Data from .csv File</h3>
|
||||
<h3>16: Read Data from .csv File</h3>
|
||||
|
||||
Click to specify a previously written AIS .csv log file, which is read and used to update the table.
|
||||
Click to specify a previously written .csv log file, which is read and used to update the table.
|
||||
|
||||
<h3>Slot Map</h3>
|
||||
|
||||
|
@ -314,6 +314,9 @@ void DSCDemod::applySettings(const DSCDemodSettings& settings, bool force)
|
||||
if ((settings.m_logEnabled != m_settings.m_logEnabled) || force) {
|
||||
reverseAPIKeys.append("logEnabled");
|
||||
}
|
||||
if ((settings.m_useFileTime != m_settings.m_useFileTime) || force) {
|
||||
reverseAPIKeys.append("useFileTime");
|
||||
}
|
||||
if (m_settings.m_streamIndex != settings.m_streamIndex)
|
||||
{
|
||||
if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only
|
||||
@ -502,10 +505,13 @@ void DSCDemod::webapiUpdateChannelSettings(
|
||||
settings.m_udpPort = response.getDscDemodSettings()->getUdpPort();
|
||||
}
|
||||
if (channelSettingsKeys.contains("logFilename")) {
|
||||
settings.m_logFilename = *response.getAdsbDemodSettings()->getLogFilename();
|
||||
settings.m_logFilename = *response.getDscDemodSettings()->getLogFilename();
|
||||
}
|
||||
if (channelSettingsKeys.contains("logEnabled")) {
|
||||
settings.m_logEnabled = response.getAdsbDemodSettings()->getLogEnabled();
|
||||
settings.m_logEnabled = response.getDscDemodSettings()->getLogEnabled();
|
||||
}
|
||||
if (channelSettingsKeys.contains("useFileTime")) {
|
||||
settings.m_useFileTime = response.getDscDemodSettings()->getUseFileTime();
|
||||
}
|
||||
if (channelSettingsKeys.contains("rgbColor")) {
|
||||
settings.m_rgbColor = response.getDscDemodSettings()->getRgbColor();
|
||||
@ -554,6 +560,7 @@ void DSCDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& resp
|
||||
response.getDscDemodSettings()->setUdpPort(settings.m_udpPort);
|
||||
response.getDscDemodSettings()->setLogFilename(new QString(settings.m_logFilename));
|
||||
response.getDscDemodSettings()->setLogEnabled(settings.m_logEnabled);
|
||||
response.getDscDemodSettings()->setUseFileTime(settings.m_useFileTime);
|
||||
|
||||
response.getDscDemodSettings()->setRgbColor(settings.m_rgbColor);
|
||||
if (response.getDscDemodSettings()->getTitle()) {
|
||||
@ -698,6 +705,9 @@ void DSCDemod::webapiFormatChannelSettings(
|
||||
if (channelSettingsKeys.contains("logEnabled") || force) {
|
||||
swgDSCDemodSettings->setLogEnabled(settings.m_logEnabled);
|
||||
}
|
||||
if (channelSettingsKeys.contains("useFileTime") || force) {
|
||||
swgDSCDemodSettings->setUseFileTime(settings.m_useFileTime);
|
||||
}
|
||||
if (channelSettingsKeys.contains("rgbColor") || force) {
|
||||
swgDSCDemodSettings->setRgbColor(settings.m_rgbColor);
|
||||
}
|
||||
|
@ -1009,6 +1009,7 @@ void DSCDemodGUI::displaySettings()
|
||||
ui->logFilename->setToolTip(QString(".csv log filename: %1").arg(m_settings.m_logFilename));
|
||||
ui->logEnable->setChecked(m_settings.m_logEnabled);
|
||||
|
||||
ui->useFileTime->setChecked(m_settings.m_useFileTime);
|
||||
ui->feed->setChecked(m_settings.m_feed);
|
||||
|
||||
// Order and size columns
|
||||
@ -1169,6 +1170,12 @@ void DSCDemodGUI::on_logOpen_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
void DSCDemodGUI::on_useFileTime_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_useFileTime = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void DSCDemodGUI::makeUIConnections()
|
||||
{
|
||||
QObject::connect(ui->deltaFrequency, &ValueDialZ::changed, this, &DSCDemodGUI::on_deltaFrequency_changed);
|
||||
@ -1183,6 +1190,7 @@ void DSCDemodGUI::makeUIConnections()
|
||||
QObject::connect(ui->logFilename, &QToolButton::clicked, this, &DSCDemodGUI::on_logFilename_clicked);
|
||||
QObject::connect(ui->logOpen, &QToolButton::clicked, this, &DSCDemodGUI::on_logOpen_clicked);
|
||||
QObject::connect(ui->feed, &ButtonSwitch::clicked, this, &DSCDemodGUI::on_feed_clicked);
|
||||
QObject::connect(ui->useFileTime, &ButtonSwitch::toggled, this, &DSCDemodGUI::on_useFileTime_toggled);
|
||||
}
|
||||
|
||||
void DSCDemodGUI::updateAbsoluteCenterFrequency()
|
||||
|
@ -151,6 +151,7 @@ private slots:
|
||||
void on_logEnable_clicked(bool checked=false);
|
||||
void on_logFilename_clicked();
|
||||
void on_logOpen_clicked();
|
||||
void on_useFileTime_toggled(bool checked=false);
|
||||
void on_feed_clicked(bool checked=false);
|
||||
void on_feed_rightClicked(const QPoint &point);
|
||||
void filterRow(int row);
|
||||
|
@ -545,6 +545,27 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="useFileTime">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Check to use date and time from input file. Uncheck to use date and time from clock.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/clockcurrent.png</normaloff>
|
||||
<normalon>:/clockfile.png</normalon>:/clockcurrent.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="logEnable">
|
||||
<property name="maximumSize">
|
||||
@ -934,18 +955,18 @@
|
||||
<extends>QToolButton</extends>
|
||||
<header>gui/buttonswitch.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RollupContents</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupcontents.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ValueDialZ</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/valuedialz.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RollupContents</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupcontents.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LevelMeterSignalDB</class>
|
||||
<extends>QWidget</extends>
|
||||
|
@ -46,6 +46,7 @@ void DSCDemodSettings::resetToDefaults()
|
||||
m_logFilename = "dsc_log.csv";
|
||||
m_logEnabled = false;
|
||||
m_feed = true;
|
||||
m_useFileTime = false;
|
||||
|
||||
m_rgbColor = QColor(181, 230, 29).rgb();
|
||||
m_title = "DSC Demodulator";
|
||||
@ -85,6 +86,7 @@ QByteArray DSCDemodSettings::serialize() const
|
||||
s.writeString(12, m_logFilename);
|
||||
s.writeBool(13, m_logEnabled);
|
||||
s.writeBool(14, m_feed);
|
||||
s.writeBool(15, m_useFileTime);
|
||||
|
||||
s.writeU32(20, m_rgbColor);
|
||||
s.writeString(21, m_title);
|
||||
@ -155,6 +157,7 @@ bool DSCDemodSettings::deserialize(const QByteArray& data)
|
||||
d.readString(12, &m_logFilename, "dsc_log.csv");
|
||||
d.readBool(13, &m_logEnabled, false);
|
||||
d.readBool(14, &m_feed, true);
|
||||
d.readBool(15, &m_useFileTime, false);
|
||||
|
||||
d.readU32(20, &m_rgbColor, QColor(181, 230, 29).rgb());
|
||||
d.readString(21, &m_title, "DSC Demodulator");
|
||||
|
@ -52,6 +52,8 @@ struct DSCDemodSettings
|
||||
|
||||
QString m_logFilename;
|
||||
bool m_logEnabled;
|
||||
|
||||
bool m_useFileTime;
|
||||
Serializable *m_scopeGUI;
|
||||
Serializable *m_rollupState;
|
||||
int m_workspaceIndex;
|
||||
|
@ -21,8 +21,10 @@
|
||||
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/scopevis.h"
|
||||
#include "device/deviceapi.h"
|
||||
#include "util/db.h"
|
||||
#include "util/popcount.h"
|
||||
#include "channel/channelwebapiutils.h"
|
||||
#include "maincore.h"
|
||||
|
||||
#include "dscdemod.h"
|
||||
@ -240,8 +242,25 @@ void DSCDemodSink::receiveBit(bool bit)
|
||||
{
|
||||
if (m_dscDecoder.decodeBits(m_bits & 0x3ff))
|
||||
{
|
||||
QDateTime dateTime = QDateTime::currentDateTime();
|
||||
|
||||
if (m_settings.m_useFileTime)
|
||||
{
|
||||
QString hardwareId = m_dscDemod->getDeviceAPI()->getHardwareId();
|
||||
|
||||
if ((hardwareId == "FileInput") || (hardwareId == "SigMFFileInput"))
|
||||
{
|
||||
QString dateTimeStr;
|
||||
int deviceIdx = m_dscDemod->getDeviceSetIndex();
|
||||
|
||||
if (ChannelWebAPIUtils::getDeviceReportValue(deviceIdx, "absoluteTime", dateTimeStr)) {
|
||||
dateTime = QDateTime::fromString(dateTimeStr, Qt::ISODateWithMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray bytes = m_dscDecoder.getMessage();
|
||||
DSCMessage message(bytes, QDateTime::currentDateTime());
|
||||
DSCMessage message(bytes, dateTime);
|
||||
//qDebug() << "RX Bytes: " << bytes.toHex();
|
||||
//qDebug() << "DSC Message: " << message.toString();
|
||||
|
||||
|
@ -60,19 +60,24 @@ The messages are submitted with Preferences > My Position... > Station name used
|
||||
|
||||
Right click to open http://yaddnet.org/ in your browser, showing recent messages received from this ID.
|
||||
|
||||
<h3>11: Start/stop Logging Messages to .csv File</h3>
|
||||
<h3>11: Use Date and Time from File</h3>
|
||||
|
||||
When checked, writes all received messages to a .csv file, specified by (12).
|
||||
When checked, if the source device is a File Input device, the date and time used for
|
||||
packet reception time is taken from the file playback time. Otherwise, the current system clock time is used.
|
||||
|
||||
<h3>12: .csv Log Filename</h3>
|
||||
<h3>12: Start/stop Logging Messages to .csv File</h3>
|
||||
|
||||
When checked, writes all received messages to a .csv file, specified by (13).
|
||||
|
||||
<h3>13: .csv Log Filename</h3>
|
||||
|
||||
Click to specify the name of the .csv file which received messasges are logged to.
|
||||
|
||||
<h3>13: Read Data from .csv File</h3>
|
||||
<h3>14: Read Data from .csv File</h3>
|
||||
|
||||
Click to specify a previously written .csv log file, which is read and used to update the table.
|
||||
|
||||
<h3>14: Received Messages Table</h3>
|
||||
<h3>15: Received Messages Table</h3>
|
||||
|
||||

|
||||
|
||||
|
65
plugins/channelrx/demodendoftrain/CMakeLists.txt
Normal file
65
plugins/channelrx/demodendoftrain/CMakeLists.txt
Normal file
@ -0,0 +1,65 @@
|
||||
project(demodendoftrain)
|
||||
|
||||
set(demodendoftrain_SOURCES
|
||||
endoftraindemod.cpp
|
||||
endoftraindemodsettings.cpp
|
||||
endoftraindemodbaseband.cpp
|
||||
endoftraindemodsink.cpp
|
||||
endoftraindemodplugin.cpp
|
||||
endoftraindemodwebapiadapter.cpp
|
||||
endoftrainpacket.cpp
|
||||
)
|
||||
|
||||
set(demodendoftrain_HEADERS
|
||||
endoftraindemod.h
|
||||
endoftraindemodsettings.h
|
||||
endoftraindemodbaseband.h
|
||||
endoftraindemodsink.h
|
||||
endoftraindemodplugin.h
|
||||
endoftraindemodwebapiadapter.h
|
||||
endoftrainpacket.h
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
|
||||
)
|
||||
|
||||
if(NOT SERVER_MODE)
|
||||
set(demodendoftrain_SOURCES
|
||||
${demodendoftrain_SOURCES}
|
||||
endoftraindemodgui.cpp
|
||||
endoftraindemodgui.ui
|
||||
)
|
||||
set(demodendoftrain_HEADERS
|
||||
${demodendoftrain_HEADERS}
|
||||
endoftraindemodgui.h
|
||||
)
|
||||
|
||||
set(TARGET_NAME demodendoftrain)
|
||||
set(TARGET_LIB "Qt::Widgets")
|
||||
set(TARGET_LIB_GUI "sdrgui")
|
||||
set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR})
|
||||
else()
|
||||
set(TARGET_NAME demodendoftrainsrv)
|
||||
set(TARGET_LIB "")
|
||||
set(TARGET_LIB_GUI "")
|
||||
set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR})
|
||||
endif()
|
||||
|
||||
add_library(${TARGET_NAME} SHARED
|
||||
${demodendoftrain_SOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(${TARGET_NAME}
|
||||
Qt::Core
|
||||
${TARGET_LIB}
|
||||
sdrbase
|
||||
${TARGET_LIB_GUI}
|
||||
)
|
||||
|
||||
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})
|
||||
|
||||
# Install debug symbols
|
||||
if (WIN32)
|
||||
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
|
||||
endif()
|
678
plugins/channelrx/demodendoftrain/endoftraindemod.cpp
Normal file
678
plugins/channelrx/demodendoftrain/endoftraindemod.cpp
Normal file
@ -0,0 +1,678 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2021-2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// Copyright (C) 2021-2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// //
|
||||
// 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 "endoftraindemod.h"
|
||||
#include "endoftrainpacket.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QBuffer>
|
||||
#include <QThread>
|
||||
|
||||
#include "SWGChannelSettings.h"
|
||||
#include "SWGWorkspaceInfo.h"
|
||||
#include "SWGEndOfTrainDemodSettings.h"
|
||||
#include "SWGChannelReport.h"
|
||||
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
#include "device/deviceapi.h"
|
||||
#include "settings/serializable.h"
|
||||
#include "util/db.h"
|
||||
#include "maincore.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(EndOfTrainDemod::MsgConfigureEndOfTrainDemod, Message)
|
||||
|
||||
const char * const EndOfTrainDemod::m_channelIdURI = "sdrangel.channel.endoftraindemod";
|
||||
const char * const EndOfTrainDemod::m_channelId = "EndOfTrainDemod";
|
||||
|
||||
EndOfTrainDemod::EndOfTrainDemod(DeviceAPI *deviceAPI) :
|
||||
ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSink),
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_basebandSampleRate(0)
|
||||
{
|
||||
setObjectName(m_channelId);
|
||||
|
||||
m_basebandSink = new EndOfTrainDemodBaseband(this);
|
||||
m_basebandSink->setMessageQueueToChannel(getInputMessageQueue());
|
||||
m_basebandSink->setChannel(this);
|
||||
m_basebandSink->moveToThread(&m_thread);
|
||||
|
||||
applySettings(m_settings, QStringList(), true);
|
||||
|
||||
m_deviceAPI->addChannelSink(this);
|
||||
m_deviceAPI->addChannelSinkAPI(this);
|
||||
|
||||
m_networkManager = new QNetworkAccessManager();
|
||||
QObject::connect(
|
||||
m_networkManager,
|
||||
&QNetworkAccessManager::finished,
|
||||
this,
|
||||
&EndOfTrainDemod::networkManagerFinished
|
||||
);
|
||||
QObject::connect(
|
||||
this,
|
||||
&ChannelAPI::indexInDeviceSetChanged,
|
||||
this,
|
||||
&EndOfTrainDemod::handleIndexInDeviceSetChanged
|
||||
);
|
||||
}
|
||||
|
||||
EndOfTrainDemod::~EndOfTrainDemod()
|
||||
{
|
||||
qDebug("EndOfTrainDemod::~EndOfTrainDemod");
|
||||
QObject::disconnect(
|
||||
m_networkManager,
|
||||
&QNetworkAccessManager::finished,
|
||||
this,
|
||||
&EndOfTrainDemod::networkManagerFinished
|
||||
);
|
||||
delete m_networkManager;
|
||||
m_deviceAPI->removeChannelSinkAPI(this);
|
||||
m_deviceAPI->removeChannelSink(this);
|
||||
|
||||
if (m_basebandSink->isRunning()) {
|
||||
stop();
|
||||
}
|
||||
|
||||
delete m_basebandSink;
|
||||
}
|
||||
|
||||
void EndOfTrainDemod::setDeviceAPI(DeviceAPI *deviceAPI)
|
||||
{
|
||||
if (deviceAPI != m_deviceAPI)
|
||||
{
|
||||
m_deviceAPI->removeChannelSinkAPI(this);
|
||||
m_deviceAPI->removeChannelSink(this);
|
||||
m_deviceAPI = deviceAPI;
|
||||
m_deviceAPI->addChannelSink(this);
|
||||
m_deviceAPI->addChannelSinkAPI(this);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EndOfTrainDemod::getNumberOfDeviceStreams() const
|
||||
{
|
||||
return m_deviceAPI->getNbSourceStreams();
|
||||
}
|
||||
|
||||
void EndOfTrainDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst)
|
||||
{
|
||||
(void) firstOfBurst;
|
||||
m_basebandSink->feed(begin, end);
|
||||
}
|
||||
|
||||
void EndOfTrainDemod::start()
|
||||
{
|
||||
qDebug("EndOfTrainDemod::start");
|
||||
|
||||
m_basebandSink->reset();
|
||||
m_basebandSink->startWork();
|
||||
m_thread.start();
|
||||
|
||||
DSPSignalNotification *dspMsg = new DSPSignalNotification(m_basebandSampleRate, m_centerFrequency);
|
||||
m_basebandSink->getInputMessageQueue()->push(dspMsg);
|
||||
|
||||
EndOfTrainDemodBaseband::MsgConfigureEndOfTrainDemodBaseband *msg = EndOfTrainDemodBaseband::MsgConfigureEndOfTrainDemodBaseband::create(m_settings, QStringList(), true);
|
||||
m_basebandSink->getInputMessageQueue()->push(msg);
|
||||
}
|
||||
|
||||
void EndOfTrainDemod::stop()
|
||||
{
|
||||
qDebug("EndOfTrainDemod::stop");
|
||||
m_basebandSink->stopWork();
|
||||
m_thread.quit();
|
||||
m_thread.wait();
|
||||
}
|
||||
|
||||
bool EndOfTrainDemod::handleMessage(const Message& cmd)
|
||||
{
|
||||
if (MsgConfigureEndOfTrainDemod::match(cmd))
|
||||
{
|
||||
MsgConfigureEndOfTrainDemod& cfg = (MsgConfigureEndOfTrainDemod&) cmd;
|
||||
qDebug() << "EndOfTrainDemod::handleMessage: MsgConfigureEndOfTrainDemod";
|
||||
applySettings(cfg.getSettings(), cfg.getSettingsKeys(), cfg.getForce());
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
m_basebandSampleRate = notif.getSampleRate();
|
||||
m_centerFrequency = notif.getCenterFrequency();
|
||||
// Forward to the sink
|
||||
DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy
|
||||
qDebug() << "EndOfTrainDemod::handleMessage: DSPSignalNotification";
|
||||
m_basebandSink->getInputMessageQueue()->push(rep);
|
||||
// Forward to GUI if any
|
||||
if (m_guiMessageQueue) {
|
||||
m_guiMessageQueue->push(new DSPSignalNotification(notif));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MainCore::MsgPacket::match(cmd))
|
||||
{
|
||||
// Forward to GUI
|
||||
MainCore::MsgPacket& report = (MainCore::MsgPacket&)cmd;
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
MainCore::MsgPacket *msg = new MainCore::MsgPacket(report);
|
||||
getMessageQueueToGUI()->push(msg);
|
||||
}
|
||||
|
||||
// Forward via UDP
|
||||
if (m_settings.m_udpEnabled)
|
||||
{
|
||||
qDebug() << "Forwarding to " << m_settings.m_udpAddress << ":" << m_settings.m_udpPort;
|
||||
m_udpSocket.writeDatagram(report.getPacket().data(), report.getPacket().size(),
|
||||
QHostAddress(m_settings.m_udpAddress), m_settings.m_udpPort);
|
||||
}
|
||||
|
||||
// Write to log file
|
||||
if (m_logFile.isOpen())
|
||||
{
|
||||
EndOfTrainPacket packet;
|
||||
|
||||
if (packet.decode(report.getPacket()))
|
||||
{
|
||||
m_logStream << report.getDateTime().date().toString() << ","
|
||||
<< report.getDateTime().time().toString() << ","
|
||||
<< report.getPacket().toHex() << ","
|
||||
<< packet.m_chainingBits << ","
|
||||
<< packet.m_batteryCondition << ","
|
||||
<< packet.m_type << ","
|
||||
<< packet.m_address << ","
|
||||
<< packet.m_pressure << ","
|
||||
<< packet.m_batteryCharge << ","
|
||||
<< packet.m_discretionary << ","
|
||||
<< packet.m_valveCircuitStatus << ","
|
||||
<< packet.m_confirmation << ","
|
||||
<< packet.m_turbine << ","
|
||||
<< packet.m_markerLightBatteryCondition << ","
|
||||
<< packet.m_markerLightStatus << ","
|
||||
<< packet.m_crcValid << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_logStream << report.getDateTime().date().toString() << ","
|
||||
<< report.getDateTime().time().toString() << ","
|
||||
<< report.getPacket().toHex() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MainCore::MsgChannelDemodQuery::match(cmd))
|
||||
{
|
||||
qDebug() << "EndOfTrainDemod::handleMessage: MsgChannelDemodQuery";
|
||||
sendSampleRateToDemodAnalyzer();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ScopeVis *EndOfTrainDemod::getScopeSink()
|
||||
{
|
||||
return m_basebandSink->getScopeSink();
|
||||
}
|
||||
|
||||
void EndOfTrainDemod::setCenterFrequency(qint64 frequency)
|
||||
{
|
||||
EndOfTrainDemodSettings settings = m_settings;
|
||||
settings.m_inputFrequencyOffset = frequency;
|
||||
applySettings(settings, {"inputFrequencyOffset"}, false);
|
||||
|
||||
if (m_guiMessageQueue) // forward to GUI if any
|
||||
{
|
||||
MsgConfigureEndOfTrainDemod *msgToGUI = MsgConfigureEndOfTrainDemod::create(settings, {"inputFrequencyOffset"}, false);
|
||||
m_guiMessageQueue->push(msgToGUI);
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemod::applySettings(const EndOfTrainDemodSettings& settings, const QStringList& settingsKeys, bool force)
|
||||
{
|
||||
qDebug() << "EndOfTrainDemod::applySettings:"
|
||||
<< settings.getDebugString(settingsKeys, force)
|
||||
<< " force: " << force;
|
||||
|
||||
if (settingsKeys.contains("streamIndex"))
|
||||
{
|
||||
if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only
|
||||
{
|
||||
m_deviceAPI->removeChannelSinkAPI(this);
|
||||
m_deviceAPI->removeChannelSink(this, m_settings.m_streamIndex);
|
||||
m_deviceAPI->addChannelSink(this, settings.m_streamIndex);
|
||||
m_deviceAPI->addChannelSinkAPI(this);
|
||||
m_settings.m_streamIndex = settings.m_streamIndex; // make sure ChannelAPI::getStreamIndex() is consistent
|
||||
emit streamIndexChanged(settings.m_streamIndex);
|
||||
}
|
||||
}
|
||||
|
||||
EndOfTrainDemodBaseband::MsgConfigureEndOfTrainDemodBaseband *msg = EndOfTrainDemodBaseband::MsgConfigureEndOfTrainDemodBaseband::create(settings, settingsKeys, force);
|
||||
m_basebandSink->getInputMessageQueue()->push(msg);
|
||||
|
||||
if (settings.m_useReverseAPI)
|
||||
{
|
||||
bool fullUpdate = (settingsKeys.contains("useReverseAPI") && settings.m_useReverseAPI) ||
|
||||
settingsKeys.contains("reverseAPIAddress") ||
|
||||
settingsKeys.contains("reverseAPIPort") ||
|
||||
settingsKeys.contains("reverseAPIDeviceIndex") ||
|
||||
settingsKeys.contains("reverseAPIChannelIndex");
|
||||
webapiReverseSendSettings(settingsKeys, settings, fullUpdate || force);
|
||||
}
|
||||
|
||||
if (settingsKeys.contains("logEnabled")
|
||||
|| settingsKeys.contains("logFilename")
|
||||
|| force)
|
||||
{
|
||||
if (m_logFile.isOpen())
|
||||
{
|
||||
m_logStream.flush();
|
||||
m_logFile.close();
|
||||
}
|
||||
if (settings.m_logEnabled && !settings.m_logFilename.isEmpty())
|
||||
{
|
||||
m_logFile.setFileName(settings.m_logFilename);
|
||||
if (m_logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text))
|
||||
{
|
||||
qDebug() << "EndOfTrainDemod::applySettings - Logging to: " << settings.m_logFilename;
|
||||
bool newFile = m_logFile.size() == 0;
|
||||
m_logStream.setDevice(&m_logFile);
|
||||
if (newFile)
|
||||
{
|
||||
// Write header
|
||||
m_logStream << "Date,Time,Data,Chaining Bits,Battery Condition,Message Type,Address,Pressure,Battery Charge,Discretionary,Valve Circuit Status,Confidence Indicator,Turbine,Motion,Marker Battery Light Condition,Marker Light Status, Arm Status,CRC Valid\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "EndOfTrainDemod::applySettings - Unable to open log file: " << settings.m_logFilename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (force) {
|
||||
m_settings = settings;
|
||||
} else {
|
||||
m_settings.applySettings(settingsKeys, settings);
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemod::sendSampleRateToDemodAnalyzer()
|
||||
{
|
||||
QList<ObjectPipe*> pipes;
|
||||
MainCore::instance()->getMessagePipes().getMessagePipes(this, "reportdemod", pipes);
|
||||
|
||||
if (pipes.size() > 0)
|
||||
{
|
||||
for (const auto& pipe : pipes)
|
||||
{
|
||||
MessageQueue *messageQueue = qobject_cast<MessageQueue*>(pipe->m_element);
|
||||
MainCore::MsgChannelDemodReport *msg = MainCore::MsgChannelDemodReport::create(
|
||||
this,
|
||||
EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE
|
||||
);
|
||||
messageQueue->push(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray EndOfTrainDemod::serialize() const
|
||||
{
|
||||
return m_settings.serialize();
|
||||
}
|
||||
|
||||
bool EndOfTrainDemod::deserialize(const QByteArray& data)
|
||||
{
|
||||
if (m_settings.deserialize(data))
|
||||
{
|
||||
MsgConfigureEndOfTrainDemod *msg = MsgConfigureEndOfTrainDemod::create(m_settings, QStringList(), true);
|
||||
m_inputMessageQueue.push(msg);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings.resetToDefaults();
|
||||
MsgConfigureEndOfTrainDemod *msg = MsgConfigureEndOfTrainDemod::create(m_settings, QStringList(), true);
|
||||
m_inputMessageQueue.push(msg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int EndOfTrainDemod::webapiSettingsGet(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) errorMessage;
|
||||
response.setEndOfTrainDemodSettings(new SWGSDRangel::SWGEndOfTrainDemodSettings());
|
||||
response.getEndOfTrainDemodSettings()->init();
|
||||
webapiFormatChannelSettings(response, m_settings);
|
||||
return 200;
|
||||
}
|
||||
|
||||
int EndOfTrainDemod::webapiWorkspaceGet(
|
||||
SWGSDRangel::SWGWorkspaceInfo& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) errorMessage;
|
||||
response.setIndex(m_settings.m_workspaceIndex);
|
||||
return 200;
|
||||
}
|
||||
|
||||
int EndOfTrainDemod::webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) errorMessage;
|
||||
EndOfTrainDemodSettings settings = m_settings;
|
||||
webapiUpdateChannelSettings(settings, channelSettingsKeys, response);
|
||||
|
||||
MsgConfigureEndOfTrainDemod *msg = MsgConfigureEndOfTrainDemod::create(settings, channelSettingsKeys, force);
|
||||
m_inputMessageQueue.push(msg);
|
||||
|
||||
qDebug("EndOfTrainDemod::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue);
|
||||
if (m_guiMessageQueue) // forward to GUI if any
|
||||
{
|
||||
MsgConfigureEndOfTrainDemod *msgToGUI = MsgConfigureEndOfTrainDemod::create(settings, channelSettingsKeys, force);
|
||||
m_guiMessageQueue->push(msgToGUI);
|
||||
}
|
||||
|
||||
webapiFormatChannelSettings(response, settings);
|
||||
|
||||
return 200;
|
||||
}
|
||||
|
||||
int EndOfTrainDemod::webapiReportGet(
|
||||
SWGSDRangel::SWGChannelReport& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) errorMessage;
|
||||
response.setEndOfTrainDemodReport(new SWGSDRangel::SWGEndOfTrainDemodReport());
|
||||
response.getEndOfTrainDemodReport()->init();
|
||||
webapiFormatChannelReport(response);
|
||||
return 200;
|
||||
}
|
||||
|
||||
void EndOfTrainDemod::webapiUpdateChannelSettings(
|
||||
EndOfTrainDemodSettings& settings,
|
||||
const QStringList& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings& response)
|
||||
{
|
||||
if (channelSettingsKeys.contains("inputFrequencyOffset")) {
|
||||
settings.m_inputFrequencyOffset = response.getEndOfTrainDemodSettings()->getInputFrequencyOffset();
|
||||
}
|
||||
if (channelSettingsKeys.contains("fmDeviation")) {
|
||||
settings.m_fmDeviation = response.getEndOfTrainDemodSettings()->getFmDeviation();
|
||||
}
|
||||
if (channelSettingsKeys.contains("rfBandwidth")) {
|
||||
settings.m_rfBandwidth = response.getEndOfTrainDemodSettings()->getRfBandwidth();
|
||||
}
|
||||
if (channelSettingsKeys.contains("udpEnabled")) {
|
||||
settings.m_udpEnabled = response.getEndOfTrainDemodSettings()->getUdpEnabled();
|
||||
}
|
||||
if (channelSettingsKeys.contains("udpAddress")) {
|
||||
settings.m_udpAddress = *response.getEndOfTrainDemodSettings()->getUdpAddress();
|
||||
}
|
||||
if (channelSettingsKeys.contains("udpPort")) {
|
||||
settings.m_udpPort = response.getEndOfTrainDemodSettings()->getUdpPort();
|
||||
}
|
||||
if (channelSettingsKeys.contains("logFilename")) {
|
||||
settings.m_logFilename = *response.getEndOfTrainDemodSettings()->getLogFilename();
|
||||
}
|
||||
if (channelSettingsKeys.contains("logEnabled")) {
|
||||
settings.m_logEnabled = response.getEndOfTrainDemodSettings()->getLogEnabled();
|
||||
}
|
||||
if (channelSettingsKeys.contains("useFileTime")) {
|
||||
settings.m_useFileTime = response.getEndOfTrainDemodSettings()->getUseFileTime();
|
||||
}
|
||||
if (channelSettingsKeys.contains("rgbColor")) {
|
||||
settings.m_rgbColor = response.getEndOfTrainDemodSettings()->getRgbColor();
|
||||
}
|
||||
if (channelSettingsKeys.contains("title")) {
|
||||
settings.m_title = *response.getEndOfTrainDemodSettings()->getTitle();
|
||||
}
|
||||
if (channelSettingsKeys.contains("streamIndex")) {
|
||||
settings.m_streamIndex = response.getEndOfTrainDemodSettings()->getStreamIndex();
|
||||
}
|
||||
if (channelSettingsKeys.contains("useReverseAPI")) {
|
||||
settings.m_useReverseAPI = response.getEndOfTrainDemodSettings()->getUseReverseApi() != 0;
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIAddress")) {
|
||||
settings.m_reverseAPIAddress = *response.getEndOfTrainDemodSettings()->getReverseApiAddress();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIPort")) {
|
||||
settings.m_reverseAPIPort = response.getEndOfTrainDemodSettings()->getReverseApiPort();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
|
||||
settings.m_reverseAPIDeviceIndex = response.getEndOfTrainDemodSettings()->getReverseApiDeviceIndex();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
|
||||
settings.m_reverseAPIChannelIndex = response.getEndOfTrainDemodSettings()->getReverseApiChannelIndex();
|
||||
}
|
||||
if (settings.m_channelMarker && channelSettingsKeys.contains("channelMarker")) {
|
||||
settings.m_channelMarker->updateFrom(channelSettingsKeys, response.getEndOfTrainDemodSettings()->getChannelMarker());
|
||||
}
|
||||
if (settings.m_rollupState && channelSettingsKeys.contains("rollupState")) {
|
||||
settings.m_rollupState->updateFrom(channelSettingsKeys, response.getEndOfTrainDemodSettings()->getRollupState());
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const EndOfTrainDemodSettings& settings)
|
||||
{
|
||||
response.getEndOfTrainDemodSettings()->setFmDeviation(settings.m_fmDeviation);
|
||||
response.getEndOfTrainDemodSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
|
||||
response.getEndOfTrainDemodSettings()->setRfBandwidth(settings.m_rfBandwidth);
|
||||
response.getEndOfTrainDemodSettings()->setUdpEnabled(settings.m_udpEnabled);
|
||||
response.getEndOfTrainDemodSettings()->setUdpAddress(new QString(settings.m_udpAddress));
|
||||
response.getEndOfTrainDemodSettings()->setUdpPort(settings.m_udpPort);
|
||||
response.getEndOfTrainDemodSettings()->setLogFilename(new QString(settings.m_logFilename));
|
||||
response.getEndOfTrainDemodSettings()->setLogEnabled(settings.m_logEnabled);
|
||||
response.getEndOfTrainDemodSettings()->setUseFileTime(settings.m_useFileTime);
|
||||
|
||||
response.getEndOfTrainDemodSettings()->setRgbColor(settings.m_rgbColor);
|
||||
if (response.getEndOfTrainDemodSettings()->getTitle()) {
|
||||
*response.getEndOfTrainDemodSettings()->getTitle() = settings.m_title;
|
||||
} else {
|
||||
response.getEndOfTrainDemodSettings()->setTitle(new QString(settings.m_title));
|
||||
}
|
||||
|
||||
response.getEndOfTrainDemodSettings()->setStreamIndex(settings.m_streamIndex);
|
||||
response.getEndOfTrainDemodSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
|
||||
|
||||
if (response.getEndOfTrainDemodSettings()->getReverseApiAddress()) {
|
||||
*response.getEndOfTrainDemodSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress;
|
||||
} else {
|
||||
response.getEndOfTrainDemodSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
|
||||
}
|
||||
|
||||
response.getEndOfTrainDemodSettings()->setReverseApiPort(settings.m_reverseAPIPort);
|
||||
response.getEndOfTrainDemodSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex);
|
||||
response.getEndOfTrainDemodSettings()->setReverseApiChannelIndex(settings.m_reverseAPIChannelIndex);
|
||||
|
||||
if (settings.m_channelMarker)
|
||||
{
|
||||
if (response.getEndOfTrainDemodSettings()->getChannelMarker())
|
||||
{
|
||||
settings.m_channelMarker->formatTo(response.getEndOfTrainDemodSettings()->getChannelMarker());
|
||||
}
|
||||
else
|
||||
{
|
||||
SWGSDRangel::SWGChannelMarker *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
settings.m_channelMarker->formatTo(swgChannelMarker);
|
||||
response.getEndOfTrainDemodSettings()->setChannelMarker(swgChannelMarker);
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.m_rollupState)
|
||||
{
|
||||
if (response.getEndOfTrainDemodSettings()->getRollupState())
|
||||
{
|
||||
settings.m_rollupState->formatTo(response.getEndOfTrainDemodSettings()->getRollupState());
|
||||
}
|
||||
else
|
||||
{
|
||||
SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
settings.m_rollupState->formatTo(swgRollupState);
|
||||
response.getEndOfTrainDemodSettings()->setRollupState(swgRollupState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response)
|
||||
{
|
||||
double magsqAvg, magsqPeak;
|
||||
int nbMagsqSamples;
|
||||
getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples);
|
||||
|
||||
response.getEndOfTrainDemodReport()->setChannelPowerDb(CalcDb::dbPower(magsqAvg));
|
||||
response.getEndOfTrainDemodReport()->setChannelSampleRate(m_basebandSink->getChannelSampleRate());
|
||||
}
|
||||
|
||||
void EndOfTrainDemod::webapiReverseSendSettings(const QStringList& channelSettingsKeys, const EndOfTrainDemodSettings& settings, bool force)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
|
||||
|
||||
QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
|
||||
.arg(settings.m_reverseAPIAddress)
|
||||
.arg(settings.m_reverseAPIPort)
|
||||
.arg(settings.m_reverseAPIDeviceIndex)
|
||||
.arg(settings.m_reverseAPIChannelIndex);
|
||||
m_networkRequest.setUrl(QUrl(channelSettingsURL));
|
||||
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QBuffer *buffer = new QBuffer();
|
||||
buffer->open((QBuffer::ReadWrite));
|
||||
buffer->write(swgChannelSettings->asJson().toUtf8());
|
||||
buffer->seek(0);
|
||||
|
||||
// Always use PATCH to avoid passing reverse API settings
|
||||
QNetworkReply *reply = m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
|
||||
buffer->setParent(reply);
|
||||
|
||||
delete swgChannelSettings;
|
||||
}
|
||||
|
||||
void EndOfTrainDemod::webapiFormatChannelSettings(
|
||||
const QStringList& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
||||
const EndOfTrainDemodSettings& settings,
|
||||
bool force
|
||||
)
|
||||
{
|
||||
swgChannelSettings->setDirection(0); // Single sink (Rx)
|
||||
swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet());
|
||||
swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex());
|
||||
swgChannelSettings->setChannelType(new QString("EndOfTrainDemod"));
|
||||
swgChannelSettings->setEndOfTrainDemodSettings(new SWGSDRangel::SWGEndOfTrainDemodSettings());
|
||||
SWGSDRangel::SWGEndOfTrainDemodSettings *swgEndOfTrainDemodSettings = swgChannelSettings->getEndOfTrainDemodSettings();
|
||||
|
||||
// transfer data that has been modified. When force is on transfer all data except reverse API data
|
||||
|
||||
if (channelSettingsKeys.contains("fmDeviation") || force) {
|
||||
swgEndOfTrainDemodSettings->setFmDeviation(settings.m_fmDeviation);
|
||||
}
|
||||
if (channelSettingsKeys.contains("inputFrequencyOffset") || force) {
|
||||
swgEndOfTrainDemodSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
|
||||
}
|
||||
if (channelSettingsKeys.contains("rfBandwidth") || force) {
|
||||
swgEndOfTrainDemodSettings->setRfBandwidth(settings.m_rfBandwidth);
|
||||
}
|
||||
if (channelSettingsKeys.contains("udpEnabled") || force) {
|
||||
swgEndOfTrainDemodSettings->setUdpEnabled(settings.m_udpEnabled);
|
||||
}
|
||||
if (channelSettingsKeys.contains("udpAddress") || force) {
|
||||
swgEndOfTrainDemodSettings->setUdpAddress(new QString(settings.m_udpAddress));
|
||||
}
|
||||
if (channelSettingsKeys.contains("udpPort") || force) {
|
||||
swgEndOfTrainDemodSettings->setUdpPort(settings.m_udpPort);
|
||||
}
|
||||
if (channelSettingsKeys.contains("logFilename") || force) {
|
||||
swgEndOfTrainDemodSettings->setLogFilename(new QString(settings.m_logFilename));
|
||||
}
|
||||
if (channelSettingsKeys.contains("logEnabled") || force) {
|
||||
swgEndOfTrainDemodSettings->setLogEnabled(settings.m_logEnabled);
|
||||
}
|
||||
if (channelSettingsKeys.contains("useFileTime") || force) {
|
||||
swgEndOfTrainDemodSettings->setUseFileTime(settings.m_useFileTime);
|
||||
}
|
||||
if (channelSettingsKeys.contains("rgbColor") || force) {
|
||||
swgEndOfTrainDemodSettings->setRgbColor(settings.m_rgbColor);
|
||||
}
|
||||
if (channelSettingsKeys.contains("title") || force) {
|
||||
swgEndOfTrainDemodSettings->setTitle(new QString(settings.m_title));
|
||||
}
|
||||
if (channelSettingsKeys.contains("streamIndex") || force) {
|
||||
swgEndOfTrainDemodSettings->setStreamIndex(settings.m_streamIndex);
|
||||
}
|
||||
|
||||
if (settings.m_channelMarker && (channelSettingsKeys.contains("channelMarker") || force))
|
||||
{
|
||||
SWGSDRangel::SWGChannelMarker *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
settings.m_channelMarker->formatTo(swgChannelMarker);
|
||||
swgEndOfTrainDemodSettings->setChannelMarker(swgChannelMarker);
|
||||
}
|
||||
|
||||
if (settings.m_rollupState && (channelSettingsKeys.contains("rollupState") || force))
|
||||
{
|
||||
SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
settings.m_rollupState->formatTo(swgRollupState);
|
||||
swgEndOfTrainDemodSettings->setRollupState(swgRollupState);
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemod::networkManagerFinished(QNetworkReply *reply)
|
||||
{
|
||||
QNetworkReply::NetworkError replyError = reply->error();
|
||||
|
||||
if (replyError)
|
||||
{
|
||||
qWarning() << "EndOfTrainDemod::networkManagerFinished:"
|
||||
<< " error(" << (int) replyError
|
||||
<< "): " << replyError
|
||||
<< ": " << reply->errorString();
|
||||
}
|
||||
else
|
||||
{
|
||||
QString answer = reply->readAll();
|
||||
answer.chop(1); // remove last \n
|
||||
qDebug("EndOfTrainDemod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void EndOfTrainDemod::handleIndexInDeviceSetChanged(int index)
|
||||
{
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString fifoLabel = QString("%1 [%2:%3]")
|
||||
.arg(m_channelId)
|
||||
.arg(m_deviceAPI->getDeviceSetIndex())
|
||||
.arg(index);
|
||||
m_basebandSink->setFifoLabel(fifoLabel);
|
||||
}
|
182
plugins/channelrx/demodendoftrain/endoftraindemod.h
Normal file
182
plugins/channelrx/demodendoftrain/endoftraindemod.h
Normal file
@ -0,0 +1,182 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
||||
// written by Christian Daniel //
|
||||
// Copyright (C) 2014-2015 John Greb <hexameron@spam.no> //
|
||||
// Copyright (C) 2015-2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// Copyright (C) 2020-2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// Copyright (C) 2020 Kacper Michajłow <kasper93@gmail.com> //
|
||||
// //
|
||||
// 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_ENDOFTRAINDEMOD_H
|
||||
#define INCLUDE_ENDOFTRAINDEMOD_H
|
||||
|
||||
#include <QNetworkRequest>
|
||||
#include <QUdpSocket>
|
||||
#include <QThread>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
#include "dsp/basebandsamplesink.h"
|
||||
#include "channel/channelapi.h"
|
||||
#include "util/message.h"
|
||||
|
||||
#include "endoftraindemodbaseband.h"
|
||||
#include "endoftraindemodsettings.h"
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
class QThread;
|
||||
class DeviceAPI;
|
||||
class ScopeVis;
|
||||
|
||||
class EndOfTrainDemod : public BasebandSampleSink, public ChannelAPI {
|
||||
public:
|
||||
class MsgConfigureEndOfTrainDemod : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
const EndOfTrainDemodSettings& getSettings() const { return m_settings; }
|
||||
const QStringList& getSettingsKeys() const { return m_settingsKeys; }
|
||||
bool getForce() const { return m_force; }
|
||||
|
||||
static MsgConfigureEndOfTrainDemod* create(const EndOfTrainDemodSettings& settings, const QStringList& settingsKeys, bool force)
|
||||
{
|
||||
return new MsgConfigureEndOfTrainDemod(settings, settingsKeys, force);
|
||||
}
|
||||
|
||||
private:
|
||||
EndOfTrainDemodSettings m_settings;
|
||||
QStringList m_settingsKeys;
|
||||
bool m_force;
|
||||
|
||||
MsgConfigureEndOfTrainDemod(const EndOfTrainDemodSettings& settings, const QStringList& settingsKeys, bool force) :
|
||||
Message(),
|
||||
m_settings(settings),
|
||||
m_settingsKeys(settingsKeys),
|
||||
m_force(force)
|
||||
{ }
|
||||
};
|
||||
|
||||
EndOfTrainDemod(DeviceAPI *deviceAPI);
|
||||
virtual ~EndOfTrainDemod();
|
||||
virtual void destroy() { delete this; }
|
||||
virtual void setDeviceAPI(DeviceAPI *deviceAPI);
|
||||
virtual DeviceAPI *getDeviceAPI() { return m_deviceAPI; }
|
||||
|
||||
using BasebandSampleSink::feed;
|
||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual void pushMessage(Message *msg) { m_inputMessageQueue.push(msg); }
|
||||
virtual QString getSinkName() { return objectName(); }
|
||||
|
||||
virtual void getIdentifier(QString& id) { id = objectName(); }
|
||||
virtual QString getIdentifier() const { return objectName(); }
|
||||
virtual const QString& getURI() const { return getName(); }
|
||||
virtual void getTitle(QString& title) { title = m_settings.m_title; }
|
||||
virtual qint64 getCenterFrequency() const { return m_settings.m_inputFrequencyOffset; }
|
||||
virtual void setCenterFrequency(qint64 frequency);
|
||||
|
||||
virtual QByteArray serialize() const;
|
||||
virtual bool deserialize(const QByteArray& data);
|
||||
|
||||
virtual int getNbSinkStreams() const { return 1; }
|
||||
virtual int getNbSourceStreams() const { return 0; }
|
||||
virtual int getStreamIndex() const { return m_settings.m_streamIndex; }
|
||||
|
||||
virtual qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const
|
||||
{
|
||||
(void) streamIndex;
|
||||
(void) sinkElseSource;
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int webapiSettingsGet(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage);
|
||||
|
||||
virtual int webapiWorkspaceGet(
|
||||
SWGSDRangel::SWGWorkspaceInfo& response,
|
||||
QString& errorMessage);
|
||||
|
||||
virtual int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage);
|
||||
|
||||
virtual int webapiReportGet(
|
||||
SWGSDRangel::SWGChannelReport& response,
|
||||
QString& errorMessage);
|
||||
|
||||
static void webapiFormatChannelSettings(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
const EndOfTrainDemodSettings& settings);
|
||||
|
||||
static void webapiUpdateChannelSettings(
|
||||
EndOfTrainDemodSettings& settings,
|
||||
const QStringList& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings& response);
|
||||
|
||||
ScopeVis *getScopeSink();
|
||||
double getMagSq() const { return m_basebandSink->getMagSq(); }
|
||||
|
||||
void getMagSqLevels(double& avg, double& peak, int& nbSamples) {
|
||||
m_basebandSink->getMagSqLevels(avg, peak, nbSamples);
|
||||
}
|
||||
/* void setMessageQueueToGUI(MessageQueue* queue) override {
|
||||
ChannelAPI::setMessageQueueToGUI(queue);
|
||||
m_basebandSink->setMessageQueueToGUI(queue);
|
||||
}*/
|
||||
|
||||
uint32_t getNumberOfDeviceStreams() const;
|
||||
|
||||
static const char * const m_channelIdURI;
|
||||
static const char * const m_channelId;
|
||||
|
||||
private:
|
||||
DeviceAPI *m_deviceAPI;
|
||||
QThread m_thread;
|
||||
EndOfTrainDemodBaseband* m_basebandSink;
|
||||
EndOfTrainDemodSettings m_settings;
|
||||
int m_basebandSampleRate; //!< stored from device message used when starting baseband sink
|
||||
qint64 m_centerFrequency;
|
||||
QUdpSocket m_udpSocket;
|
||||
QFile m_logFile;
|
||||
QTextStream m_logStream;
|
||||
|
||||
QNetworkAccessManager *m_networkManager;
|
||||
QNetworkRequest m_networkRequest;
|
||||
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
void applySettings(const EndOfTrainDemodSettings& settings, const QStringList& settingsKeys, bool force = false);
|
||||
void sendSampleRateToDemodAnalyzer();
|
||||
void webapiReverseSendSettings(const QStringList& channelSettingsKeys, const EndOfTrainDemodSettings& settings, bool force);
|
||||
void webapiFormatChannelSettings(
|
||||
const QStringList& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
||||
const EndOfTrainDemodSettings& settings,
|
||||
bool force
|
||||
);
|
||||
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
|
||||
|
||||
private slots:
|
||||
void networkManagerFinished(QNetworkReply *reply);
|
||||
void handleIndexInDeviceSetChanged(int index);
|
||||
|
||||
};
|
||||
|
||||
#endif // INCLUDE_ENDOFTRAINDEMOD_H
|
186
plugins/channelrx/demodendoftrain/endoftraindemodbaseband.cpp
Normal file
186
plugins/channelrx/demodendoftrain/endoftraindemodbaseband.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2019-2021 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// Copyright (C) 2020-2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// Copyright (C) 2022 Jiří Pinkava <jiri.pinkava@rossum.ai> //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
#include "dsp/downchannelizer.h"
|
||||
|
||||
#include "endoftraindemodbaseband.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(EndOfTrainDemodBaseband::MsgConfigureEndOfTrainDemodBaseband, Message)
|
||||
|
||||
EndOfTrainDemodBaseband::EndOfTrainDemodBaseband(EndOfTrainDemod *endoftrainDemod) :
|
||||
m_sink(endoftrainDemod),
|
||||
m_running(false)
|
||||
{
|
||||
qDebug("EndOfTrainDemodBaseband::EndOfTrainDemodBaseband");
|
||||
|
||||
m_scopeSink.setNbStreams(EndOfTrainDemodSettings::m_scopeStreams);
|
||||
m_sink.setScopeSink(&m_scopeSink);
|
||||
m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(48000));
|
||||
m_channelizer = new DownChannelizer(&m_sink);
|
||||
}
|
||||
|
||||
EndOfTrainDemodBaseband::~EndOfTrainDemodBaseband()
|
||||
{
|
||||
m_inputMessageQueue.clear();
|
||||
|
||||
delete m_channelizer;
|
||||
}
|
||||
|
||||
void EndOfTrainDemodBaseband::reset()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
m_inputMessageQueue.clear();
|
||||
m_sampleFifo.reset();
|
||||
}
|
||||
|
||||
void EndOfTrainDemodBaseband::startWork()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
QObject::connect(
|
||||
&m_sampleFifo,
|
||||
&SampleSinkFifo::dataReady,
|
||||
this,
|
||||
&EndOfTrainDemodBaseband::handleData,
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
m_running = true;
|
||||
}
|
||||
|
||||
void EndOfTrainDemodBaseband::stopWork()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
QObject::disconnect(
|
||||
&m_sampleFifo,
|
||||
&SampleSinkFifo::dataReady,
|
||||
this,
|
||||
&EndOfTrainDemodBaseband::handleData
|
||||
);
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
void EndOfTrainDemodBaseband::setChannel(ChannelAPI *channel)
|
||||
{
|
||||
m_sink.setChannel(channel);
|
||||
}
|
||||
|
||||
void EndOfTrainDemodBaseband::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
|
||||
{
|
||||
m_sampleFifo.write(begin, end);
|
||||
}
|
||||
|
||||
void EndOfTrainDemodBaseband::handleData()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
while ((m_sampleFifo.fill() > 0) && (m_inputMessageQueue.size() == 0))
|
||||
{
|
||||
SampleVector::iterator part1begin;
|
||||
SampleVector::iterator part1end;
|
||||
SampleVector::iterator part2begin;
|
||||
SampleVector::iterator part2end;
|
||||
|
||||
std::size_t count = m_sampleFifo.readBegin(m_sampleFifo.fill(), &part1begin, &part1end, &part2begin, &part2end);
|
||||
|
||||
// first part of FIFO data
|
||||
if (part1begin != part1end) {
|
||||
m_channelizer->feed(part1begin, part1end);
|
||||
}
|
||||
|
||||
// second part of FIFO data (used when block wraps around)
|
||||
if(part2begin != part2end) {
|
||||
m_channelizer->feed(part2begin, part2end);
|
||||
}
|
||||
|
||||
m_sampleFifo.readCommit((unsigned int) count);
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemodBaseband::handleInputMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = m_inputMessageQueue.pop()) != nullptr)
|
||||
{
|
||||
if (handleMessage(*message)) {
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool EndOfTrainDemodBaseband::handleMessage(const Message& cmd)
|
||||
{
|
||||
if (MsgConfigureEndOfTrainDemodBaseband::match(cmd))
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
MsgConfigureEndOfTrainDemodBaseband& cfg = (MsgConfigureEndOfTrainDemodBaseband&) cmd;
|
||||
qDebug() << "EndOfTrainDemodBaseband::handleMessage: MsgConfigureEndOfTrainDemodBaseband";
|
||||
|
||||
applySettings(cfg.getSettings(), cfg.getSettingsKeys(), cfg.getForce());
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
qDebug() << "EndOfTrainDemodBaseband::handleMessage: DSPSignalNotification: basebandSampleRate: " << notif.getSampleRate();
|
||||
setBasebandSampleRate(notif.getSampleRate());
|
||||
m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(notif.getSampleRate()));
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemodBaseband::applySettings(const EndOfTrainDemodSettings& settings, const QStringList& settingsKeys, bool force)
|
||||
{
|
||||
if (settingsKeys.contains("inputFrequencyOffset") || force)
|
||||
{
|
||||
m_channelizer->setChannelization(EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE, settings.m_inputFrequencyOffset);
|
||||
m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
}
|
||||
|
||||
m_sink.applySettings(settings, settingsKeys, force);
|
||||
|
||||
if (force) {
|
||||
m_settings = settings;
|
||||
} else {
|
||||
m_settings.applySettings(settingsKeys, settings);
|
||||
}
|
||||
}
|
||||
|
||||
int EndOfTrainDemodBaseband::getChannelSampleRate() const
|
||||
{
|
||||
return m_channelizer->getChannelSampleRate();
|
||||
}
|
||||
|
||||
void EndOfTrainDemodBaseband::setBasebandSampleRate(int sampleRate)
|
||||
{
|
||||
m_channelizer->setBasebandSampleRate(sampleRate);
|
||||
m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
}
|
105
plugins/channelrx/demodendoftrain/endoftraindemodbaseband.h
Normal file
105
plugins/channelrx/demodendoftrain/endoftraindemodbaseband.h
Normal file
@ -0,0 +1,105 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2019-2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// Copyright (C) 2020-2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// Copyright (C) 2022 Jiří Pinkava <jiri.pinkava@rossum.ai> //
|
||||
// //
|
||||
// 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_ENDOFTRAINDEMODBASEBAND_H
|
||||
#define INCLUDE_ENDOFTRAINDEMODBASEBAND_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QRecursiveMutex>
|
||||
|
||||
#include "dsp/samplesinkfifo.h"
|
||||
#include "dsp/scopevis.h"
|
||||
#include "util/message.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
#include "endoftraindemodsink.h"
|
||||
|
||||
class DownChannelizer;
|
||||
class ChannelAPI;
|
||||
class EndOfTrainDemod;
|
||||
class ScopeVis;
|
||||
|
||||
class EndOfTrainDemodBaseband : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
class MsgConfigureEndOfTrainDemodBaseband : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
const EndOfTrainDemodSettings& getSettings() const { return m_settings; }
|
||||
const QStringList& getSettingsKeys() const { return m_settingsKeys; }
|
||||
bool getForce() const { return m_force; }
|
||||
|
||||
static MsgConfigureEndOfTrainDemodBaseband* create(const EndOfTrainDemodSettings& settings, const QStringList& settingsKeys, bool force)
|
||||
{
|
||||
return new MsgConfigureEndOfTrainDemodBaseband(settings, settingsKeys, force);
|
||||
}
|
||||
|
||||
private:
|
||||
EndOfTrainDemodSettings m_settings;
|
||||
QStringList m_settingsKeys;
|
||||
bool m_force;
|
||||
|
||||
MsgConfigureEndOfTrainDemodBaseband(const EndOfTrainDemodSettings& settings, const QStringList& settingsKeys, bool force) :
|
||||
Message(),
|
||||
m_settings(settings),
|
||||
m_settingsKeys(settingsKeys),
|
||||
m_force(force)
|
||||
{ }
|
||||
};
|
||||
|
||||
EndOfTrainDemodBaseband(EndOfTrainDemod *endoftrainDemod);
|
||||
~EndOfTrainDemodBaseband();
|
||||
void reset();
|
||||
void startWork();
|
||||
void stopWork();
|
||||
void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
||||
void getMagSqLevels(double& avg, double& peak, int& nbSamples) {
|
||||
m_sink.getMagSqLevels(avg, peak, nbSamples);
|
||||
}
|
||||
void setMessageQueueToChannel(MessageQueue *messageQueue) { m_sink.setMessageQueueToChannel(messageQueue); }
|
||||
void setBasebandSampleRate(int sampleRate);
|
||||
ScopeVis *getScopeSink() { return &m_scopeSink; }
|
||||
int getChannelSampleRate() const;
|
||||
void setChannel(ChannelAPI *channel);
|
||||
double getMagSq() const { return m_sink.getMagSq(); }
|
||||
bool isRunning() const { return m_running; }
|
||||
void setFifoLabel(const QString& label) { m_sampleFifo.setLabel(label); }
|
||||
|
||||
private:
|
||||
SampleSinkFifo m_sampleFifo;
|
||||
DownChannelizer *m_channelizer;
|
||||
EndOfTrainDemodSink m_sink;
|
||||
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
|
||||
EndOfTrainDemodSettings m_settings;
|
||||
ScopeVis m_scopeSink;
|
||||
bool m_running;
|
||||
QRecursiveMutex m_mutex;
|
||||
|
||||
bool handleMessage(const Message& cmd);
|
||||
void applySettings(const EndOfTrainDemodSettings& settings, const QStringList& settingsKeys, bool force = false);
|
||||
|
||||
private slots:
|
||||
void handleInputMessages();
|
||||
void handleData(); //!< Handle data when samples have to be processed
|
||||
};
|
||||
|
||||
#endif // INCLUDE_ENDOFTRAINDEMODBASEBAND_H
|
771
plugins/channelrx/demodendoftrain/endoftraindemodgui.cpp
Normal file
771
plugins/channelrx/demodendoftrain/endoftraindemodgui.cpp
Normal file
@ -0,0 +1,771 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2021-2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// Copyright (C) 2021-2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// //
|
||||
// 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 <QMainWindow>
|
||||
#include <QDebug>
|
||||
#include <QMessageBox>
|
||||
#include <QAction>
|
||||
#include <QRegExp>
|
||||
#include <QFileDialog>
|
||||
#include <QScrollBar>
|
||||
|
||||
#include "endoftraindemodgui.h"
|
||||
#include "endoftrainpacket.h"
|
||||
|
||||
#include "device/deviceuiset.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
#include "ui_endoftraindemodgui.h"
|
||||
#include "plugin/pluginapi.h"
|
||||
#include "util/simpleserializer.h"
|
||||
#include "util/csv.h"
|
||||
#include "util/db.h"
|
||||
#include "util/units.h"
|
||||
#include "gui/basicchannelsettingsdialog.h"
|
||||
#include "gui/devicestreamselectiondialog.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/glscopesettings.h"
|
||||
#include "gui/crightclickenabler.h"
|
||||
#include "gui/dialogpositioner.h"
|
||||
#include "channel/channelwebapiutils.h"
|
||||
#include "maincore.h"
|
||||
|
||||
#include "endoftraindemod.h"
|
||||
#include "endoftraindemodsink.h"
|
||||
|
||||
void EndOfTrainDemodGUI::resizeTable()
|
||||
{
|
||||
// Fill table with a row of dummy data that will size the columns nicely
|
||||
// Trailing spaces are for sort arrow
|
||||
int row = ui->packets->rowCount();
|
||||
ui->packets->setRowCount(row + 1);
|
||||
ui->packets->setItem(row, PACKETS_COL_DATE, new QTableWidgetItem("Frid Apr 15 2016-"));
|
||||
ui->packets->setItem(row, PACKETS_COL_TIME, new QTableWidgetItem("10:17:00"));
|
||||
ui->packets->setItem(row, PACKETS_COL_BATTERY_CONDITION, new QTableWidgetItem("Very low"));
|
||||
ui->packets->setItem(row, PACKETS_COL_TYPE, new QTableWidgetItem("7-"));
|
||||
ui->packets->setItem(row, PACKETS_COL_ADDRESS, new QTableWidgetItem("65535-"));
|
||||
ui->packets->setItem(row, PACKETS_COL_PRESSURE, new QTableWidgetItem("PID-"));
|
||||
ui->packets->setItem(row, PACKETS_COL_BATTERY_CHARGE, new QTableWidgetItem("100.0%"));
|
||||
ui->packets->setItem(row, PACKETS_COL_ARM_STATUS, new QTableWidgetItem("Normal"));
|
||||
ui->packets->setItem(row, PACKETS_COL_CRC, new QTableWidgetItem("123456-15-"));
|
||||
ui->packets->setItem(row, PACKETS_COL_DATA_HEX, new QTableWidgetItem("88888888888888888888"));
|
||||
ui->packets->resizeColumnsToContents();
|
||||
ui->packets->removeRow(row);
|
||||
}
|
||||
|
||||
// Columns in table reordered
|
||||
void EndOfTrainDemodGUI::endoftrains_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex)
|
||||
{
|
||||
(void) oldVisualIndex;
|
||||
|
||||
m_settings.m_columnIndexes[logicalIndex] = newVisualIndex;
|
||||
}
|
||||
|
||||
// Column in table resized (when hidden size is 0)
|
||||
void EndOfTrainDemodGUI::endoftrains_sectionResized(int logicalIndex, int oldSize, int newSize)
|
||||
{
|
||||
(void) oldSize;
|
||||
|
||||
m_settings.m_columnSizes[logicalIndex] = newSize;
|
||||
}
|
||||
|
||||
// Right click in table header - show column select menu
|
||||
void EndOfTrainDemodGUI::columnSelectMenu(QPoint pos)
|
||||
{
|
||||
menu->popup(ui->packets->horizontalHeader()->viewport()->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
// Hide/show column when menu selected
|
||||
void EndOfTrainDemodGUI::columnSelectMenuChecked(bool checked)
|
||||
{
|
||||
(void) checked;
|
||||
|
||||
QAction* action = qobject_cast<QAction*>(sender());
|
||||
if (action != nullptr)
|
||||
{
|
||||
int idx = action->data().toInt(nullptr);
|
||||
ui->packets->setColumnHidden(idx, !action->isChecked());
|
||||
}
|
||||
}
|
||||
|
||||
// Create column select menu item
|
||||
QAction *EndOfTrainDemodGUI::createCheckableItem(QString &text, int idx, bool checked)
|
||||
{
|
||||
QAction *action = new QAction(text, this);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(checked);
|
||||
action->setData(QVariant(idx));
|
||||
connect(action, SIGNAL(triggered()), this, SLOT(columnSelectMenuChecked()));
|
||||
return action;
|
||||
}
|
||||
|
||||
EndOfTrainDemodGUI* EndOfTrainDemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
|
||||
{
|
||||
EndOfTrainDemodGUI* gui = new EndOfTrainDemodGUI(pluginAPI, deviceUISet, rxChannel);
|
||||
return gui;
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::destroy()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::resetToDefaults()
|
||||
{
|
||||
m_settings.resetToDefaults();
|
||||
displaySettings();
|
||||
applyAllSettings();
|
||||
}
|
||||
|
||||
QByteArray EndOfTrainDemodGUI::serialize() const
|
||||
{
|
||||
return m_settings.serialize();
|
||||
}
|
||||
|
||||
bool EndOfTrainDemodGUI::deserialize(const QByteArray& data)
|
||||
{
|
||||
if(m_settings.deserialize(data))
|
||||
{
|
||||
displaySettings();
|
||||
applyAllSettings();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Add row to table
|
||||
void EndOfTrainDemodGUI::packetReceived(const QByteArray& packetData, const QDateTime& dateTime)
|
||||
{
|
||||
EndOfTrainPacket packet;
|
||||
|
||||
if (packet.decode(packetData))
|
||||
{
|
||||
// Is scroll bar at bottom
|
||||
QScrollBar *sb = ui->packets->verticalScrollBar();
|
||||
bool scrollToBottom = sb->value() == sb->maximum();
|
||||
|
||||
ui->packets->setSortingEnabled(false);
|
||||
int row = ui->packets->rowCount();
|
||||
ui->packets->setRowCount(row + 1);
|
||||
|
||||
QTableWidgetItem *dateItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *timeItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *chainingBitsItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *batteryConditionItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *typeItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *addressItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *pressureItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *batteryChargeItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *discretionaryItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *valveCircuitStatusItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *confIndItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *turbineItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *motionItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *markerBatteryLightConditionItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *markerLightStatusItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *armStatusItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *crcItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *dataHexItem = new QTableWidgetItem();
|
||||
ui->packets->setItem(row, PACKETS_COL_DATE, dateItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_TIME, timeItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_CHAINING_BITS, chainingBitsItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_BATTERY_CONDITION, batteryConditionItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_TYPE, typeItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_ADDRESS, addressItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_PRESSURE, pressureItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_BATTERY_CHARGE, batteryChargeItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_DISCRETIONARY, discretionaryItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_VALVE_CIRCUIT_STATUS, valveCircuitStatusItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_CONF_IND, confIndItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_TURBINE, turbineItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_MOTION, motionItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_MARKER_BATTERY, markerBatteryLightConditionItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_MARKER_LIGHT, markerLightStatusItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_ARM_STATUS, armStatusItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_CRC, crcItem);
|
||||
ui->packets->setItem(row, PACKETS_COL_DATA_HEX, dataHexItem);
|
||||
dateItem->setText(dateTime.date().toString());
|
||||
timeItem->setText(dateTime.time().toString());
|
||||
chainingBitsItem->setText(QString::number(packet.m_chainingBits));
|
||||
batteryConditionItem->setText(packet.getBatteryCondition());
|
||||
typeItem->setText(packet.getMessageType());
|
||||
addressItem->setText(QString::number(packet.m_address));
|
||||
pressureItem->setText(QString::number(packet.m_pressure));
|
||||
batteryChargeItem->setText(QString("%1%").arg(packet.getBatteryChargePercent(), 0, 'f', 1));
|
||||
discretionaryItem->setCheckState(packet.m_discretionary ? Qt::Checked : Qt::Unchecked);
|
||||
valveCircuitStatusItem->setText(packet.getValveCircuitStatus());
|
||||
confIndItem->setCheckState(packet.m_confirmation ? Qt::Checked : Qt::Unchecked);
|
||||
turbineItem->setCheckState(packet.m_turbine ? Qt::Checked : Qt::Unchecked);
|
||||
motionItem->setCheckState(packet.m_motion ? Qt::Checked : Qt::Unchecked);
|
||||
markerBatteryLightConditionItem->setText(packet.getMarkerLightBatteryCondition());
|
||||
markerLightStatusItem->setText(packet.getMarkerLightStatus());
|
||||
armStatusItem->setText(packet.getArmStatus());
|
||||
crcItem->setCheckState(packet.m_crcValid ? Qt::Checked : Qt::Unchecked);
|
||||
dataHexItem->setText(packet.m_dataHex);
|
||||
filterRow(row);
|
||||
ui->packets->setSortingEnabled(true);
|
||||
if (scrollToBottom) {
|
||||
ui->packets->scrollToBottom();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "EndOfTrainDemodGUI::packetReceived: Unsupported packet: " << packetData;
|
||||
}
|
||||
}
|
||||
|
||||
bool EndOfTrainDemodGUI::handleMessage(const Message& message)
|
||||
{
|
||||
if (EndOfTrainDemod::MsgConfigureEndOfTrainDemod::match(message))
|
||||
{
|
||||
qDebug("EndOfTrainDemodGUI::handleMessage: EndOfTrainDemod::MsgConfigureEndOfTrainDemod");
|
||||
const EndOfTrainDemod::MsgConfigureEndOfTrainDemod& cfg = (EndOfTrainDemod::MsgConfigureEndOfTrainDemod&) message;
|
||||
m_settings = cfg.getSettings();
|
||||
blockApplySettings(true);
|
||||
ui->scopeGUI->updateSettings();
|
||||
m_channelMarker.updateSettings(static_cast<const ChannelMarker*>(m_settings.m_channelMarker));
|
||||
displaySettings();
|
||||
blockApplySettings(false);
|
||||
return true;
|
||||
}
|
||||
else if (DSPSignalNotification::match(message))
|
||||
{
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) message;
|
||||
m_deviceCenterFrequency = notif.getCenterFrequency();
|
||||
m_basebandSampleRate = notif.getSampleRate();
|
||||
ui->deltaFrequency->setValueRange(false, 7, -m_basebandSampleRate/2, m_basebandSampleRate/2);
|
||||
ui->deltaFrequencyLabel->setToolTip(tr("Range %1 %L2 Hz").arg(QChar(0xB1)).arg(m_basebandSampleRate/2));
|
||||
updateAbsoluteCenterFrequency();
|
||||
return true;
|
||||
}
|
||||
else if (MainCore::MsgPacket::match(message))
|
||||
{
|
||||
MainCore::MsgPacket& report = (MainCore::MsgPacket&) message;
|
||||
packetReceived(report.getPacket(), report.getDateTime());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::handleInputMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = getInputMessageQueue()->pop()) != 0)
|
||||
{
|
||||
if (handleMessage(*message))
|
||||
{
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::channelMarkerChangedByCursor()
|
||||
{
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
applySetting("inputFrequencyOffset");
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::channelMarkerHighlightedByCursor()
|
||||
{
|
||||
setHighlighted(m_channelMarker.getHighlighted());
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::on_deltaFrequency_changed(qint64 value)
|
||||
{
|
||||
m_channelMarker.setCenterFrequency(value);
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
updateAbsoluteCenterFrequency();
|
||||
applySetting("inputFrequencyOffset");
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::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;
|
||||
applySetting("rfBandwidth");
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::on_fmDev_valueChanged(int value)
|
||||
{
|
||||
ui->fmDevText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1));
|
||||
m_settings.m_fmDeviation = value * 100.0;
|
||||
applySetting("fmDeviation");
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::on_filterFrom_editingFinished()
|
||||
{
|
||||
m_settings.m_filterFrom = ui->filterFrom->text();
|
||||
filter();
|
||||
applySetting("filterFrom");
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::on_clearTable_clicked()
|
||||
{
|
||||
ui->packets->setRowCount(0);
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::on_udpEnabled_clicked(bool checked)
|
||||
{
|
||||
m_settings.m_udpEnabled = checked;
|
||||
applySetting("udpEnabled");
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::on_udpAddress_editingFinished()
|
||||
{
|
||||
m_settings.m_udpAddress = ui->udpAddress->text();
|
||||
applySetting("udpAddress");
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::on_udpPort_editingFinished()
|
||||
{
|
||||
m_settings.m_udpPort = ui->udpPort->text().toInt();
|
||||
applySetting("udpPort");
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::filterRow(int row)
|
||||
{
|
||||
bool hidden = false;
|
||||
if (m_settings.m_filterFrom != "")
|
||||
{
|
||||
QRegExp re(m_settings.m_filterFrom);
|
||||
QTableWidgetItem *fromItem = ui->packets->item(row, PACKETS_COL_ADDRESS);
|
||||
if (!re.exactMatch(fromItem->text()))
|
||||
hidden = true;
|
||||
}
|
||||
ui->packets->setRowHidden(row, hidden);
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::filter()
|
||||
{
|
||||
for (int i = 0; i < ui->packets->rowCount(); i++)
|
||||
{
|
||||
filterRow(i);
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||||
{
|
||||
(void) widget;
|
||||
(void) rollDown;
|
||||
|
||||
getRollupContents()->saveState(m_rollupState);
|
||||
applySetting("rollupState");
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::onMenuDialogCalled(const QPoint &p)
|
||||
{
|
||||
if (m_contextMenuType == ContextMenuChannelSettings)
|
||||
{
|
||||
BasicChannelSettingsDialog dialog(&m_channelMarker, this);
|
||||
dialog.setUseReverseAPI(m_settings.m_useReverseAPI);
|
||||
dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress);
|
||||
dialog.setReverseAPIPort(m_settings.m_reverseAPIPort);
|
||||
dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex);
|
||||
dialog.setReverseAPIChannelIndex(m_settings.m_reverseAPIChannelIndex);
|
||||
dialog.setDefaultTitle(m_displayedName);
|
||||
|
||||
if (m_deviceUISet->m_deviceMIMOEngine)
|
||||
{
|
||||
dialog.setNumberOfStreams(m_endoftrainDemod->getNumberOfDeviceStreams());
|
||||
dialog.setStreamIndex(m_settings.m_streamIndex);
|
||||
}
|
||||
|
||||
dialog.move(p);
|
||||
new DialogPositioner(&dialog, false);
|
||||
dialog.exec();
|
||||
|
||||
m_settings.m_rgbColor = m_channelMarker.getColor().rgb();
|
||||
m_settings.m_title = m_channelMarker.getTitle();
|
||||
m_settings.m_useReverseAPI = dialog.useReverseAPI();
|
||||
m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress();
|
||||
m_settings.m_reverseAPIPort = dialog.getReverseAPIPort();
|
||||
m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex();
|
||||
m_settings.m_reverseAPIChannelIndex = dialog.getReverseAPIChannelIndex();
|
||||
|
||||
setWindowTitle(m_settings.m_title);
|
||||
setTitle(m_channelMarker.getTitle());
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
|
||||
QStringList settingsKeys({
|
||||
"rgbColor",
|
||||
"title",
|
||||
"useReverseAPI",
|
||||
"reverseAPIAddress",
|
||||
"reverseAPIPort",
|
||||
"reverseAPIDeviceIndex",
|
||||
"reverseAPIChannelIndex"
|
||||
});
|
||||
|
||||
if (m_deviceUISet->m_deviceMIMOEngine)
|
||||
{
|
||||
m_settings.m_streamIndex = dialog.getSelectedStreamIndex();
|
||||
m_channelMarker.clearStreamIndexes();
|
||||
m_channelMarker.addStreamIndex(m_settings.m_streamIndex);
|
||||
updateIndexLabel();
|
||||
}
|
||||
|
||||
applySettings(settingsKeys);
|
||||
}
|
||||
|
||||
resetContextMenuType();
|
||||
}
|
||||
|
||||
EndOfTrainDemodGUI::EndOfTrainDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent) :
|
||||
ChannelGUI(parent),
|
||||
ui(new Ui::EndOfTrainDemodGUI),
|
||||
m_pluginAPI(pluginAPI),
|
||||
m_deviceUISet(deviceUISet),
|
||||
m_channelMarker(this),
|
||||
m_deviceCenterFrequency(0),
|
||||
m_doApplySettings(true),
|
||||
m_tickCount(0)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
m_helpURL = "plugins/channelrx/demodendoftrain/readme.md";
|
||||
RollupContents *rollupContents = getRollupContents();
|
||||
ui->setupUi(rollupContents);
|
||||
setSizePolicy(rollupContents->sizePolicy());
|
||||
rollupContents->arrangeRollups();
|
||||
connect(rollupContents, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
|
||||
|
||||
m_endoftrainDemod = reinterpret_cast<EndOfTrainDemod*>(rxChannel);
|
||||
m_endoftrainDemod->setMessageQueueToGUI(getInputMessageQueue());
|
||||
|
||||
connect(&MainCore::instance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); // 50 ms
|
||||
|
||||
m_scopeVis = m_endoftrainDemod->getScopeSink();
|
||||
m_scopeVis->setGLScope(ui->glScope);
|
||||
ui->glScope->connectTimer(MainCore::instance()->getMasterTimer());
|
||||
ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope);
|
||||
ui->scopeGUI->setStreams(QStringList({"IQ", "MagSq", "FM demod", "f0Filt", "f1Filt", "diff", "sample", "bit", "gotSOP"}));
|
||||
|
||||
// Scope settings to display the IQ waveforms
|
||||
ui->scopeGUI->setPreTrigger(1);
|
||||
GLScopeSettings::TraceData traceDataI, traceDataQ;
|
||||
traceDataI.m_projectionType = Projector::ProjectionReal;
|
||||
traceDataI.m_amp = 1.0; // for -1 to +1
|
||||
traceDataI.m_ofs = 0.0; // vertical offset
|
||||
traceDataQ.m_projectionType = Projector::ProjectionImag;
|
||||
traceDataQ.m_amp = 1.0;
|
||||
traceDataQ.m_ofs = 0.0;
|
||||
ui->scopeGUI->changeTrace(0, traceDataI);
|
||||
ui->scopeGUI->addTrace(traceDataQ);
|
||||
ui->scopeGUI->setDisplayMode(GLScopeSettings::DisplayXYV);
|
||||
ui->scopeGUI->focusOnTrace(0); // re-focus to take changes into account in the GUI
|
||||
|
||||
GLScopeSettings::TriggerData triggerData;
|
||||
triggerData.m_triggerLevel = 0.1;
|
||||
triggerData.m_triggerLevelCoarse = 10;
|
||||
triggerData.m_triggerPositiveEdge = true;
|
||||
ui->scopeGUI->changeTrigger(0, triggerData);
|
||||
ui->scopeGUI->focusOnTrigger(0); // re-focus to take changes into account in the GUI
|
||||
|
||||
m_scopeVis->setLiveRate(EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE);
|
||||
//m_scopeVis->setFreeRun(false); // FIXME: add method rather than call m_scopeVis->configure()
|
||||
|
||||
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
|
||||
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
|
||||
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
|
||||
ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenAndBlue);
|
||||
|
||||
m_channelMarker.blockSignals(true);
|
||||
m_channelMarker.setColor(Qt::yellow);
|
||||
m_channelMarker.setBandwidth(m_settings.m_rfBandwidth);
|
||||
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
|
||||
m_channelMarker.setTitle("End Of Train Demodulator");
|
||||
m_channelMarker.blockSignals(false);
|
||||
m_channelMarker.setVisible(true); // activate signal on the last setting only
|
||||
|
||||
setTitleColor(m_channelMarker.getColor());
|
||||
m_settings.setChannelMarker(&m_channelMarker);
|
||||
m_settings.setRollupState(&m_rollupState);
|
||||
|
||||
m_deviceUISet->addChannelMarker(&m_channelMarker);
|
||||
|
||||
connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor()));
|
||||
connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor()));
|
||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
|
||||
ui->scopeContainer->setVisible(false);
|
||||
|
||||
// Resize the table using dummy data
|
||||
resizeTable();
|
||||
// Allow user to reorder columns
|
||||
ui->packets->horizontalHeader()->setSectionsMovable(true);
|
||||
// Allow user to sort table by clicking on headers
|
||||
ui->packets->setSortingEnabled(true);
|
||||
// Add context menu to allow hiding/showing of columns
|
||||
menu = new QMenu(ui->packets);
|
||||
for (int i = 0; i < ui->packets->horizontalHeader()->count(); i++)
|
||||
{
|
||||
QString text = ui->packets->horizontalHeaderItem(i)->text();
|
||||
menu->addAction(createCheckableItem(text, i, true));
|
||||
}
|
||||
ui->packets->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->packets->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(columnSelectMenu(QPoint)));
|
||||
// Get signals when columns change
|
||||
connect(ui->packets->horizontalHeader(), SIGNAL(sectionMoved(int, int, int)), SLOT(endoftrains_sectionMoved(int, int, int)));
|
||||
connect(ui->packets->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), SLOT(endoftrains_sectionResized(int, int, int)));
|
||||
|
||||
displaySettings();
|
||||
makeUIConnections();
|
||||
applyAllSettings();
|
||||
m_resizer.enableChildMouseTracking();
|
||||
}
|
||||
|
||||
EndOfTrainDemodGUI::~EndOfTrainDemodGUI()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::blockApplySettings(bool block)
|
||||
{
|
||||
m_doApplySettings = !block;
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::applySetting(const QString& settingsKey)
|
||||
{
|
||||
applySettings({settingsKey});
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::applySettings(const QStringList& settingsKeys, bool force)
|
||||
{
|
||||
m_settingsKeys.append(settingsKeys);
|
||||
if (m_doApplySettings)
|
||||
{
|
||||
EndOfTrainDemod::MsgConfigureEndOfTrainDemod* message = EndOfTrainDemod::MsgConfigureEndOfTrainDemod::create(m_settings, m_settingsKeys, force);
|
||||
m_endoftrainDemod->getInputMessageQueue()->push(message);
|
||||
m_settingsKeys.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::applyAllSettings()
|
||||
{
|
||||
applySettings(QStringList(), true);
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::displaySettings()
|
||||
{
|
||||
m_channelMarker.blockSignals(true);
|
||||
m_channelMarker.setBandwidth(m_settings.m_rfBandwidth);
|
||||
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
|
||||
m_channelMarker.setTitle(m_settings.m_title);
|
||||
m_channelMarker.blockSignals(false);
|
||||
m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only
|
||||
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
setWindowTitle(m_channelMarker.getTitle());
|
||||
setTitle(m_channelMarker.getTitle());
|
||||
|
||||
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);
|
||||
|
||||
updateIndexLabel();
|
||||
|
||||
ui->filterFrom->setText(m_settings.m_filterFrom);
|
||||
|
||||
ui->udpEnabled->setChecked(m_settings.m_udpEnabled);
|
||||
ui->udpAddress->setText(m_settings.m_udpAddress);
|
||||
ui->udpPort->setText(QString::number(m_settings.m_udpPort));
|
||||
|
||||
ui->logFilename->setToolTip(QString(".csv log filename: %1").arg(m_settings.m_logFilename));
|
||||
ui->logEnable->setChecked(m_settings.m_logEnabled);
|
||||
|
||||
ui->useFileTime->setChecked(m_settings.m_useFileTime);
|
||||
|
||||
// Order and size columns
|
||||
QHeaderView *header = ui->packets->horizontalHeader();
|
||||
for (int i = 0; i < ENDOFTRAINDEMOD_COLUMNS; i++)
|
||||
{
|
||||
bool hidden = m_settings.m_columnSizes[i] == 0;
|
||||
header->setSectionHidden(i, hidden);
|
||||
menu->actions().at(i)->setChecked(!hidden);
|
||||
if (m_settings.m_columnSizes[i] > 0)
|
||||
ui->packets->setColumnWidth(i, m_settings.m_columnSizes[i]);
|
||||
header->moveSection(header->visualIndex(i), m_settings.m_columnIndexes[i]);
|
||||
}
|
||||
|
||||
filter();
|
||||
|
||||
getRollupContents()->restoreState(m_rollupState);
|
||||
updateAbsoluteCenterFrequency();
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::leaveEvent(QEvent* event)
|
||||
{
|
||||
m_channelMarker.setHighlighted(false);
|
||||
ChannelGUI::leaveEvent(event);
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::enterEvent(EnterEventType* event)
|
||||
{
|
||||
m_channelMarker.setHighlighted(true);
|
||||
ChannelGUI::enterEvent(event);
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::tick()
|
||||
{
|
||||
double magsqAvg, magsqPeak;
|
||||
int nbMagsqSamples;
|
||||
m_endoftrainDemod->getMagSqLevels(magsqAvg, magsqPeak, nbMagsqSamples);
|
||||
double powDbAvg = CalcDb::dbPower(magsqAvg);
|
||||
double powDbPeak = CalcDb::dbPower(magsqPeak);
|
||||
|
||||
ui->channelPowerMeter->levelChanged(
|
||||
(100.0f + powDbAvg) / 100.0f,
|
||||
(100.0f + powDbPeak) / 100.0f,
|
||||
nbMagsqSamples);
|
||||
|
||||
if (m_tickCount % 4 == 0) {
|
||||
ui->channelPower->setText(QString::number(powDbAvg, 'f', 1));
|
||||
}
|
||||
|
||||
m_tickCount++;
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::on_logEnable_clicked(bool checked)
|
||||
{
|
||||
m_settings.m_logEnabled = checked;
|
||||
applySetting("logEnabled");
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::on_logFilename_clicked()
|
||||
{
|
||||
// Get filename to save to
|
||||
QFileDialog fileDialog(nullptr, "Select file to log received frames to", "", "*.csv");
|
||||
fileDialog.setAcceptMode(QFileDialog::AcceptSave);
|
||||
if (fileDialog.exec())
|
||||
{
|
||||
QStringList fileNames = fileDialog.selectedFiles();
|
||||
if (fileNames.size() > 0)
|
||||
{
|
||||
m_settings.m_logFilename = fileNames[0];
|
||||
ui->logFilename->setToolTip(QString(".csv log filename: %1").arg(m_settings.m_logFilename));
|
||||
applySetting("logFilename");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read .csv log and process as received frames
|
||||
void EndOfTrainDemodGUI::on_logOpen_clicked()
|
||||
{
|
||||
QFileDialog fileDialog(nullptr, "Select .csv log file to read", "", "*.csv");
|
||||
if (fileDialog.exec())
|
||||
{
|
||||
QStringList fileNames = fileDialog.selectedFiles();
|
||||
if (fileNames.size() > 0)
|
||||
{
|
||||
QFile file(fileNames[0]);
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
QTextStream in(&file);
|
||||
QString error;
|
||||
QHash<QString, int> colIndexes = CSV::readHeader(in, {"Date", "Time", "Data"}, error);
|
||||
if (error.isEmpty())
|
||||
{
|
||||
int dateCol = colIndexes.value("Date");
|
||||
int timeCol = colIndexes.value("Time");
|
||||
int dataCol = colIndexes.value("Data");
|
||||
int maxCol = std::max({dateCol, timeCol, dataCol});
|
||||
|
||||
QMessageBox dialog(this);
|
||||
dialog.setText("Reading packet data");
|
||||
dialog.addButton(QMessageBox::Cancel);
|
||||
dialog.show();
|
||||
QApplication::processEvents();
|
||||
int count = 0;
|
||||
bool cancelled = false;
|
||||
QStringList cols;
|
||||
while (!cancelled && CSV::readRow(in, &cols))
|
||||
{
|
||||
if (cols.size() > maxCol)
|
||||
{
|
||||
QDate date = QDate::fromString(cols[dateCol]);
|
||||
QTime time = QTime::fromString(cols[timeCol]);
|
||||
QDateTime dateTime(date, time);
|
||||
QByteArray bytes = QByteArray::fromHex(cols[dataCol].toLatin1());
|
||||
packetReceived(bytes, dateTime);
|
||||
if (count % 1000 == 0)
|
||||
{
|
||||
QApplication::processEvents();
|
||||
if (dialog.clickedButton()) {
|
||||
cancelled = true;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
dialog.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "End-Of-Train Demod", error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "End-Of-Train Demod", QString("Failed to open file %1").arg(fileNames[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::on_useFileTime_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_useFileTime = checked;
|
||||
applySetting("useFileTime");
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::makeUIConnections()
|
||||
{
|
||||
QObject::connect(ui->deltaFrequency, &ValueDialZ::changed, this, &EndOfTrainDemodGUI::on_deltaFrequency_changed);
|
||||
QObject::connect(ui->rfBW, &QSlider::valueChanged, this, &EndOfTrainDemodGUI::on_rfBW_valueChanged);
|
||||
QObject::connect(ui->fmDev, &QSlider::valueChanged, this, &EndOfTrainDemodGUI::on_fmDev_valueChanged);
|
||||
QObject::connect(ui->filterFrom, &QLineEdit::editingFinished, this, &EndOfTrainDemodGUI::on_filterFrom_editingFinished);
|
||||
QObject::connect(ui->clearTable, &QPushButton::clicked, this, &EndOfTrainDemodGUI::on_clearTable_clicked);
|
||||
QObject::connect(ui->udpEnabled, &QCheckBox::clicked, this, &EndOfTrainDemodGUI::on_udpEnabled_clicked);
|
||||
QObject::connect(ui->udpAddress, &QLineEdit::editingFinished, this, &EndOfTrainDemodGUI::on_udpAddress_editingFinished);
|
||||
QObject::connect(ui->udpPort, &QLineEdit::editingFinished, this, &EndOfTrainDemodGUI::on_udpPort_editingFinished);
|
||||
QObject::connect(ui->logEnable, &ButtonSwitch::clicked, this, &EndOfTrainDemodGUI::on_logEnable_clicked);
|
||||
QObject::connect(ui->logFilename, &QToolButton::clicked, this, &EndOfTrainDemodGUI::on_logFilename_clicked);
|
||||
QObject::connect(ui->logOpen, &QToolButton::clicked, this, &EndOfTrainDemodGUI::on_logOpen_clicked);
|
||||
QObject::connect(ui->useFileTime, &ButtonSwitch::toggled, this, &EndOfTrainDemodGUI::on_useFileTime_toggled);
|
||||
}
|
||||
|
||||
void EndOfTrainDemodGUI::updateAbsoluteCenterFrequency()
|
||||
{
|
||||
setStatusFrequency(m_deviceCenterFrequency + m_settings.m_inputFrequencyOffset);
|
||||
}
|
153
plugins/channelrx/demodendoftrain/endoftraindemodgui.h
Normal file
153
plugins/channelrx/demodendoftrain/endoftraindemodgui.h
Normal file
@ -0,0 +1,153 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2020-2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// Copyright (C) 2020, 2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// //
|
||||
// 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_ENDOFTRAINDEMODGUI_H
|
||||
#define INCLUDE_ENDOFTRAINDEMODGUI_H
|
||||
|
||||
#include <QMenu>
|
||||
|
||||
#include "channel/channelgui.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "util/messagequeue.h"
|
||||
#include "settings/rollupstate.h"
|
||||
#include "endoftraindemodsettings.h"
|
||||
|
||||
class PluginAPI;
|
||||
class DeviceUISet;
|
||||
class BasebandSampleSink;
|
||||
class ScopeVis;
|
||||
class EndOfTrainDemod;
|
||||
class EndOfTrainDemodGUI;
|
||||
|
||||
namespace Ui {
|
||||
class EndOfTrainDemodGUI;
|
||||
}
|
||||
class EndOfTrainDemodGUI;
|
||||
|
||||
class EndOfTrainDemodGUI : public ChannelGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static EndOfTrainDemodGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel);
|
||||
virtual void destroy();
|
||||
|
||||
void resetToDefaults();
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; };
|
||||
virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; };
|
||||
virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; };
|
||||
virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; };
|
||||
virtual QString getTitle() const { return m_settings.m_title; };
|
||||
virtual QColor getTitleColor() const { return m_settings.m_rgbColor; };
|
||||
virtual void zetHidden(bool hidden) { m_settings.m_hidden = hidden; }
|
||||
virtual bool getHidden() const { return m_settings.m_hidden; }
|
||||
virtual ChannelMarker& getChannelMarker() { return m_channelMarker; }
|
||||
virtual int getStreamIndex() const { return m_settings.m_streamIndex; }
|
||||
virtual void setStreamIndex(int streamIndex) { m_settings.m_streamIndex = streamIndex; }
|
||||
|
||||
public slots:
|
||||
void channelMarkerChangedByCursor();
|
||||
void channelMarkerHighlightedByCursor();
|
||||
|
||||
private:
|
||||
Ui::EndOfTrainDemodGUI* ui;
|
||||
PluginAPI* m_pluginAPI;
|
||||
DeviceUISet* m_deviceUISet;
|
||||
ChannelMarker m_channelMarker;
|
||||
RollupState m_rollupState;
|
||||
EndOfTrainDemodSettings m_settings;
|
||||
QStringList m_settingsKeys;
|
||||
qint64 m_deviceCenterFrequency;
|
||||
bool m_doApplySettings;
|
||||
ScopeVis* m_scopeVis;
|
||||
|
||||
EndOfTrainDemod* m_endoftrainDemod;
|
||||
int m_basebandSampleRate;
|
||||
uint32_t m_tickCount;
|
||||
MessageQueue m_inputMessageQueue;
|
||||
|
||||
QMenu *menu; // Column select context menu
|
||||
|
||||
explicit EndOfTrainDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0);
|
||||
virtual ~EndOfTrainDemodGUI();
|
||||
|
||||
void blockApplySettings(bool block);
|
||||
void applySetting(const QString& settingsKey);
|
||||
void applySettings(const QStringList& settingsKeys, bool force = false);
|
||||
void applyAllSettings();
|
||||
void displaySettings();
|
||||
void packetReceived(const QByteArray& packet, const QDateTime& dateTime);
|
||||
bool handleMessage(const Message& message);
|
||||
void makeUIConnections();
|
||||
void updateAbsoluteCenterFrequency();
|
||||
|
||||
void leaveEvent(QEvent*);
|
||||
void enterEvent(EnterEventType*);
|
||||
|
||||
void resizeTable();
|
||||
QAction *createCheckableItem(QString& text, int idx, bool checked);
|
||||
|
||||
enum EndOfTrainCol {
|
||||
PACKETS_COL_DATE,
|
||||
PACKETS_COL_TIME,
|
||||
PACKETS_COL_CHAINING_BITS,
|
||||
PACKETS_COL_BATTERY_CONDITION,
|
||||
PACKETS_COL_TYPE,
|
||||
PACKETS_COL_ADDRESS,
|
||||
PACKETS_COL_PRESSURE,
|
||||
PACKETS_COL_BATTERY_CHARGE,
|
||||
PACKETS_COL_DISCRETIONARY,
|
||||
PACKETS_COL_VALVE_CIRCUIT_STATUS,
|
||||
PACKETS_COL_CONF_IND,
|
||||
PACKETS_COL_TURBINE,
|
||||
PACKETS_COL_MOTION,
|
||||
PACKETS_COL_MARKER_BATTERY,
|
||||
PACKETS_COL_MARKER_LIGHT,
|
||||
PACKETS_COL_ARM_STATUS,
|
||||
PACKETS_COL_CRC,
|
||||
PACKETS_COL_DATA_HEX
|
||||
};
|
||||
|
||||
private slots:
|
||||
void on_deltaFrequency_changed(qint64 value);
|
||||
void on_rfBW_valueChanged(int index);
|
||||
void on_fmDev_valueChanged(int value);
|
||||
void on_filterFrom_editingFinished();
|
||||
void on_clearTable_clicked();
|
||||
void on_udpEnabled_clicked(bool checked);
|
||||
void on_udpAddress_editingFinished();
|
||||
void on_udpPort_editingFinished();
|
||||
void on_logEnable_clicked(bool checked=false);
|
||||
void on_logFilename_clicked();
|
||||
void on_logOpen_clicked();
|
||||
void on_useFileTime_toggled(bool checked=false);
|
||||
void filterRow(int row);
|
||||
void filter();
|
||||
void endoftrains_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex);
|
||||
void endoftrains_sectionResized(int logicalIndex, int oldSize, int newSize);
|
||||
void columnSelectMenu(QPoint pos);
|
||||
void columnSelectMenuChecked(bool checked = false);
|
||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||
void onMenuDialogCalled(const QPoint& p);
|
||||
void handleInputMessages();
|
||||
void tick();
|
||||
};
|
||||
|
||||
#endif // INCLUDE_ENDOFTRAINDEMODGUI_H
|
875
plugins/channelrx/demodendoftrain/endoftraindemodgui.ui
Normal file
875
plugins/channelrx/demodendoftrain/endoftraindemodgui.ui
Normal file
@ -0,0 +1,875 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EndOfTrainDemodGUI</class>
|
||||
<widget class="RollupContents" name="EndOfTrainDemodGUI">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>398</width>
|
||||
<height>806</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>352</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>EndOfTrain Demodulator</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="settingsContainer" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>390</width>
|
||||
<height>151</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>350</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="powLayout">
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<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>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</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>
|
||||
<layout class="QHBoxLayout" name="channelPowerLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="channelPower">
|
||||
<property name="toolTip">
|
||||
<string>Channel power</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::RightToLeft</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0.0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="channelPowerUnits">
|
||||
<property name="text">
|
||||
<string> dB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="powerLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="channelPowerMeterUnits">
|
||||
<property name="text">
|
||||
<string>dB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LevelMeterSignalDB" name="channelPowerMeter" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Liberation Mono</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Level meter (dB) top trace: average, bottom trace: instantaneous peak, tip: peak hold</string>
|
||||
</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="phySettingsLayout">
|
||||
<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_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<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="Line" name="line_2">
|
||||
<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_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="udpLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="udpEnabledLabel">
|
||||
<property name="text">
|
||||
<string>UDP</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="udpEnabled">
|
||||
<property name="toolTip">
|
||||
<string>Send endoftrains via UDP</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::RightToLeft</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="udpAddress">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Destination UDP address</string>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string>000.000.000.000</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>127.0.0.1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="udpSeparator">
|
||||
<property name="text">
|
||||
<string>:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="udpPort">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Destination UDP port</string>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string>00000</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>9998</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="filterLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="filterFromLabel">
|
||||
<property name="text">
|
||||
<string>Filter Address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="filterFrom">
|
||||
<property name="toolTip">
|
||||
<string>Display only packets where the address matches the specified regular expression</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<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="ButtonSwitch" name="useFileTime">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Check to use date and time from input file. Uncheck to use date and time from clock.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/clockcurrent.png</normaloff>
|
||||
<normalon>:/clockfile.png</normalon>:/clockcurrent.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="logEnable">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Start/stop logging of received packets to .csv file</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/record_off.png</normaloff>:/record_off.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="logFilename">
|
||||
<property name="toolTip">
|
||||
<string>Set log .csv filename</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/save.png</normaloff>:/save.png</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="logOpen">
|
||||
<property name="toolTip">
|
||||
<string>Read data from .csv log file</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/load.png</normaloff>:/load.png</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="clearTable">
|
||||
<property name="toolTip">
|
||||
<string>Clear endoftrains from table</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/bin.png</normaloff>:/bin.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="dataContainer" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>170</y>
|
||||
<width>391</width>
|
||||
<height>261</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Received Packets</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayoutTable">
|
||||
<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="QTableWidget" name="packets">
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Date</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Date packet was received</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Time</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Time packet was received</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Chain</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Battery</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Battery condition</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Message type</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Unit address</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Pressure (PSIG)</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Brake pipe pressure in Pounds per Square Inch Gauge (PSIG)</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Charge (%)</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Battery charge in %</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Disc</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Discretionary bit used for varying data by different vendors</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Valve</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Valve circuit status</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Conf</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Confirmation</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Turbine</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Motion</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Motion detected</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Light Batt</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Market light battery condtion</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Light</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Marker light status (on / off)</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Arm Status</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>CRC</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Indicates if calculated CRC matches received CRC</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Hex</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Packet hex data</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="scopeContainer" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>440</y>
|
||||
<width>716</width>
|
||||
<height>341</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>714</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Waveforms</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="transmittedLayout_2">
|
||||
<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="GLScope" name="glScope" 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="GLScopeGUI" name="scopeGUI" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<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>
|
||||
<customwidget>
|
||||
<class>RollupContents</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupcontents.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LevelMeterSignalDB</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/levelmeter.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GLScope</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/glscope.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GLScopeGUI</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/glscopegui.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>packets</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../../sdrgui/resources/res.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
96
plugins/channelrx/demodendoftrain/endoftraindemodplugin.cpp
Normal file
96
plugins/channelrx/demodendoftrain/endoftraindemodplugin.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
||||
// written by Christian Daniel //
|
||||
// Copyright (C) 2015-2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// Copyright (C) 2019 Davide Gerhard <rainbow@irh.it> //
|
||||
// Copyright (C) 2020-2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// Copyright (C) 2020 Kacper Michajłow <kasper93@gmail.com> //
|
||||
// //
|
||||
// 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 "endoftraindemodgui.h"
|
||||
#endif
|
||||
#include "endoftraindemod.h"
|
||||
#include "endoftraindemodwebapiadapter.h"
|
||||
#include "endoftraindemodplugin.h"
|
||||
|
||||
const PluginDescriptor EndOfTrainDemodPlugin::m_pluginDescriptor = {
|
||||
EndOfTrainDemod::m_channelId,
|
||||
QStringLiteral("End-of-Train Demodulator"),
|
||||
QStringLiteral("7.19.0"),
|
||||
QStringLiteral("(c) Jon Beniston, M7RCE"),
|
||||
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
||||
true,
|
||||
QStringLiteral("https://github.com/f4exb/sdrangel")
|
||||
};
|
||||
|
||||
EndOfTrainDemodPlugin::EndOfTrainDemodPlugin(QObject* parent) :
|
||||
QObject(parent),
|
||||
m_pluginAPI(0)
|
||||
{
|
||||
}
|
||||
|
||||
const PluginDescriptor& EndOfTrainDemodPlugin::getPluginDescriptor() const
|
||||
{
|
||||
return m_pluginDescriptor;
|
||||
}
|
||||
|
||||
void EndOfTrainDemodPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
{
|
||||
m_pluginAPI = pluginAPI;
|
||||
|
||||
m_pluginAPI->registerRxChannel(EndOfTrainDemod::m_channelIdURI, EndOfTrainDemod::m_channelId, this);
|
||||
}
|
||||
|
||||
void EndOfTrainDemodPlugin::createRxChannel(DeviceAPI *deviceAPI, BasebandSampleSink **bs, ChannelAPI **cs) const
|
||||
{
|
||||
if (bs || cs)
|
||||
{
|
||||
EndOfTrainDemod *instance = new EndOfTrainDemod(deviceAPI);
|
||||
|
||||
if (bs) {
|
||||
*bs = instance;
|
||||
}
|
||||
|
||||
if (cs) {
|
||||
*cs = instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SERVER_MODE
|
||||
ChannelGUI* EndOfTrainDemodPlugin::createRxChannelGUI(
|
||||
DeviceUISet *deviceUISet,
|
||||
BasebandSampleSink *rxChannel) const
|
||||
{
|
||||
(void) deviceUISet;
|
||||
(void) rxChannel;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
ChannelGUI* EndOfTrainDemodPlugin::createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) const
|
||||
{
|
||||
return EndOfTrainDemodGUI::create(m_pluginAPI, deviceUISet, rxChannel);
|
||||
}
|
||||
#endif
|
||||
|
||||
ChannelWebAPIAdapter* EndOfTrainDemodPlugin::createChannelWebAPIAdapter() const
|
||||
{
|
||||
return new EndOfTrainDemodWebAPIAdapter();
|
||||
}
|
52
plugins/channelrx/demodendoftrain/endoftraindemodplugin.h
Normal file
52
plugins/channelrx/demodendoftrain/endoftraindemodplugin.h
Normal file
@ -0,0 +1,52 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
||||
// written by Christian Daniel //
|
||||
// Copyright (C) 2015-2020 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// Copyright (C) 2015 John Greb <hexameron@spam.no> //
|
||||
// Copyright (C) 2020-2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// //
|
||||
// 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_ENDOFTRAINDEMODPLUGIN_H
|
||||
#define INCLUDE_ENDOFTRAINDEMODPLUGIN_H
|
||||
|
||||
#include <QObject>
|
||||
#include "plugin/plugininterface.h"
|
||||
|
||||
class DeviceUISet;
|
||||
class BasebandSampleSink;
|
||||
|
||||
class EndOfTrainDemodPlugin : public QObject, PluginInterface {
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(PluginInterface)
|
||||
Q_PLUGIN_METADATA(IID "sdrangel.channel.endoftraindemod")
|
||||
|
||||
public:
|
||||
explicit EndOfTrainDemodPlugin(QObject* parent = NULL);
|
||||
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
virtual void createRxChannel(DeviceAPI *deviceAPI, BasebandSampleSink **bs, ChannelAPI **cs) const;
|
||||
virtual ChannelGUI* createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) const;
|
||||
virtual ChannelWebAPIAdapter* createChannelWebAPIAdapter() const;
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
||||
PluginAPI* m_pluginAPI;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_ENDOFTRAINDEMODPLUGIN_H
|
328
plugins/channelrx/demodendoftrain/endoftraindemodsettings.cpp
Normal file
328
plugins/channelrx/demodendoftrain/endoftraindemodsettings.cpp
Normal file
@ -0,0 +1,328 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
||||
// written by Christian Daniel //
|
||||
// Copyright (C) 2015-2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// Copyright (C) 2020-2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// //
|
||||
// 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 "util/simpleserializer.h"
|
||||
#include "settings/serializable.h"
|
||||
#include "endoftraindemodsettings.h"
|
||||
|
||||
EndOfTrainDemodSettings::EndOfTrainDemodSettings() :
|
||||
m_channelMarker(nullptr),
|
||||
m_rollupState(nullptr)
|
||||
{
|
||||
for (int i = 0; i < ENDOFTRAINDEMOD_COLUMNS; i++)
|
||||
{
|
||||
m_columnIndexes.append(i);
|
||||
m_columnSizes.append(-1);
|
||||
}
|
||||
resetToDefaults();
|
||||
}
|
||||
|
||||
void EndOfTrainDemodSettings::resetToDefaults()
|
||||
{
|
||||
m_inputFrequencyOffset = 0;
|
||||
m_rfBandwidth = 20000.0f;
|
||||
m_fmDeviation = 3000.0f;
|
||||
m_filterFrom = "";
|
||||
m_udpEnabled = false;
|
||||
m_udpAddress = "127.0.0.1";
|
||||
m_udpPort = 9999;
|
||||
m_logFilename = "endoftrain_log.csv";
|
||||
m_logEnabled = false;
|
||||
m_useFileTime = false;
|
||||
|
||||
m_rgbColor = QColor(170, 85, 0).rgb();
|
||||
m_title = "End-of-Train Demodulator";
|
||||
m_streamIndex = 0;
|
||||
m_useReverseAPI = false;
|
||||
m_reverseAPIAddress = "127.0.0.1";
|
||||
m_reverseAPIPort = 8888;
|
||||
m_reverseAPIDeviceIndex = 0;
|
||||
m_reverseAPIChannelIndex = 0;
|
||||
m_workspaceIndex = 0;
|
||||
m_hidden = false;
|
||||
|
||||
for (int i = 0; i < ENDOFTRAINDEMOD_COLUMNS; i++)
|
||||
{
|
||||
m_columnIndexes[i] = i;
|
||||
m_columnSizes[i] = -1; // Autosize
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray EndOfTrainDemodSettings::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
|
||||
s.writeS32(1, m_inputFrequencyOffset);
|
||||
s.writeFloat(2, m_rfBandwidth);
|
||||
s.writeFloat(3, m_fmDeviation);
|
||||
s.writeString(4, m_filterFrom);
|
||||
s.writeBool(5, m_udpEnabled);
|
||||
s.writeString(6, m_udpAddress);
|
||||
s.writeU32(7, m_udpPort);
|
||||
s.writeString(8, m_logFilename);
|
||||
s.writeBool(9, m_logEnabled);
|
||||
s.writeBool(10, m_useFileTime);
|
||||
|
||||
s.writeU32(20, m_rgbColor);
|
||||
s.writeString(21, m_title);
|
||||
if (m_channelMarker) {
|
||||
s.writeBlob(22, m_channelMarker->serialize());
|
||||
}
|
||||
s.writeS32(23, m_streamIndex);
|
||||
s.writeBool(24, m_useReverseAPI);
|
||||
s.writeString(25, m_reverseAPIAddress);
|
||||
s.writeU32(26, m_reverseAPIPort);
|
||||
s.writeU32(27, m_reverseAPIDeviceIndex);
|
||||
s.writeU32(28, m_reverseAPIChannelIndex);
|
||||
if (m_rollupState) {
|
||||
s.writeBlob(29, m_rollupState->serialize());
|
||||
}
|
||||
s.writeS32(30, m_workspaceIndex);
|
||||
s.writeBlob(31, m_geometryBytes);
|
||||
s.writeBool(32, m_hidden);
|
||||
|
||||
s.writeList(33, m_columnIndexes);
|
||||
s.writeList(34, m_columnSizes);
|
||||
|
||||
return s.final();
|
||||
}
|
||||
|
||||
bool EndOfTrainDemodSettings::deserialize(const QByteArray& data)
|
||||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if(!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
uint32_t utmp;
|
||||
QString strtmp;
|
||||
|
||||
d.readS32(1, &m_inputFrequencyOffset, 0);
|
||||
d.readFloat(2, &m_rfBandwidth, 20000.0f);
|
||||
d.readFloat(3, &m_fmDeviation, 3000.0f);
|
||||
d.readString(4, &m_filterFrom, "");
|
||||
d.readBool(5, &m_udpEnabled);
|
||||
d.readString(6, &m_udpAddress);
|
||||
d.readU32(7, &utmp);
|
||||
if ((utmp > 1023) && (utmp < 65535)) {
|
||||
m_udpPort = utmp;
|
||||
} else {
|
||||
m_udpPort = 9999;
|
||||
}
|
||||
d.readString(8, &m_logFilename, "endoftrain_log.csv");
|
||||
d.readBool(9, &m_logEnabled, false);
|
||||
d.readBool(10, &m_useFileTime, false);
|
||||
|
||||
d.readU32(20, &m_rgbColor, QColor(170, 85, 0).rgb());
|
||||
d.readString(21, &m_title, "End-of-Train Demodulator");
|
||||
if (m_channelMarker)
|
||||
{
|
||||
d.readBlob(22, &bytetmp);
|
||||
m_channelMarker->deserialize(bytetmp);
|
||||
}
|
||||
d.readS32(23, &m_streamIndex, 0);
|
||||
d.readBool(24, &m_useReverseAPI, false);
|
||||
d.readString(25, &m_reverseAPIAddress, "127.0.0.1");
|
||||
d.readU32(26, &utmp, 0);
|
||||
|
||||
if ((utmp > 1023) && (utmp < 65535)) {
|
||||
m_reverseAPIPort = utmp;
|
||||
} else {
|
||||
m_reverseAPIPort = 8888;
|
||||
}
|
||||
|
||||
d.readU32(27, &utmp, 0);
|
||||
m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp;
|
||||
d.readU32(28, &utmp, 0);
|
||||
m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp;
|
||||
|
||||
if (m_rollupState)
|
||||
{
|
||||
d.readBlob(29, &bytetmp);
|
||||
m_rollupState->deserialize(bytetmp);
|
||||
}
|
||||
|
||||
d.readS32(30, &m_workspaceIndex, 0);
|
||||
d.readBlob(31, &m_geometryBytes);
|
||||
d.readBool(32, &m_hidden, false);
|
||||
|
||||
d.readList(33, &m_columnIndexes);
|
||||
d.readList(34, &m_columnSizes);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemodSettings::applySettings(const QStringList& settingsKeys, const EndOfTrainDemodSettings& settings)
|
||||
{
|
||||
if (settingsKeys.contains("inputFrequencyOffset")) {
|
||||
m_inputFrequencyOffset = settings.m_inputFrequencyOffset;
|
||||
}
|
||||
if (settingsKeys.contains("rfBandwidth")) {
|
||||
m_rfBandwidth = settings.m_rfBandwidth;
|
||||
}
|
||||
if (settingsKeys.contains("fmDeviation")) {
|
||||
m_fmDeviation = settings.m_fmDeviation;
|
||||
}
|
||||
if (settingsKeys.contains("filterFrom")) {
|
||||
m_filterFrom = settings.m_filterFrom;
|
||||
}
|
||||
if (settingsKeys.contains("udpEnabled")) {
|
||||
m_udpEnabled = settings.m_udpEnabled;
|
||||
}
|
||||
if (settingsKeys.contains("udpAddress")) {
|
||||
m_udpAddress = settings.m_udpAddress;
|
||||
}
|
||||
if (settingsKeys.contains("udpPort")) {
|
||||
m_udpPort = settings.m_udpPort;
|
||||
}
|
||||
if (settingsKeys.contains("logFilename")) {
|
||||
m_logFilename = settings.m_logFilename;
|
||||
}
|
||||
if (settingsKeys.contains("logEnabled")) {
|
||||
m_logEnabled = settings.m_logEnabled;
|
||||
}
|
||||
if (settingsKeys.contains("useFileTime")) {
|
||||
m_useFileTime = settings.m_useFileTime;
|
||||
}
|
||||
if (settingsKeys.contains("rgbColor")) {
|
||||
m_rgbColor = settings.m_rgbColor;
|
||||
}
|
||||
if (settingsKeys.contains("title")) {
|
||||
m_title = settings.m_title;
|
||||
}
|
||||
if (settingsKeys.contains("streamIndex")) {
|
||||
m_streamIndex = settings.m_streamIndex;
|
||||
}
|
||||
if (settingsKeys.contains("useReverseAPI")) {
|
||||
m_useReverseAPI = settings.m_useReverseAPI;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIAddress")) {
|
||||
m_reverseAPIAddress = settings.m_reverseAPIAddress;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIPort")) {
|
||||
m_reverseAPIPort = settings.m_reverseAPIPort;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIDeviceIndex")) {
|
||||
m_reverseAPIDeviceIndex = settings.m_reverseAPIDeviceIndex;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIChannelIndex")) {
|
||||
m_reverseAPIChannelIndex = settings.m_reverseAPIChannelIndex;
|
||||
}
|
||||
if (settingsKeys.contains("workspaceIndex")) {
|
||||
m_workspaceIndex = settings.m_workspaceIndex;
|
||||
}
|
||||
if (settingsKeys.contains("hidden")) {
|
||||
m_hidden = settings.m_hidden;
|
||||
}
|
||||
if (settingsKeys.contains("columnIndexes")) {
|
||||
m_columnIndexes = settings.m_columnIndexes;
|
||||
}
|
||||
if (settingsKeys.contains("columnSizes")) {
|
||||
m_columnSizes = settings.m_columnSizes;
|
||||
}
|
||||
}
|
||||
|
||||
QString EndOfTrainDemodSettings::getDebugString(const QStringList& settingsKeys, bool force) const
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
|
||||
if (settingsKeys.contains("inputFrequencyOffset") || force) {
|
||||
ostr << " m_inputFrequencyOffset: " << m_inputFrequencyOffset;
|
||||
}
|
||||
if (settingsKeys.contains("rfBandwidth")) {
|
||||
ostr << " m_rfBandwidth: " << m_rfBandwidth;
|
||||
}
|
||||
if (settingsKeys.contains("fmDeviation")) {
|
||||
ostr << " m_fmDeviation: " << m_fmDeviation;
|
||||
}
|
||||
if (settingsKeys.contains("filterFrom")) {
|
||||
ostr << " m_filterFrom: " << m_filterFrom.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("udpEnabled")) {
|
||||
ostr << " m_udpEnabled: " << m_udpEnabled;
|
||||
}
|
||||
if (settingsKeys.contains("udpAddress")) {
|
||||
ostr << " m_udpAddress: " << m_udpAddress.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("udpPort")) {
|
||||
ostr << " m_udpPort: " << m_udpPort;
|
||||
}
|
||||
if (settingsKeys.contains("logFilename")) {
|
||||
ostr << " m_logFilename: " << m_logFilename.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("logEnabledp")) {
|
||||
ostr << " m_logEnabled: " << m_logEnabled;
|
||||
}
|
||||
if (settingsKeys.contains("useFileTime")) {
|
||||
ostr << " m_useFileTime: " << m_useFileTime;
|
||||
}
|
||||
if (settingsKeys.contains("rgbColor") || force) {
|
||||
ostr << " m_rgbColor: " << m_rgbColor;
|
||||
}
|
||||
if (settingsKeys.contains("title") || force) {
|
||||
ostr << " m_title: " << m_title.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("streamIndex") || force) {
|
||||
ostr << " m_streamIndex: " << m_streamIndex;
|
||||
}
|
||||
if (settingsKeys.contains("useReverseAPI") || force) {
|
||||
ostr << " m_useReverseAPI: " << m_useReverseAPI;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIAddress") || force) {
|
||||
ostr << " m_reverseAPIAddress: " << m_reverseAPIAddress.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIPort") || force) {
|
||||
ostr << " m_reverseAPIPort: " << m_reverseAPIPort;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIDeviceIndex") || force) {
|
||||
ostr << " m_reverseAPIDeviceIndex: " << m_reverseAPIDeviceIndex;
|
||||
}
|
||||
if (settingsKeys.contains("reverseAPIChannelIndex") || force) {
|
||||
ostr << " m_reverseAPIChannelIndex: " << m_reverseAPIChannelIndex;
|
||||
}
|
||||
if (settingsKeys.contains("workspaceIndex") || force) {
|
||||
ostr << " m_workspaceIndex: " << m_workspaceIndex;
|
||||
}
|
||||
if (settingsKeys.contains("hidden") || force) {
|
||||
ostr << " m_hidden: " << m_hidden;
|
||||
}
|
||||
if (settingsKeys.contains("columnIndexes") || force) {
|
||||
// Don't display
|
||||
}
|
||||
if (settingsKeys.contains("columnSizes") || force) {
|
||||
// Don't display
|
||||
}
|
||||
|
||||
return QString(ostr.str().c_str());
|
||||
}
|
79
plugins/channelrx/demodendoftrain/endoftraindemodsettings.h
Normal file
79
plugins/channelrx/demodendoftrain/endoftraindemodsettings.h
Normal file
@ -0,0 +1,79 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
||||
// written by Christian Daniel //
|
||||
// Copyright (C) 2015-2019, 2021-2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// Copyright (C) 2021-2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// //
|
||||
// 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_ENDOFTRAINDEMODSETTINGS_H
|
||||
#define INCLUDE_ENDOFTRAINDEMODSETTINGS_H
|
||||
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
|
||||
#include "dsp/dsptypes.h"
|
||||
|
||||
class Serializable;
|
||||
|
||||
// Number of columns in the table
|
||||
#define ENDOFTRAINDEMOD_COLUMNS 18
|
||||
|
||||
struct EndOfTrainDemodSettings
|
||||
{
|
||||
qint32 m_inputFrequencyOffset;
|
||||
Real m_rfBandwidth;
|
||||
Real m_fmDeviation;
|
||||
QString m_filterFrom;
|
||||
bool m_udpEnabled;
|
||||
QString m_udpAddress;
|
||||
uint16_t m_udpPort;
|
||||
QString m_logFilename;
|
||||
bool m_logEnabled;
|
||||
bool m_useFileTime;
|
||||
|
||||
quint32 m_rgbColor;
|
||||
QString m_title;
|
||||
Serializable *m_channelMarker;
|
||||
int m_streamIndex; //!< MIMO channel. Not relevant when connected to SI (single Rx).
|
||||
bool m_useReverseAPI;
|
||||
QString m_reverseAPIAddress;
|
||||
uint16_t m_reverseAPIPort;
|
||||
uint16_t m_reverseAPIDeviceIndex;
|
||||
uint16_t m_reverseAPIChannelIndex;
|
||||
|
||||
Serializable *m_rollupState;
|
||||
int m_workspaceIndex;
|
||||
QByteArray m_geometryBytes;
|
||||
bool m_hidden;
|
||||
|
||||
QList<int> m_columnIndexes; //!< How the columns are ordered in the table
|
||||
QList<int> m_columnSizes; //!< Size of the columns in the table
|
||||
|
||||
static const int CHANNEL_SAMPLE_RATE = 48000; // Must be integer multiple of baud rate
|
||||
static const int BAUD_RATE = 1200;
|
||||
static const int m_scopeStreams = 9;
|
||||
|
||||
EndOfTrainDemodSettings();
|
||||
void resetToDefaults();
|
||||
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
|
||||
void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; }
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
void applySettings(const QStringList& settingsKeys, const EndOfTrainDemodSettings& settings);
|
||||
QString getDebugString(const QStringList& settingsKeys, bool force = false) const;
|
||||
};
|
||||
|
||||
#endif /* INCLUDE_ENDOFTRAINDEMODSETTINGS_H */
|
366
plugins/channelrx/demodendoftrain/endoftraindemodsink.cpp
Normal file
366
plugins/channelrx/demodendoftrain/endoftraindemodsink.cpp
Normal file
@ -0,0 +1,366 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2021-2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// Copyright (C) 2021-2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/datafifo.h"
|
||||
#include "device/deviceapi.h"
|
||||
#include "util/db.h"
|
||||
#include "channel/channelwebapiutils.h"
|
||||
#include "maincore.h"
|
||||
|
||||
#include "endoftraindemod.h"
|
||||
#include "endoftraindemodsink.h"
|
||||
|
||||
EndOfTrainDemodSink::EndOfTrainDemodSink(EndOfTrainDemod *endoftrainDemod) :
|
||||
m_scopeSink(nullptr),
|
||||
m_endoftrainDemod(endoftrainDemod),
|
||||
m_channelSampleRate(EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE),
|
||||
m_channelFrequencyOffset(0),
|
||||
m_magsqSum(0.0f),
|
||||
m_magsqPeak(0.0f),
|
||||
m_magsqCount(0),
|
||||
m_messageQueueToChannel(nullptr),
|
||||
m_f1(nullptr),
|
||||
m_f0(nullptr),
|
||||
m_corrBuf(nullptr),
|
||||
m_corrIdx(0),
|
||||
m_corrCnt(0),
|
||||
m_sampleBufferIndex(0)
|
||||
{
|
||||
m_magsq = 0.0;
|
||||
|
||||
m_demodBuffer.resize(1<<12);
|
||||
m_demodBufferFill = 0;
|
||||
for (int i = 0; i < EndOfTrainDemodSettings::m_scopeStreams; i++) {
|
||||
m_sampleBuffer[i].resize(m_sampleBufferSize);
|
||||
}
|
||||
|
||||
applySettings(m_settings, QStringList(), true);
|
||||
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
||||
}
|
||||
|
||||
EndOfTrainDemodSink::~EndOfTrainDemodSink()
|
||||
{
|
||||
delete[] m_f1;
|
||||
delete[] m_f0;
|
||||
delete[] m_corrBuf;
|
||||
}
|
||||
|
||||
void EndOfTrainDemodSink::sampleToScope(Complex sample, Real s1, Real s2, Real s3, Real s4, Real s5, Real s6, Real s7, Real s8)
|
||||
{
|
||||
if (m_scopeSink)
|
||||
{
|
||||
m_sampleBuffer[0][m_sampleBufferIndex] = sample;
|
||||
m_sampleBuffer[1][m_sampleBufferIndex] = Complex(s1, 0.0f);
|
||||
m_sampleBuffer[2][m_sampleBufferIndex] = Complex(s2, 0.0f);
|
||||
m_sampleBuffer[3][m_sampleBufferIndex] = Complex(s3, 0.0f);
|
||||
m_sampleBuffer[4][m_sampleBufferIndex] = Complex(s4, 0.0f);
|
||||
m_sampleBuffer[5][m_sampleBufferIndex] = Complex(s5, 0.0f);
|
||||
m_sampleBuffer[6][m_sampleBufferIndex] = Complex(s6, 0.0f);
|
||||
m_sampleBuffer[7][m_sampleBufferIndex] = Complex(s7, 0.0f);
|
||||
m_sampleBuffer[8][m_sampleBufferIndex] = Complex(s8, 0.0f);
|
||||
m_sampleBufferIndex++;
|
||||
if (m_sampleBufferIndex == m_sampleBufferSize)
|
||||
{
|
||||
std::vector<ComplexVector::const_iterator> vbegin;
|
||||
|
||||
for (int i = 0; i < EndOfTrainDemodSettings::m_scopeStreams; i++) {
|
||||
vbegin.push_back(m_sampleBuffer[i].begin());
|
||||
}
|
||||
|
||||
m_scopeSink->feed(vbegin, m_sampleBufferSize);
|
||||
m_sampleBufferIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemodSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
|
||||
{
|
||||
Complex ci;
|
||||
|
||||
for (SampleVector::const_iterator it = begin; it != end; ++it)
|
||||
{
|
||||
Complex c(it->real(), it->imag());
|
||||
c *= m_nco.nextIQ();
|
||||
|
||||
if (m_interpolatorDistance < 1.0f) // interpolate
|
||||
{
|
||||
while (!m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci))
|
||||
{
|
||||
processOneSample(ci);
|
||||
m_interpolatorDistanceRemain += m_interpolatorDistance;
|
||||
}
|
||||
}
|
||||
else // decimate
|
||||
{
|
||||
if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci))
|
||||
{
|
||||
processOneSample(ci);
|
||||
m_interpolatorDistanceRemain += m_interpolatorDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemodSink::processOneSample(Complex &ci)
|
||||
{
|
||||
Complex ca;
|
||||
|
||||
// FM demodulation
|
||||
double magsqRaw;
|
||||
Real deviation;
|
||||
Real fmDemod = m_phaseDiscri.phaseDiscriminatorDelta(ci, magsqRaw, deviation);
|
||||
|
||||
// Calculate average and peak levels for level meter
|
||||
Real magsq = magsqRaw / (SDR_RX_SCALED*SDR_RX_SCALED);
|
||||
m_movingAverage(magsq);
|
||||
m_magsq = m_movingAverage.asDouble();
|
||||
m_magsqSum += magsq;
|
||||
if (magsq > m_magsqPeak)
|
||||
{
|
||||
m_magsqPeak = magsq;
|
||||
}
|
||||
m_magsqCount++;
|
||||
|
||||
Real f0Filt = 0.0f;
|
||||
Real f1Filt = 0.0f;
|
||||
float diff = 0.0;
|
||||
int sample = 0;
|
||||
int bit = 0;
|
||||
|
||||
m_corrBuf[m_corrIdx] = fmDemod;
|
||||
if (m_corrCnt >= m_correlationLength)
|
||||
{
|
||||
// Correlate with 1200 + 1800 baud complex exponentials
|
||||
Complex corrF0 = 0.0f;
|
||||
Complex corrF1 = 0.0f;
|
||||
for (int i = 0; i < m_correlationLength; i++)
|
||||
{
|
||||
int j = m_corrIdx - i;
|
||||
if (j < 0)
|
||||
j += m_correlationLength;
|
||||
corrF0 += m_f0[i] * m_corrBuf[j];
|
||||
corrF1 += m_f1[i] * m_corrBuf[j];
|
||||
}
|
||||
m_corrCnt--; // Avoid overflow in increment below
|
||||
|
||||
// Low pass filter, to minimize changes above the baud rate
|
||||
f0Filt = m_lowpassF0.filter(std::abs(corrF0));
|
||||
f1Filt = m_lowpassF1.filter(std::abs(corrF1));
|
||||
|
||||
// Determine which is the closest match and then quantise to 1 or -1
|
||||
diff = f1Filt - f0Filt;
|
||||
sample = diff >= 0.0f ? 1 : 0;
|
||||
|
||||
// Look for edge
|
||||
if (sample != m_samplePrev)
|
||||
{
|
||||
m_syncCount = EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE/EndOfTrainDemodSettings::BAUD_RATE/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_syncCount--;
|
||||
if (m_syncCount <= 0)
|
||||
{
|
||||
bit = sample;
|
||||
|
||||
// Store in shift reg - LSB first
|
||||
m_bits |= bit << m_bitCount;
|
||||
|
||||
m_bitCount++;
|
||||
|
||||
if (!m_gotSOP)
|
||||
{
|
||||
if (m_bitCount >= 17)
|
||||
{
|
||||
// Look for frame sync
|
||||
if ((m_bits & 0x1ffff) == 0x91D5)
|
||||
{
|
||||
// Start of packet
|
||||
m_gotSOP = true;
|
||||
m_bits = 0;
|
||||
m_bitCount = 0;
|
||||
m_byteCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bitCount--;
|
||||
m_bits >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_bitCount == 8)
|
||||
{
|
||||
if (m_byteCount == 8)
|
||||
{
|
||||
QByteArray rxPacket((char *)m_bytes, m_byteCount);
|
||||
//qDebug() << "RX: " << rxPacket.toHex();
|
||||
if (getMessageQueueToChannel())
|
||||
{
|
||||
QDateTime dateTime = QDateTime::currentDateTime();
|
||||
if (m_settings.m_useFileTime)
|
||||
{
|
||||
QString hardwareId = m_endoftrainDemod->getDeviceAPI()->getHardwareId();
|
||||
|
||||
if ((hardwareId == "FileInput") || (hardwareId == "SigMFFileInput"))
|
||||
{
|
||||
QString dateTimeStr;
|
||||
int deviceIdx = m_endoftrainDemod->getDeviceSetIndex();
|
||||
|
||||
if (ChannelWebAPIUtils::getDeviceReportValue(deviceIdx, "absoluteTime", dateTimeStr)) {
|
||||
dateTime = QDateTime::fromString(dateTimeStr, Qt::ISODateWithMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MainCore::MsgPacket *msg = MainCore::MsgPacket::create(m_endoftrainDemod, rxPacket, dateTime);
|
||||
getMessageQueueToChannel()->push(msg);
|
||||
}
|
||||
// Reset state to start receiving next packet
|
||||
m_gotSOP = false;
|
||||
m_bits = 0;
|
||||
m_bitCount = 0;
|
||||
m_byteCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bytes[m_byteCount] = m_bits;
|
||||
m_byteCount++;
|
||||
}
|
||||
m_bits = 0;
|
||||
m_bitCount = 0;
|
||||
}
|
||||
}
|
||||
m_syncCount = EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE/EndOfTrainDemodSettings::BAUD_RATE;
|
||||
}
|
||||
}
|
||||
m_samplePrev = sample;
|
||||
}
|
||||
m_corrIdx = (m_corrIdx + 1) % m_correlationLength;
|
||||
m_corrCnt++;
|
||||
|
||||
// Select signals to feed to scope
|
||||
sampleToScope(ci / SDR_RX_SCALEF, magsq, fmDemod, f0Filt, f1Filt, diff, sample, bit, m_gotSOP);
|
||||
|
||||
// Send demod signal to Demod Analzyer feature
|
||||
m_demodBuffer[m_demodBufferFill++] = fmDemod * std::numeric_limits<int16_t>::max();
|
||||
|
||||
if (m_demodBufferFill >= m_demodBuffer.size())
|
||||
{
|
||||
QList<ObjectPipe*> dataPipes;
|
||||
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
|
||||
|
||||
if (dataPipes.size() > 0)
|
||||
{
|
||||
QList<ObjectPipe*>::iterator it = dataPipes.begin();
|
||||
|
||||
for (; it != dataPipes.end(); ++it)
|
||||
{
|
||||
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
|
||||
|
||||
if (fifo) {
|
||||
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_demodBufferFill = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfTrainDemodSink::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force)
|
||||
{
|
||||
qDebug() << "EndOfTrainDemodSink::applyChannelSettings:"
|
||||
<< " channelSampleRate: " << channelSampleRate
|
||||
<< " channelFrequencyOffset: " << channelFrequencyOffset;
|
||||
|
||||
if ((m_channelFrequencyOffset != channelFrequencyOffset) ||
|
||||
(m_channelSampleRate != channelSampleRate) || force)
|
||||
{
|
||||
m_nco.setFreq(-channelFrequencyOffset, channelSampleRate);
|
||||
}
|
||||
|
||||
if ((m_channelSampleRate != channelSampleRate) || force)
|
||||
{
|
||||
m_interpolator.create(16, channelSampleRate, m_settings.m_rfBandwidth / 2.2);
|
||||
m_interpolatorDistance = (Real) channelSampleRate / (Real) EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE;
|
||||
m_interpolatorDistanceRemain = m_interpolatorDistance;
|
||||
}
|
||||
|
||||
m_channelSampleRate = channelSampleRate;
|
||||
m_channelFrequencyOffset = channelFrequencyOffset;
|
||||
}
|
||||
|
||||
void EndOfTrainDemodSink::applySettings(const EndOfTrainDemodSettings& settings, const QStringList& settingsKeys, bool force)
|
||||
{
|
||||
qDebug() << "EndOfTrainDemodSink::applySettings:"
|
||||
<< settings.getDebugString(settingsKeys, force)
|
||||
<< " force: " << force;
|
||||
|
||||
if (settingsKeys.contains("rfBandwidth") || force)
|
||||
{
|
||||
m_interpolator.create(16, m_channelSampleRate, settings.m_rfBandwidth / 2.2);
|
||||
m_interpolatorDistance = (Real) m_channelSampleRate / (Real) EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE;
|
||||
m_interpolatorDistanceRemain = m_interpolatorDistance;
|
||||
}
|
||||
if (settingsKeys.contains("fmDeviation") || force)
|
||||
{
|
||||
m_phaseDiscri.setFMScaling(EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE / (2.0f * settings.m_fmDeviation));
|
||||
}
|
||||
|
||||
if (force)
|
||||
{
|
||||
delete[] m_f1;
|
||||
delete[] m_f0;
|
||||
delete[] m_corrBuf;
|
||||
m_correlationLength = EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE/EndOfTrainDemodSettings::BAUD_RATE;
|
||||
m_f1 = new Complex[m_correlationLength]();
|
||||
m_f0 = new Complex[m_correlationLength]();
|
||||
m_corrBuf = new Complex[m_correlationLength]();
|
||||
m_corrIdx = 0;
|
||||
m_corrCnt = 0;
|
||||
Real f0 = 0.0f;
|
||||
Real f1 = 0.0f;
|
||||
for (int i = 0; i < m_correlationLength; i++)
|
||||
{
|
||||
m_f0[i] = Complex(cos(f0), sin(f0));
|
||||
m_f1[i] = Complex(cos(f1), sin(f1));
|
||||
f0 += 2.0f*(Real)M_PI*1800.0f/EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE;
|
||||
f1 += 2.0f*(Real)M_PI*1200.0f/EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE;
|
||||
}
|
||||
|
||||
m_lowpassF1.create(301, EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE, EndOfTrainDemodSettings::BAUD_RATE * 1.1f);
|
||||
m_lowpassF0.create(301, EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE, EndOfTrainDemodSettings::BAUD_RATE * 1.1f);
|
||||
m_samplePrev = 0;
|
||||
m_syncCount = 0;
|
||||
m_bits = 0;
|
||||
m_bitCount = 0;
|
||||
m_gotSOP = false;
|
||||
m_byteCount = 0;
|
||||
}
|
||||
|
||||
if (force) {
|
||||
m_settings = settings;
|
||||
} else {
|
||||
m_settings.applySettings(settingsKeys, settings);
|
||||
}
|
||||
}
|
138
plugins/channelrx/demodendoftrain/endoftraindemodsink.h
Normal file
138
plugins/channelrx/demodendoftrain/endoftraindemodsink.h
Normal file
@ -0,0 +1,138 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2019-2021 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// Copyright (C) 2020-2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// Copyright (C) 2020 Kacper Michajłow <kasper93@gmail.com> //
|
||||
// //
|
||||
// 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_ENDOFTRAINDEMODSINK_H
|
||||
#define INCLUDE_ENDOFTRAINDEMODSINK_H
|
||||
|
||||
#include <QVector>
|
||||
|
||||
#include "dsp/channelsamplesink.h"
|
||||
#include "dsp/phasediscri.h"
|
||||
#include "dsp/nco.h"
|
||||
#include "dsp/interpolator.h"
|
||||
#include "dsp/firfilter.h"
|
||||
#include "util/movingaverage.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
#include "endoftraindemodsettings.h"
|
||||
|
||||
class ChannelAPI;
|
||||
class EndOfTrainDemod;
|
||||
class ScopeVis;
|
||||
|
||||
class EndOfTrainDemodSink : public ChannelSampleSink {
|
||||
public:
|
||||
EndOfTrainDemodSink(EndOfTrainDemod *endoftrainDemod);
|
||||
~EndOfTrainDemodSink();
|
||||
|
||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
|
||||
|
||||
void setScopeSink(ScopeVis* scopeSink) { m_scopeSink = scopeSink; }
|
||||
void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false);
|
||||
void applySettings(const EndOfTrainDemodSettings& settings, const QStringList& settingsKeys, bool force = false);
|
||||
void setMessageQueueToChannel(MessageQueue *messageQueue) { m_messageQueueToChannel = messageQueue; }
|
||||
void setChannel(ChannelAPI *channel) { m_channel = channel; }
|
||||
|
||||
double getMagSq() const { return m_magsq; }
|
||||
|
||||
void getMagSqLevels(double& avg, double& peak, int& nbSamples)
|
||||
{
|
||||
if (m_magsqCount > 0)
|
||||
{
|
||||
m_magsq = m_magsqSum / m_magsqCount;
|
||||
m_magSqLevelStore.m_magsq = m_magsq;
|
||||
m_magSqLevelStore.m_magsqPeak = m_magsqPeak;
|
||||
}
|
||||
|
||||
avg = m_magSqLevelStore.m_magsq;
|
||||
peak = m_magSqLevelStore.m_magsqPeak;
|
||||
nbSamples = m_magsqCount == 0 ? 1 : m_magsqCount;
|
||||
|
||||
m_magsqSum = 0.0f;
|
||||
m_magsqPeak = 0.0f;
|
||||
m_magsqCount = 0;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
struct MagSqLevelsStore
|
||||
{
|
||||
MagSqLevelsStore() :
|
||||
m_magsq(1e-12),
|
||||
m_magsqPeak(1e-12)
|
||||
{}
|
||||
double m_magsq;
|
||||
double m_magsqPeak;
|
||||
};
|
||||
|
||||
ScopeVis* m_scopeSink; // Scope GUI to display baseband waveform
|
||||
EndOfTrainDemod *m_endoftrainDemod;
|
||||
EndOfTrainDemodSettings m_settings;
|
||||
ChannelAPI *m_channel;
|
||||
int m_channelSampleRate;
|
||||
int m_channelFrequencyOffset;
|
||||
|
||||
NCO m_nco;
|
||||
Interpolator m_interpolator;
|
||||
Real m_interpolatorDistance;
|
||||
Real m_interpolatorDistanceRemain;
|
||||
|
||||
double m_magsq;
|
||||
double m_magsqSum;
|
||||
double m_magsqPeak;
|
||||
int m_magsqCount;
|
||||
MagSqLevelsStore m_magSqLevelStore;
|
||||
|
||||
MessageQueue *m_messageQueueToChannel;
|
||||
|
||||
MovingAverageUtil<Real, double, 16> m_movingAverage;
|
||||
|
||||
PhaseDiscriminators m_phaseDiscri;
|
||||
|
||||
int m_correlationLength;
|
||||
Complex *m_f1;
|
||||
Complex *m_f0;
|
||||
Complex *m_corrBuf;
|
||||
int m_corrIdx;
|
||||
int m_corrCnt;
|
||||
|
||||
Lowpass<Real> m_lowpassF1;
|
||||
Lowpass<Real> m_lowpassF0;
|
||||
|
||||
int m_samplePrev;
|
||||
int m_syncCount;
|
||||
quint32 m_bits;
|
||||
int m_bitCount;
|
||||
bool m_gotSOP;
|
||||
unsigned char m_bytes[8];
|
||||
int m_byteCount;
|
||||
|
||||
QVector<qint16> m_demodBuffer;
|
||||
int m_demodBufferFill;
|
||||
|
||||
ComplexVector m_sampleBuffer[EndOfTrainDemodSettings::m_scopeStreams];
|
||||
static const int m_sampleBufferSize = EndOfTrainDemodSettings::CHANNEL_SAMPLE_RATE / 20;
|
||||
int m_sampleBufferIndex;
|
||||
|
||||
void processOneSample(Complex &ci);
|
||||
MessageQueue *getMessageQueueToChannel() { return m_messageQueueToChannel; }
|
||||
void sampleToScope(Complex sample, Real s1, Real s2, Real s3, Real s4, Real s5, Real s6, Real s7, Real s8);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_ENDOFTRAINDEMODSINK_H
|
@ -0,0 +1,54 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
||||
// written by Christian Daniel //
|
||||
// Copyright (C) 2015-2020 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// Copyright (C) 2021-2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// //
|
||||
// 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 "endoftraindemod.h"
|
||||
#include "endoftraindemodwebapiadapter.h"
|
||||
|
||||
EndOfTrainDemodWebAPIAdapter::EndOfTrainDemodWebAPIAdapter()
|
||||
{}
|
||||
|
||||
EndOfTrainDemodWebAPIAdapter::~EndOfTrainDemodWebAPIAdapter()
|
||||
{}
|
||||
|
||||
int EndOfTrainDemodWebAPIAdapter::webapiSettingsGet(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) errorMessage;
|
||||
response.setEndOfTrainDemodSettings(new SWGSDRangel::SWGEndOfTrainDemodSettings());
|
||||
response.getEndOfTrainDemodSettings()->init();
|
||||
EndOfTrainDemod::webapiFormatChannelSettings(response, m_settings);
|
||||
|
||||
return 200;
|
||||
}
|
||||
|
||||
int EndOfTrainDemodWebAPIAdapter::webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) force;
|
||||
(void) errorMessage;
|
||||
EndOfTrainDemod::webapiUpdateChannelSettings(m_settings, channelSettingsKeys, response);
|
||||
|
||||
return 200;
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2019 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// Copyright (C) 2020-2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// //
|
||||
// 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_ENDOFTRAINDEMOD_WEBAPIADAPTER_H
|
||||
#define INCLUDE_ENDOFTRAINDEMOD_WEBAPIADAPTER_H
|
||||
|
||||
#include "channel/channelwebapiadapter.h"
|
||||
#include "endoftraindemodsettings.h"
|
||||
|
||||
/**
|
||||
* Standalone API adapter only for the settings
|
||||
*/
|
||||
class EndOfTrainDemodWebAPIAdapter : public ChannelWebAPIAdapter {
|
||||
public:
|
||||
EndOfTrainDemodWebAPIAdapter();
|
||||
virtual ~EndOfTrainDemodWebAPIAdapter();
|
||||
|
||||
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:
|
||||
EndOfTrainDemodSettings m_settings;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_ENDOFTRAINDEMOD_WEBAPIADAPTER_H
|
99
plugins/channelrx/demodendoftrain/endoftrainpacket.cpp
Normal file
99
plugins/channelrx/demodendoftrain/endoftrainpacket.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// Copyright (C) 2018 Eric Reuter //
|
||||
// //
|
||||
// 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 "endoftrainpacket.h"
|
||||
|
||||
#include "util/crc.h"
|
||||
|
||||
// Reverse order of bits
|
||||
static quint32 reverse(quint32 x)
|
||||
{
|
||||
x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
|
||||
x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
|
||||
x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
|
||||
x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
|
||||
return((x >> 16) | (x << 16));
|
||||
}
|
||||
|
||||
// Reverse order of bits, for specified number of bits
|
||||
static quint32 reverseBits(quint32 x, int bits)
|
||||
{
|
||||
return reverse(x) >> (32-bits);
|
||||
}
|
||||
|
||||
// Decode end-of-train packet
|
||||
// Defined in:
|
||||
// AAR MSRP (Manual of Standards and Recommended Practices) - Section K Part II Locomotive Electronics and Train Consist System Architecture - S-9152 End of Train Communication
|
||||
// but not readily available, so see:
|
||||
// https://patents.google.com/patent/US5374015A/en
|
||||
// https://rdso.indianrailways.gov.in/uploads/files/TC0156_15_02_2022.pdf
|
||||
|
||||
bool EndOfTrainPacket::decode(const QByteArray& packet)
|
||||
{
|
||||
//qDebug() << packet.toHex();
|
||||
|
||||
if (packet.size() != 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_chainingBits = packet[0] & 0x3;
|
||||
|
||||
m_batteryCondition = (packet[0] >> 2) & 0x3;
|
||||
|
||||
m_type = (packet[0] >> 4) & 0x7;
|
||||
|
||||
m_address = ((packet[2] & 0xff) << 9) | ((packet[1] & 0xff) << 1) | ((packet[0] >> 7) & 0x1);
|
||||
|
||||
m_pressure = packet[3] & 0x7f;
|
||||
|
||||
m_discretionary = (packet[3] >> 7) & 1;
|
||||
|
||||
m_batteryCharge = packet[4] & 0x7f;
|
||||
|
||||
m_valveCircuitStatus = (packet[4] >> 7) & 1;
|
||||
|
||||
m_confirmation = packet[5] & 1;
|
||||
m_turbine = (packet[5] >> 1) & 1;
|
||||
m_motion = (packet[5] >> 2) & 1;
|
||||
m_markerLightBatteryCondition = (packet[5] >> 3) & 1;
|
||||
m_markerLightStatus = (packet[5] >> 4) & 1;
|
||||
|
||||
// Calculate and compare CRC
|
||||
|
||||
crc crc18(18, 0x39A0F, true, 0, 0x2b770);
|
||||
|
||||
// 45-bits are protected
|
||||
crc18.calculate(packet[5] & 0x1f, 5);
|
||||
crc18.calculate(packet[4] & 0xff, 8);
|
||||
crc18.calculate(packet[3] & 0xff, 8);
|
||||
crc18.calculate(packet[2] & 0xff, 8);
|
||||
crc18.calculate(packet[1] & 0xff, 8);
|
||||
crc18.calculate(packet[0] & 0xff, 8);
|
||||
|
||||
m_crc = ((packet[7] & 0xff) << 11) | ((packet[6] & 0xff) << 3) | ((packet[5] >> 5) & 0x7);
|
||||
m_crcCalculated = reverseBits(crc18.get(), 18);
|
||||
m_crcValid = m_crc == m_crcCalculated;
|
||||
|
||||
if (crc18.get() != m_crc) {
|
||||
qDebug() << "CRC Mismatch: " << QString::number(crc18.get(), 16) << QString::number(m_crc, 16);
|
||||
}
|
||||
|
||||
m_dataHex = QString(packet.toHex());
|
||||
|
||||
return m_crcValid;
|
||||
}
|
98
plugins/channelrx/demodendoftrain/endoftrainpacket.h
Normal file
98
plugins/channelrx/demodendoftrain/endoftrainpacket.h
Normal file
@ -0,0 +1,98 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2024 Jon Beniston, M7RCE <jon@beniston.com> //
|
||||
// Copyright (C) 2018 Eric Reuter //
|
||||
// //
|
||||
// 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_ENDOFTRAINPACKET_H
|
||||
#define INCLUDE_ENDOFTRAINPACKET_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
|
||||
struct EndOfTrainPacket {
|
||||
|
||||
int m_chainingBits;
|
||||
int m_batteryCondition; // Device battery status
|
||||
int m_type; // Message type identifier
|
||||
int m_address; // EOT unit address
|
||||
int m_pressure; // Rear brake pressure PSIG
|
||||
int m_batteryCharge; // Battery charge
|
||||
bool m_discretionary; // Used differently by different vendors
|
||||
bool m_valveCircuitStatus;
|
||||
bool m_confirmation;
|
||||
bool m_turbine;
|
||||
bool m_motion; // Whether train is in motion
|
||||
bool m_markerLightBatteryCondition; // Condition of marker light battery
|
||||
bool m_markerLightStatus; // Whether light is on or off
|
||||
quint32 m_crc;
|
||||
quint32 m_crcCalculated;
|
||||
bool m_crcValid;
|
||||
|
||||
QString m_dataHex;
|
||||
|
||||
bool decode(const QByteArray& packet);
|
||||
|
||||
QString getMessageType() const
|
||||
{
|
||||
return QString::number(m_type);
|
||||
}
|
||||
|
||||
QString getBatteryCondition() const
|
||||
{
|
||||
const QStringList batteryConditions = {"N/A", "Very Low", "Low", "OK"};
|
||||
return batteryConditions[m_batteryCondition];
|
||||
}
|
||||
|
||||
QString getValveCircuitStatus() const
|
||||
{
|
||||
return m_valveCircuitStatus ? "OK" : "Fail";
|
||||
}
|
||||
|
||||
QString getMarkerLightBatteryCondition() const
|
||||
{
|
||||
return m_markerLightBatteryCondition ? "Low" : "Ok";
|
||||
}
|
||||
|
||||
QString getMarkerLightStatus() const
|
||||
{
|
||||
return m_markerLightStatus ? "On" : "Off";
|
||||
}
|
||||
|
||||
float getBatteryChargePercent() const
|
||||
{
|
||||
return 100.0f * m_batteryCharge / 127.0f;
|
||||
}
|
||||
|
||||
QString getArmStatus() const
|
||||
{
|
||||
if (m_type == 7)
|
||||
{
|
||||
if (m_confirmation == 0) {
|
||||
return "Arming";
|
||||
} else {
|
||||
return "Armed";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Normal";
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // INCLUDE_ENDOFTRAINPACKET_H
|
107
plugins/channelrx/demodendoftrain/readme.md
Normal file
107
plugins/channelrx/demodendoftrain/readme.md
Normal file
@ -0,0 +1,107 @@
|
||||
<h1>End-of-Train Demodulator Plugin</h1>
|
||||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
This plugin can be used to demodulate End-of-Train packets. These are packets transmitted by an [End-of-Train Device](https://en.wikipedia.org/wiki/End-of-train_device),
|
||||
that can be found on some trains.
|
||||
It transmits information about whether motion is detected, brake pressue, whether the marker light is on and battery information.
|
||||
|
||||
* Frequency: 457.9375 MHz (North America, India), 477.7 MHz (Australia) and 450.2625 MHz (New Zealand).
|
||||
* Modulation: FSK, 1800Hz space, 1200 mark, +-3kHz deviation.
|
||||
* Baud rate: 1200 baud.
|
||||
|
||||
The End-of-train packet specification is defined in:
|
||||
AAR Manual of Standards and Recommended Practices - S-9152 End of Train Communication - Section K Part II Locomotive Electronics and Train Consist System Architecture.
|
||||
If anyone has a copy, please get in touch.
|
||||
|
||||
<h2>Interface</h2>
|
||||
|
||||
The top and bottom bars of the channel window are described [here](../../../sdrgui/channel/readme.md)
|
||||
|
||||

|
||||
|
||||
<h3>1: Frequency shift from center frequency of reception</h3>
|
||||
|
||||
Use the wheels to adjust the frequency shift in Hz from the center frequency of reception. Left click on a digit sets the cursor position at this digit. Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position. Wheels are moved with the mousewheel while pointing at the wheel or by selecting the wheel with the left mouse click and using the keyboard arrows. Pressing shift simultaneously moves digit by 5 and pressing control moves it by 2.
|
||||
|
||||
<h3>2: Channel power</h3>
|
||||
|
||||
Average total power in dB relative to a +/- 1.0 amplitude signal received in the pass band.
|
||||
|
||||
<h3>3: Level meter in dB</h3>
|
||||
|
||||
- top bar (green): average value
|
||||
- bottom bar (blue green): instantaneous peak value
|
||||
- tip vertical bar (bright green): peak hold value
|
||||
|
||||
<h3>4: RF Bandwidth</h3>
|
||||
|
||||
This specifies the bandwidth of a LPF that is applied to the input signal to limit the RF bandwidth.
|
||||
|
||||
<h3>5: Frequency deviation</h3>
|
||||
|
||||
Adjusts the expected frequency deviation in 0.1 kHz steps from 1 to 6 kHz. Typical value is 3 kHz.
|
||||
|
||||
<h3>6: Filter Address</h3>
|
||||
|
||||
Entering a regular expression in the field displays only packets where the unit address matches the regular expression.
|
||||
|
||||
<h3>7: UDP</h3>
|
||||
|
||||
When checked, received packets are forwarded to the specified UDP address (8) and port (9).
|
||||
|
||||
<h3>8: UDP address</h3>
|
||||
|
||||
IP address of the host to forward received packets to via UDP.
|
||||
|
||||
<h3>9: UDP port</h3>
|
||||
|
||||
UDP port number to forward received packets to.
|
||||
|
||||
<h3>10: Use Date and Time from File</h3>
|
||||
|
||||
When checked, if the source device is a File Input device, the date and time used for
|
||||
packet reception time is taken from the file playback time. Otherwise, the current system clock time is used.
|
||||
|
||||
<h3>11: Start/stop Logging Packets to .csv File</h3>
|
||||
|
||||
When checked, writes all received packets to a .csv file. The filename is specified by (12).
|
||||
|
||||
<h3>12: .csv Log Filename</h3>
|
||||
|
||||
Click to specify the name of the .csv file which received packets are logged to.
|
||||
|
||||
<h3>13: Read Data from .csv File</h3>
|
||||
|
||||
Click to specify a previously written .csv log file, which is read and used to update the table.
|
||||
|
||||
<h3>14: Clear table</h3>
|
||||
|
||||
Pressing this button clears all packets from the table.
|
||||
|
||||
<h3>Received Packets Table</h3>
|
||||
|
||||
The received packets table displays the contents of the packets that have been received. Only packets with valid CRCs are displayed.
|
||||
|
||||
* Date - Date the packet was received.
|
||||
* Time - Time the packet was received.
|
||||
* Battery condition - Whether the battery charge is OK, low, very low or not monitored (N/A).
|
||||
* Type - Message type identifier.
|
||||
* Address - Unit address, which uniquely identifies the end-of-train unit.
|
||||
* Pressure - Brake pipe pressure in Pounds per Square Inch Gauge (PSIG).
|
||||
* Charge - Battery charge in percent.
|
||||
* Disc - Discretionary bit that is used for varying data by different vendors.
|
||||
* Valve - Valve circuit status (Ok or Fail).
|
||||
* Conf - Confirmation indicator.
|
||||
* Turbine - Air tubine equiped.
|
||||
* Motion - Whether motion is detected (i.e. is the rear of the train is moving).
|
||||
* Light Batt - Marker light battery condition (Ok or Low).
|
||||
* Light - Marker light status (On or off).
|
||||
* CRC - Whether the calculated CRC matches the received CRC.
|
||||
* Hex - The packet data displayed as hexadecimal.
|
||||
|
||||
<h2>Attribution</h2>
|
||||
|
||||
Based on code and reverse engineering by Eric Reuter
|
||||
|
||||
Clock icons created by Pixel perfect from Flaticon https:://www.flaticon.com
|
@ -297,6 +297,9 @@ void PacketDemod::applySettings(const PacketDemodSettings& settings, bool force)
|
||||
if ((settings.m_logEnabled != m_settings.m_logEnabled) || force) {
|
||||
reverseAPIKeys.append("logEnabled");
|
||||
}
|
||||
if ((settings.m_useFileTime != m_settings.m_useFileTime) || force) {
|
||||
reverseAPIKeys.append("useFileTime");
|
||||
}
|
||||
if (m_settings.m_streamIndex != settings.m_streamIndex)
|
||||
{
|
||||
if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only
|
||||
@ -482,10 +485,13 @@ void PacketDemod::webapiUpdateChannelSettings(
|
||||
settings.m_udpPort = response.getPacketDemodSettings()->getUdpPort();
|
||||
}
|
||||
if (channelSettingsKeys.contains("logFilename")) {
|
||||
settings.m_logFilename = *response.getAdsbDemodSettings()->getLogFilename();
|
||||
settings.m_logFilename = *response.getPacketDemodSettings()->getLogFilename();
|
||||
}
|
||||
if (channelSettingsKeys.contains("logEnabled")) {
|
||||
settings.m_logEnabled = response.getAdsbDemodSettings()->getLogEnabled();
|
||||
settings.m_logEnabled = response.getPacketDemodSettings()->getLogEnabled();
|
||||
}
|
||||
if (channelSettingsKeys.contains("useFileTime")) {
|
||||
settings.m_useFileTime = response.getPacketDemodSettings()->getUseFileTime();
|
||||
}
|
||||
if (channelSettingsKeys.contains("rgbColor")) {
|
||||
settings.m_rgbColor = response.getPacketDemodSettings()->getRgbColor();
|
||||
@ -530,6 +536,7 @@ void PacketDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& r
|
||||
response.getPacketDemodSettings()->setUdpPort(settings.m_udpPort);
|
||||
response.getPacketDemodSettings()->setLogFilename(new QString(settings.m_logFilename));
|
||||
response.getPacketDemodSettings()->setLogEnabled(settings.m_logEnabled);
|
||||
response.getPacketDemodSettings()->setUseFileTime(settings.m_useFileTime);
|
||||
|
||||
response.getPacketDemodSettings()->setRgbColor(settings.m_rgbColor);
|
||||
if (response.getPacketDemodSettings()->getTitle()) {
|
||||
@ -658,6 +665,9 @@ void PacketDemod::webapiFormatChannelSettings(
|
||||
if (channelSettingsKeys.contains("logEnabled") || force) {
|
||||
swgPacketDemodSettings->setLogEnabled(settings.m_logEnabled);
|
||||
}
|
||||
if (channelSettingsKeys.contains("useFilTime") || force) {
|
||||
swgPacketDemodSettings->setUseFileTime(settings.m_useFileTime);
|
||||
}
|
||||
if (channelSettingsKeys.contains("rgbColor") || force) {
|
||||
swgPacketDemodSettings->setRgbColor(settings.m_rgbColor);
|
||||
}
|
||||
|
@ -16,10 +16,6 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <limits>
|
||||
#include <ctype.h>
|
||||
#include <QDockWidget>
|
||||
#include <QMainWindow>
|
||||
#include <QDebug>
|
||||
#include <QMessageBox>
|
||||
#include <QAction>
|
||||
@ -38,7 +34,6 @@
|
||||
#include "util/simpleserializer.h"
|
||||
#include "util/csv.h"
|
||||
#include "util/db.h"
|
||||
#include "util/morse.h"
|
||||
#include "util/units.h"
|
||||
#include "gui/basicchannelsettingsdialog.h"
|
||||
#include "gui/devicestreamselectiondialog.h"
|
||||
@ -51,20 +46,14 @@
|
||||
#include "packetdemod.h"
|
||||
#include "packetdemodsink.h"
|
||||
|
||||
#define PACKET_COL_FROM 0
|
||||
#define PACKET_COL_TO 1
|
||||
#define PACKET_COL_VIA 2
|
||||
#define PACKET_COL_TYPE 3
|
||||
#define PACKET_COL_PID 4
|
||||
#define PACKET_COL_DATA_ASCII 5
|
||||
#define PACKET_COL_DATA_HEX 6
|
||||
|
||||
void PacketDemodGUI::resizeTable()
|
||||
{
|
||||
// Fill table with a row of dummy data that will size the columns nicely
|
||||
// Trailing spaces are for sort arrow
|
||||
int row = ui->packets->rowCount();
|
||||
ui->packets->setRowCount(row + 1);
|
||||
ui->packets->setItem(row, PACKET_COL_DATE, new QTableWidgetItem("Frid Apr 15 2016-"));
|
||||
ui->packets->setItem(row, PACKET_COL_TIME, new QTableWidgetItem("10:17:00"));
|
||||
ui->packets->setItem(row, PACKET_COL_FROM, new QTableWidgetItem("123456-15-"));
|
||||
ui->packets->setItem(row, PACKET_COL_TO, new QTableWidgetItem("123456-15-"));
|
||||
ui->packets->setItem(row, PACKET_COL_VIA, new QTableWidgetItem("123456-15-"));
|
||||
@ -158,7 +147,7 @@ bool PacketDemodGUI::deserialize(const QByteArray& data)
|
||||
}
|
||||
|
||||
// Add row to table
|
||||
void PacketDemodGUI::packetReceived(QByteArray packet)
|
||||
void PacketDemodGUI::packetReceived(const QByteArray& packet, QDateTime dateTime)
|
||||
{
|
||||
AX25Packet ax25;
|
||||
|
||||
@ -172,6 +161,8 @@ void PacketDemodGUI::packetReceived(QByteArray packet)
|
||||
int row = ui->packets->rowCount();
|
||||
ui->packets->setRowCount(row + 1);
|
||||
|
||||
QTableWidgetItem *dateItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *timeItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *fromItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *toItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *viaItem = new QTableWidgetItem();
|
||||
@ -179,6 +170,8 @@ void PacketDemodGUI::packetReceived(QByteArray packet)
|
||||
QTableWidgetItem *pidItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *dataASCIIItem = new QTableWidgetItem();
|
||||
QTableWidgetItem *dataHexItem = new QTableWidgetItem();
|
||||
ui->packets->setItem(row, PACKET_COL_DATE, dateItem);
|
||||
ui->packets->setItem(row, PACKET_COL_TIME, timeItem);
|
||||
ui->packets->setItem(row, PACKET_COL_FROM, fromItem);
|
||||
ui->packets->setItem(row, PACKET_COL_TO, toItem);
|
||||
ui->packets->setItem(row, PACKET_COL_VIA, viaItem);
|
||||
@ -186,6 +179,8 @@ void PacketDemodGUI::packetReceived(QByteArray packet)
|
||||
ui->packets->setItem(row, PACKET_COL_PID, pidItem);
|
||||
ui->packets->setItem(row, PACKET_COL_DATA_ASCII, dataASCIIItem);
|
||||
ui->packets->setItem(row, PACKET_COL_DATA_HEX, dataHexItem);
|
||||
dateItem->setText(dateTime.date().toString());
|
||||
timeItem->setText(dateTime.time().toString());
|
||||
fromItem->setText(ax25.m_from);
|
||||
toItem->setText(ax25.m_to);
|
||||
viaItem->setText(ax25.m_via);
|
||||
@ -229,7 +224,7 @@ bool PacketDemodGUI::handleMessage(const Message& message)
|
||||
else if (MainCore::MsgPacket::match(message))
|
||||
{
|
||||
MainCore::MsgPacket& report = (MainCore::MsgPacket&) message;
|
||||
packetReceived(report.getPacket());
|
||||
packetReceived(report.getPacket(), report.getDateTime());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -554,6 +549,8 @@ void PacketDemodGUI::displaySettings()
|
||||
ui->logFilename->setToolTip(QString(".csv log filename: %1").arg(m_settings.m_logFilename));
|
||||
ui->logEnable->setChecked(m_settings.m_logEnabled);
|
||||
|
||||
ui->useFileTime->setChecked(m_settings.m_useFileTime);
|
||||
|
||||
// Order and size columns
|
||||
QHeaderView *header = ui->packets->horizontalHeader();
|
||||
for (int i = 0; i < PACKETDEMOD_COLUMNS; i++)
|
||||
@ -666,7 +663,7 @@ void PacketDemodGUI::on_logOpen_clicked()
|
||||
QTime time = QTime::fromString(cols[timeCol]);
|
||||
QDateTime dateTime(date, time);
|
||||
QByteArray bytes = QByteArray::fromHex(cols[dataCol].toLatin1());
|
||||
packetReceived(bytes);
|
||||
packetReceived(bytes, dateTime);
|
||||
if (count % 1000 == 0)
|
||||
{
|
||||
QApplication::processEvents();
|
||||
@ -692,6 +689,12 @@ void PacketDemodGUI::on_logOpen_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
void PacketDemodGUI::on_useFileTime_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_useFileTime = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void PacketDemodGUI::makeUIConnections()
|
||||
{
|
||||
QObject::connect(ui->deltaFrequency, &ValueDialZ::changed, this, &PacketDemodGUI::on_deltaFrequency_changed);
|
||||
@ -708,6 +711,7 @@ void PacketDemodGUI::makeUIConnections()
|
||||
QObject::connect(ui->logEnable, &ButtonSwitch::clicked, this, &PacketDemodGUI::on_logEnable_clicked);
|
||||
QObject::connect(ui->logFilename, &QToolButton::clicked, this, &PacketDemodGUI::on_logFilename_clicked);
|
||||
QObject::connect(ui->logOpen, &QToolButton::clicked, this, &PacketDemodGUI::on_logOpen_clicked);
|
||||
QObject::connect(ui->useFileTime, &ButtonSwitch::toggled, this, &PacketDemodGUI::on_useFileTime_toggled);
|
||||
}
|
||||
|
||||
void PacketDemodGUI::updateAbsoluteCenterFrequency()
|
||||
|
@ -97,7 +97,7 @@ private:
|
||||
void blockApplySettings(bool block);
|
||||
void applySettings(bool force = false);
|
||||
void displaySettings();
|
||||
void packetReceived(QByteArray packet);
|
||||
void packetReceived(const QByteArray& packet, QDateTime dateTime);
|
||||
bool handleMessage(const Message& message);
|
||||
void makeUIConnections();
|
||||
void updateAbsoluteCenterFrequency();
|
||||
@ -108,6 +108,18 @@ private:
|
||||
void resizeTable();
|
||||
QAction *createCheckableItem(QString& text, int idx, bool checked);
|
||||
|
||||
enum PacketCol {
|
||||
PACKET_COL_DATE,
|
||||
PACKET_COL_TIME,
|
||||
PACKET_COL_FROM,
|
||||
PACKET_COL_TO,
|
||||
PACKET_COL_VIA,
|
||||
PACKET_COL_TYPE,
|
||||
PACKET_COL_PID,
|
||||
PACKET_COL_DATA_ASCII,
|
||||
PACKET_COL_DATA_HEX
|
||||
};
|
||||
|
||||
private slots:
|
||||
void on_deltaFrequency_changed(qint64 value);
|
||||
void on_mode_currentIndexChanged(int value);
|
||||
@ -123,6 +135,7 @@ private slots:
|
||||
void on_logEnable_clicked(bool checked=false);
|
||||
void on_logFilename_clicked();
|
||||
void on_logOpen_clicked();
|
||||
void on_useFileTime_toggled(bool checked=false);
|
||||
void filterRow(int row);
|
||||
void filter();
|
||||
void packets_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex);
|
||||
|
@ -385,6 +385,13 @@
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="udpLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="udpEnabledLabel">
|
||||
<property name="text">
|
||||
<string>UDP</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="udpEnabled">
|
||||
<property name="toolTip">
|
||||
@ -394,7 +401,7 @@
|
||||
<enum>Qt::RightToLeft</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>UDP</string>
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -536,6 +543,27 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="useFileTime">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Check to use date and time from input file. Uncheck to use date and time from clock.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/clockcurrent.png</normaloff>
|
||||
<normalon>:/clockfile.png</normalon>:/clockcurrent.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="logEnable">
|
||||
<property name="maximumSize">
|
||||
@ -650,6 +678,22 @@
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Date</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Date packet was received</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Time</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Time packet was received</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>From</string>
|
||||
@ -713,10 +757,9 @@
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>RollupContents</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupcontents.h</header>
|
||||
<container>1</container>
|
||||
<class>ButtonSwitch</class>
|
||||
<extends>QToolButton</extends>
|
||||
<header>gui/buttonswitch.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ValueDialZ</class>
|
||||
@ -724,17 +767,18 @@
|
||||
<header>gui/valuedialz.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RollupContents</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupcontents.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LevelMeterSignalDB</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>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>packets</tabstop>
|
||||
|
@ -46,6 +46,7 @@ void PacketDemodSettings::resetToDefaults()
|
||||
m_udpPort = 9999;
|
||||
m_logFilename = "packet_log.csv";
|
||||
m_logEnabled = false;
|
||||
m_useFileTime = false;
|
||||
|
||||
m_rgbColor = QColor(0, 105, 2).rgb();
|
||||
m_title = "Packet Demodulator";
|
||||
@ -103,6 +104,8 @@ QByteArray PacketDemodSettings::serialize() const
|
||||
s.writeBlob(29, m_geometryBytes);
|
||||
s.writeBool(30, m_hidden);
|
||||
|
||||
s.writeBool(31, m_useFileTime);
|
||||
|
||||
for (int i = 0; i < PACKETDEMOD_COLUMNS; i++) {
|
||||
s.writeS32(100 + i, m_columnIndexes[i]);
|
||||
}
|
||||
@ -185,6 +188,8 @@ bool PacketDemodSettings::deserialize(const QByteArray& data)
|
||||
d.readBlob(29, &m_geometryBytes);
|
||||
d.readBool(30, &m_hidden, false);
|
||||
|
||||
d.readBool(31, &m_useFileTime, false);
|
||||
|
||||
for (int i = 0; i < PACKETDEMOD_COLUMNS; i++) {
|
||||
d.readS32(100 + i, &m_columnIndexes[i], i);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
class Serializable;
|
||||
|
||||
// Number of columns in the table
|
||||
#define PACKETDEMOD_COLUMNS 7
|
||||
#define PACKETDEMOD_COLUMNS 9
|
||||
|
||||
struct PacketDemodSettings
|
||||
{
|
||||
@ -45,6 +45,7 @@ struct PacketDemodSettings
|
||||
bool m_udpEnabled;
|
||||
QString m_udpAddress;
|
||||
uint16_t m_udpPort;
|
||||
bool m_useFileTime;
|
||||
|
||||
quint32 m_rgbColor;
|
||||
QString m_title;
|
||||
|
@ -22,8 +22,10 @@
|
||||
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/datafifo.h"
|
||||
#include "device/deviceapi.h"
|
||||
#include "util/db.h"
|
||||
#include "util/stepfunctions.h"
|
||||
#include "channel/channelwebapiutils.h"
|
||||
#include "maincore.h"
|
||||
|
||||
#include "packetdemod.h"
|
||||
@ -191,7 +193,23 @@ void PacketDemodSink::processOneSample(Complex &ci)
|
||||
qDebug() << "RX: " << rxPacket.toHex();
|
||||
if (getMessageQueueToChannel())
|
||||
{
|
||||
MainCore::MsgPacket *msg = MainCore::MsgPacket::create(m_packetDemod, rxPacket, QDateTime::currentDateTime()); // FIXME pointer
|
||||
QDateTime dateTime = QDateTime::currentDateTime();
|
||||
if (m_settings.m_useFileTime)
|
||||
{
|
||||
QString hardwareId = m_packetDemod->getDeviceAPI()->getHardwareId();
|
||||
|
||||
if ((hardwareId == "FileInput") || (hardwareId == "SigMFFileInput"))
|
||||
{
|
||||
QString dateTimeStr;
|
||||
int deviceIdx = m_packetDemod->getDeviceSetIndex();
|
||||
|
||||
if (ChannelWebAPIUtils::getDeviceReportValue(deviceIdx, "absoluteTime", dateTimeStr)) {
|
||||
dateTime = QDateTime::fromString(dateTimeStr, Qt::ISODateWithMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MainCore::MsgPacket *msg = MainCore::MsgPacket::create(m_packetDemod, rxPacket, dateTime);
|
||||
getMessageQueueToChannel()->push(msg);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<h1>Packet radio demodulator plugin</h1>
|
||||
<h1>Packet Radio Demodulator Plugin</h1>
|
||||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
@ -60,19 +60,24 @@ When checked, received packets are forwarded to the specified UDP address (12) a
|
||||
|
||||
IP address of the host to forward received packets to via UDP.
|
||||
|
||||
<h3>11: UDP port</h3>
|
||||
<h3>13: UDP port</h3>
|
||||
|
||||
UDP port number to forward received packets to.
|
||||
|
||||
<h3>12: Start/stop Logging Packets to .csv File</h3>
|
||||
<h3>14: Use Date and Time from File</h3>
|
||||
|
||||
When checked, if the source device is a File Input device, the date and time used for
|
||||
packet reception time is taken from the file playback time. Otherwise, the current system clock time is used.
|
||||
|
||||
<h3>15: Start/stop Logging Packets to .csv File</h3>
|
||||
|
||||
When checked, writes all received packets to a .csv file.
|
||||
|
||||
<h3>13: .csv Log Filename</h3>
|
||||
<h3>16: .csv Log Filename</h3>
|
||||
|
||||
Click to specify the name of the .csv file which received packets are logged to.
|
||||
|
||||
<h3>14: Read Data from .csv File</h3>
|
||||
<h3>17: Read Data from .csv File</h3>
|
||||
|
||||
Click to specify a previously written .csv log file, which is read and used to update the table.
|
||||
|
||||
@ -80,6 +85,8 @@ Click to specify a previously written .csv log file, which is read and used to u
|
||||
|
||||
The received packets table displays the contents of the packets that have been received. Only packets with valid CRCs are displayed.
|
||||
|
||||
* Date - The date the packet was received.
|
||||
* Time - The time the packet was received.
|
||||
* From - The source address / callsign of the sender of the packet.
|
||||
* To - The destination address.
|
||||
* Via - List of addresses of repeaters the packet has passed through or directed via.
|
||||
|
@ -337,6 +337,9 @@ void RadiosondeDemod::applySettings(const RadiosondeDemodSettings& settings, boo
|
||||
if ((settings.m_logEnabled != m_settings.m_logEnabled) || force) {
|
||||
reverseAPIKeys.append("logEnabled");
|
||||
}
|
||||
if ((settings.m_useFileTime != m_settings.m_useFileTime) || force) {
|
||||
reverseAPIKeys.append("useFileTime");
|
||||
}
|
||||
if (m_settings.m_streamIndex != settings.m_streamIndex)
|
||||
{
|
||||
if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only
|
||||
@ -516,6 +519,9 @@ void RadiosondeDemod::webapiUpdateChannelSettings(
|
||||
if (channelSettingsKeys.contains("logEnabled")) {
|
||||
settings.m_logEnabled = response.getRadiosondeDemodSettings()->getLogEnabled();
|
||||
}
|
||||
if (channelSettingsKeys.contains("useFileTime")) {
|
||||
settings.m_useFileTime = response.getRadiosondeDemodSettings()->getUseFileTime();
|
||||
}
|
||||
if (channelSettingsKeys.contains("rgbColor")) {
|
||||
settings.m_rgbColor = response.getRadiosondeDemodSettings()->getRgbColor();
|
||||
}
|
||||
@ -563,6 +569,7 @@ void RadiosondeDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSetting
|
||||
response.getRadiosondeDemodSettings()->setUdpPort(settings.m_udpPort);
|
||||
response.getRadiosondeDemodSettings()->setLogFilename(new QString(settings.m_logFilename));
|
||||
response.getRadiosondeDemodSettings()->setLogEnabled(settings.m_logEnabled);
|
||||
response.getRadiosondeDemodSettings()->setUseFileTime(settings.m_useFileTime);
|
||||
|
||||
response.getRadiosondeDemodSettings()->setRgbColor(settings.m_rgbColor);
|
||||
if (response.getRadiosondeDemodSettings()->getTitle()) {
|
||||
@ -698,6 +705,9 @@ void RadiosondeDemod::webapiFormatChannelSettings(
|
||||
if (channelSettingsKeys.contains("logEnabled") || force) {
|
||||
swgRadiosondeDemodSettings->setLogEnabled(settings.m_logEnabled);
|
||||
}
|
||||
if (channelSettingsKeys.contains("useFileTime") || force) {
|
||||
swgRadiosondeDemodSettings->setUseFileTime(settings.m_useFileTime);
|
||||
}
|
||||
if (channelSettingsKeys.contains("rgbColor") || force) {
|
||||
swgRadiosondeDemodSettings->setRgbColor(settings.m_rgbColor);
|
||||
}
|
||||
|
@ -82,9 +82,9 @@ public:
|
||||
int getErrorsCorrected() const { return m_errorsCorrected; }
|
||||
int getThreshold() const { return m_threshold; }
|
||||
|
||||
static MsgMessage* create(QByteArray message, int errorsCorrected, int threshold)
|
||||
static MsgMessage* create(const QByteArray& message, QDateTime dateTime, int errorsCorrected, int threshold)
|
||||
{
|
||||
return new MsgMessage(message, QDateTime::currentDateTime(), errorsCorrected, threshold);
|
||||
return new MsgMessage(message, dateTime, errorsCorrected, threshold);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -93,7 +93,7 @@ public:
|
||||
int m_errorsCorrected;
|
||||
int m_threshold;
|
||||
|
||||
MsgMessage(QByteArray message, QDateTime dateTime, int errorsCorrected, int threshold) :
|
||||
MsgMessage(const QByteArray& message, QDateTime dateTime, int errorsCorrected, int threshold) :
|
||||
Message(),
|
||||
m_message(message),
|
||||
m_dateTime(dateTime),
|
||||
|
@ -771,6 +771,8 @@ void RadiosondeDemodGUI::displaySettings()
|
||||
ui->logFilename->setToolTip(QString(".csv log filename: %1").arg(m_settings.m_logFilename));
|
||||
ui->logEnable->setChecked(m_settings.m_logEnabled);
|
||||
|
||||
ui->useFileTime->setChecked(m_settings.m_useFileTime);
|
||||
|
||||
// Order and size columns
|
||||
QHeaderView *header = ui->frames->horizontalHeader();
|
||||
for (int i = 0; i < RADIOSONDEDEMOD_FRAME_COLUMNS; i++)
|
||||
@ -924,6 +926,12 @@ void RadiosondeDemodGUI::on_logOpen_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
void RadiosondeDemodGUI::on_useFileTime_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_useFileTime = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void RadiosondeDemodGUI::makeUIConnections()
|
||||
{
|
||||
QObject::connect(ui->deltaFrequency, &ValueDialZ::changed, this, &RadiosondeDemodGUI::on_deltaFrequency_changed);
|
||||
@ -939,6 +947,7 @@ void RadiosondeDemodGUI::makeUIConnections()
|
||||
QObject::connect(ui->logEnable, &ButtonSwitch::clicked, this, &RadiosondeDemodGUI::on_logEnable_clicked);
|
||||
QObject::connect(ui->logFilename, &QToolButton::clicked, this, &RadiosondeDemodGUI::on_logFilename_clicked);
|
||||
QObject::connect(ui->logOpen, &QToolButton::clicked, this, &RadiosondeDemodGUI::on_logOpen_clicked);
|
||||
QObject::connect(ui->useFileTime, &ButtonSwitch::toggled, this, &RadiosondeDemodGUI::on_useFileTime_toggled);
|
||||
}
|
||||
|
||||
void RadiosondeDemodGUI::updateAbsoluteCenterFrequency()
|
||||
|
@ -154,6 +154,7 @@ private slots:
|
||||
void on_logEnable_clicked(bool checked=false);
|
||||
void on_logFilename_clicked();
|
||||
void on_logOpen_clicked();
|
||||
void on_useFileTime_toggled(bool checked=false);
|
||||
void filterRow(int row);
|
||||
void filter();
|
||||
void frames_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex);
|
||||
|
@ -524,6 +524,27 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="useFileTime">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Check to use date and time from input file. Uncheck to use date and time from clock.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/clockcurrent.png</normaloff>
|
||||
<normalon>:/clockfile.png</normalon>:/clockcurrent.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="logEnable">
|
||||
<property name="maximumSize">
|
||||
@ -1076,29 +1097,29 @@
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<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>
|
||||
<customwidget>
|
||||
<class>RollupContents</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupcontents.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ButtonSwitch</class>
|
||||
<extends>QToolButton</extends>
|
||||
<header>gui/buttonswitch.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LevelMeterSignalDB</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/levelmeter.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ValueDialZ</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/valuedialz.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GLScope</class>
|
||||
<extends>QWidget</extends>
|
||||
|
@ -48,6 +48,7 @@ void RadiosondeDemodSettings::resetToDefaults()
|
||||
m_scopeCh2 = 6;
|
||||
m_logFilename = "radiosonde_log.csv";
|
||||
m_logEnabled = false;
|
||||
m_useFileTime = false;
|
||||
m_rgbColor = QColor(102, 0, 102).rgb();
|
||||
m_title = "Radiosonde Demodulator";
|
||||
m_streamIndex = 0;
|
||||
@ -106,6 +107,8 @@ QByteArray RadiosondeDemodSettings::serialize() const
|
||||
s.writeBlob(27, m_geometryBytes);
|
||||
s.writeBool(28, m_hidden);
|
||||
|
||||
s.writeBool(29, m_useFileTime);
|
||||
|
||||
for (int i = 0; i < RADIOSONDEDEMOD_FRAME_COLUMNS; i++)
|
||||
s.writeS32(100 + i, m_frameColumnIndexes[i]);
|
||||
for (int i = 0; i < RADIOSONDEDEMOD_FRAME_COLUMNS; i++)
|
||||
@ -192,6 +195,8 @@ bool RadiosondeDemodSettings::deserialize(const QByteArray& data)
|
||||
d.readBlob(27, &m_geometryBytes);
|
||||
d.readBool(28, &m_hidden, false);
|
||||
|
||||
d.readBool(29, &m_useFileTime, false);
|
||||
|
||||
for (int i = 0; i < RADIOSONDEDEMOD_FRAME_COLUMNS; i++) {
|
||||
d.readS32(100 + i, &m_frameColumnIndexes[i], i);
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ struct RadiosondeDemodSettings
|
||||
|
||||
QString m_logFilename;
|
||||
bool m_logEnabled;
|
||||
bool m_useFileTime;
|
||||
|
||||
quint32 m_rgbColor;
|
||||
QString m_title;
|
||||
|
@ -23,8 +23,10 @@
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/datafifo.h"
|
||||
#include "dsp/scopevis.h"
|
||||
#include "device/deviceapi.h"
|
||||
#include "util/db.h"
|
||||
#include "util/stepfunctions.h"
|
||||
#include "channel/channelwebapiutils.h"
|
||||
#include "util/reedsolomon.h"
|
||||
#include "maincore.h"
|
||||
|
||||
@ -415,8 +417,23 @@ bool RadiosondeDemodSink::processFrame(int length, float corr, int sampleIdx)
|
||||
{
|
||||
if (getMessageQueueToChannel())
|
||||
{
|
||||
QDateTime dateTime = QDateTime::currentDateTime();
|
||||
if (m_settings.m_useFileTime)
|
||||
{
|
||||
QString hardwareId = m_radiosondeDemod->getDeviceAPI()->getHardwareId();
|
||||
|
||||
if ((hardwareId == "FileInput") || (hardwareId == "SigMFFileInput"))
|
||||
{
|
||||
QString dateTimeStr;
|
||||
int deviceIdx = m_radiosondeDemod->getDeviceSetIndex();
|
||||
|
||||
if (ChannelWebAPIUtils::getDeviceReportValue(deviceIdx, "absoluteTime", dateTimeStr)) {
|
||||
dateTime = QDateTime::fromString(dateTimeStr, Qt::ISODateWithMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
QByteArray rxPacket((char *)m_bytes, length);
|
||||
RadiosondeDemod::MsgMessage *msg = RadiosondeDemod::MsgMessage::create(rxPacket, errorsCorrected, corr);
|
||||
RadiosondeDemod::MsgMessage *msg = RadiosondeDemod::MsgMessage::create(rxPacket, dateTime, errorsCorrected, corr);
|
||||
getMessageQueueToChannel()->push(msg);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<h1>Radiosonde demodulator plugin</h1>
|
||||
<h1>Radiosonde Demodulator Plugin</h1>
|
||||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
@ -56,19 +56,24 @@ UDP port number to forward received frames to.
|
||||
|
||||
Entering a regular expression in the Find field displays only frames where the radiosonde serial number matches the given regular expression.
|
||||
|
||||
<h3>11: Start/stop Logging Frames to .csv File</h3>
|
||||
<h3>11: Use Date and Time from File</h3>
|
||||
|
||||
When checked, if the source device is a File Input device, the date and time used for
|
||||
frame reception time is taken from the file playback time. Otherwise, the current system clock time is used.
|
||||
|
||||
<h3>12: Start/stop Logging Frames to .csv File</h3>
|
||||
|
||||
When checked, writes all received frames to a .csv file.
|
||||
|
||||
<h3>14: .csv Log Filename</h3>
|
||||
<h3>13: .csv Log Filename</h3>
|
||||
|
||||
Click to specify the name of the .csv file which received frames are logged to.
|
||||
|
||||
<h3>15: Read Data from .csv File</h3>
|
||||
<h3>14: Read Data from .csv File</h3>
|
||||
|
||||
Click to specify a previously written radiosonde .csv log file, which is read and used to update the table.
|
||||
|
||||
<h3>11: Clear Data from table</h3>
|
||||
<h3>15: Clear Data from table</h3>
|
||||
|
||||
Pressing this button clears all data from the table.
|
||||
|
||||
|
@ -33,6 +33,7 @@ const QStringList DemodAnalyzerSettings::m_channelTypes = {
|
||||
QStringLiteral("BFMDemod"),
|
||||
QStringLiteral("DABDemod"),
|
||||
QStringLiteral("DSDDemod"),
|
||||
QStringLiteral("EndOfTrainDemod"),
|
||||
QStringLiteral("FT8Demod"),
|
||||
QStringLiteral("M17Demod"),
|
||||
QStringLiteral("M17Mmod"),
|
||||
@ -57,6 +58,7 @@ const QStringList DemodAnalyzerSettings::m_channelURIs = {
|
||||
QStringLiteral("sdrangel.channel.bfm"),
|
||||
QStringLiteral("sdrangel.channel.dabdemod"),
|
||||
QStringLiteral("sdrangel.channel.dsddemod"),
|
||||
QStringLiteral("sdrangel.channel.endoftraindemod"),
|
||||
QStringLiteral("sdrangel.channel.ft8demod"),
|
||||
QStringLiteral("sdrangel.channel.m17demod"),
|
||||
QStringLiteral("sdrangel.channeltx.modm17"),
|
||||
|
@ -1048,6 +1048,9 @@ margin-bottom: 20px;
|
||||
"logEnabled" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"useFileTime" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"rgbColor" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
@ -3836,6 +3839,9 @@ margin-bottom: 20px;
|
||||
"DSDDemodReport" : {
|
||||
"$ref" : "#/definitions/DSDDemodReport"
|
||||
},
|
||||
"EndOfTrainDemodReport" : {
|
||||
"$ref" : "#/definitions/EndOfTrainDemodReport"
|
||||
},
|
||||
"IEEE_802_15_4_ModReport" : {
|
||||
"$ref" : "#/definitions/IEEE_802_15_4_ModReport"
|
||||
},
|
||||
@ -4018,6 +4024,9 @@ margin-bottom: 20px;
|
||||
"DSDDemodSettings" : {
|
||||
"$ref" : "#/definitions/DSDDemodSettings"
|
||||
},
|
||||
"EndOfTrainDemodSettings" : {
|
||||
"$ref" : "#/definitions/EndOfTrainDemodSettings"
|
||||
},
|
||||
"FileSinkSettings" : {
|
||||
"$ref" : "#/definitions/FileSinkSettings"
|
||||
},
|
||||
@ -5170,6 +5179,9 @@ margin-bottom: 20px;
|
||||
"logEnabled" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"useFileTime" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"rgbColor" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
@ -5870,6 +5882,89 @@ margin-bottom: 20px;
|
||||
}
|
||||
},
|
||||
"description" : "Device running state"
|
||||
};
|
||||
defs.EndOfTrainDemodReport = {
|
||||
"properties" : {
|
||||
"channelPowerDB" : {
|
||||
"type" : "number",
|
||||
"format" : "float",
|
||||
"description" : "power received in channel (dB)"
|
||||
},
|
||||
"channelSampleRate" : {
|
||||
"type" : "integer"
|
||||
}
|
||||
},
|
||||
"description" : "EndOfTrainDemod"
|
||||
};
|
||||
defs.EndOfTrainDemodSettings = {
|
||||
"properties" : {
|
||||
"inputFrequencyOffset" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
},
|
||||
"rfBandwidth" : {
|
||||
"type" : "number",
|
||||
"format" : "float"
|
||||
},
|
||||
"fmDeviation" : {
|
||||
"type" : "number",
|
||||
"format" : "float"
|
||||
},
|
||||
"udpEnabled" : {
|
||||
"type" : "integer",
|
||||
"description" : "Whether to forward received packets to specified UDP port"
|
||||
},
|
||||
"udpAddress" : {
|
||||
"type" : "string",
|
||||
"description" : "UDP address to forward received packets to"
|
||||
},
|
||||
"udpPort" : {
|
||||
"type" : "integer",
|
||||
"description" : "UDP port to forward received packets to"
|
||||
},
|
||||
"logFilename" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"logEnabled" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"useFileTime" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"channelMarker" : {
|
||||
"$ref" : "#/definitions/ChannelMarker"
|
||||
},
|
||||
"rollupState" : {
|
||||
"$ref" : "#/definitions/RollupState"
|
||||
}
|
||||
},
|
||||
"description" : "EndOfTrain"
|
||||
};
|
||||
defs.ErrorResponse = {
|
||||
"required" : [ "message" ],
|
||||
@ -10943,7 +11038,7 @@ margin-bottom: 20px;
|
||||
"type" : "integer"
|
||||
}
|
||||
},
|
||||
"description" : "AMDemod"
|
||||
"description" : "PacketDemod"
|
||||
};
|
||||
defs.PacketDemodSettings = {
|
||||
"properties" : {
|
||||
@ -10981,6 +11076,9 @@ margin-bottom: 20px;
|
||||
"logEnabled" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"useFileTime" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"rgbColor" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
@ -12591,6 +12689,9 @@ margin-bottom: 20px;
|
||||
"logEnabled" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"useFileTime" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"rgbColor" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
@ -58672,7 +58773,7 @@ except ApiException as e:
|
||||
</div>
|
||||
<div id="generator">
|
||||
<div class="content">
|
||||
Generated 2024-02-27T15:07:08.970+01:00
|
||||
Generated 2024-03-03T22:27:13.533+01:00
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -32,6 +32,8 @@ AISDemodSettings:
|
||||
type: string
|
||||
logEnabled:
|
||||
type: integer
|
||||
useFileTime:
|
||||
type: integer
|
||||
rgbColor:
|
||||
type: integer
|
||||
title:
|
||||
|
@ -39,6 +39,8 @@ ChannelReport:
|
||||
$ref: "/doc/swagger/include/DSCDemod.yaml#/DSCDemodReport"
|
||||
DSDDemodReport:
|
||||
$ref: "/doc/swagger/include/DSDDemod.yaml#/DSDDemodReport"
|
||||
EndOfTrainDemodReport:
|
||||
$ref: "/doc/swagger/include/EndOfTrainDemod.yaml#/EndOfTrainDemodReport"
|
||||
IEEE_802_15_4_ModReport:
|
||||
$ref: "/doc/swagger/include/IEEE_802_15_4_Mod.yaml#/IEEE_802_15_4_ModReport"
|
||||
FileSinkReport:
|
||||
|
@ -55,6 +55,8 @@ ChannelSettings:
|
||||
$ref: "/doc/swagger/include/DSCDemod.yaml#/DSCDemodSettings"
|
||||
DSDDemodSettings:
|
||||
$ref: "/doc/swagger/include/DSDDemod.yaml#/DSDDemodSettings"
|
||||
EndOfTrainDemodSettings:
|
||||
$ref: "/doc/swagger/include/EndOfTrainDemod.yaml#/EndOfTrainDemodSettings"
|
||||
FileSinkSettings:
|
||||
$ref: "/doc/swagger/include/FileSink.yaml#/FileSinkSettings"
|
||||
FileSourceSettings:
|
||||
|
@ -23,6 +23,8 @@ DSCDemodSettings:
|
||||
type: string
|
||||
logEnabled:
|
||||
type: integer
|
||||
useFileTime:
|
||||
type: integer
|
||||
rgbColor:
|
||||
type: integer
|
||||
title:
|
||||
|
@ -0,0 +1,59 @@
|
||||
EndOfTrainDemodSettings:
|
||||
description: EndOfTrain
|
||||
properties:
|
||||
inputFrequencyOffset:
|
||||
type: integer
|
||||
format: int64
|
||||
rfBandwidth:
|
||||
type: number
|
||||
format: float
|
||||
fmDeviation:
|
||||
type: number
|
||||
format: float
|
||||
udpEnabled:
|
||||
description: "Whether to forward received packets to specified UDP port"
|
||||
type: integer
|
||||
udpAddress:
|
||||
description: "UDP address to forward received packets to"
|
||||
type: string
|
||||
udpPort:
|
||||
description: "UDP port to forward received packets to"
|
||||
type: integer
|
||||
logFilename:
|
||||
type: string
|
||||
logEnabled:
|
||||
type: integer
|
||||
useFileTime:
|
||||
type: integer
|
||||
rgbColor:
|
||||
type: integer
|
||||
title:
|
||||
type: string
|
||||
streamIndex:
|
||||
description: MIMO channel. Not relevant when connected to SI (single Rx).
|
||||
type: integer
|
||||
useReverseAPI:
|
||||
description: Synchronize with reverse API (1 for yes, 0 for no)
|
||||
type: integer
|
||||
reverseAPIAddress:
|
||||
type: string
|
||||
reverseAPIPort:
|
||||
type: integer
|
||||
reverseAPIDeviceIndex:
|
||||
type: integer
|
||||
reverseAPIChannelIndex:
|
||||
type: integer
|
||||
channelMarker:
|
||||
$ref: "/doc/swagger/include/ChannelMarker.yaml#/ChannelMarker"
|
||||
rollupState:
|
||||
$ref: "/doc/swagger/include/RollupState.yaml#/RollupState"
|
||||
|
||||
EndOfTrainDemodReport:
|
||||
description: EndOfTrainDemod
|
||||
properties:
|
||||
channelPowerDB:
|
||||
description: power received in channel (dB)
|
||||
type: number
|
||||
format: float
|
||||
channelSampleRate:
|
||||
type: integer
|
@ -28,6 +28,8 @@ PacketDemodSettings:
|
||||
type: string
|
||||
logEnabled:
|
||||
type: integer
|
||||
useFileTime:
|
||||
type: integer
|
||||
rgbColor:
|
||||
type: integer
|
||||
title:
|
||||
@ -52,7 +54,7 @@ PacketDemodSettings:
|
||||
$ref: "/doc/swagger/include/RollupState.yaml#/RollupState"
|
||||
|
||||
PacketDemodReport:
|
||||
description: AMDemod
|
||||
description: PacketDemod
|
||||
properties:
|
||||
channelPowerDB:
|
||||
description: power received in channel (dB)
|
||||
|
@ -29,6 +29,8 @@ RadiosondeDemodSettings:
|
||||
type: string
|
||||
logEnabled:
|
||||
type: integer
|
||||
useFileTime:
|
||||
type: integer
|
||||
rgbColor:
|
||||
type: integer
|
||||
title:
|
||||
|
@ -44,7 +44,7 @@ void crc::calculate(uint32_t data, int data_bits)
|
||||
{
|
||||
mask = (1 << m_poly_bits) - 1;
|
||||
msb = 1 << (m_poly_bits - 1);
|
||||
tmp = m_crc ^ (data << (m_poly_bits - 8));
|
||||
tmp = m_crc ^ (data << (m_poly_bits - data_bits));
|
||||
for (i = 0; i < data_bits; i++)
|
||||
{
|
||||
if (tmp & msb)
|
||||
|
@ -93,6 +93,8 @@ void KiwiSDRList::handleReply(QNetworkReply* reply)
|
||||
|
||||
void KiwiSDRList::handleHTML(const QString& url, const QByteArray& bytes)
|
||||
{
|
||||
(void) url;
|
||||
|
||||
QList<KiwiSDR> sdrs;
|
||||
QString html(bytes);
|
||||
QRegularExpression div("<div class='cl-info'>(.*?)<\\/div>", QRegularExpression::DotMatchesEverythingOption);
|
||||
|
@ -93,6 +93,8 @@ void SpyServerList::handleReply(QNetworkReply* reply)
|
||||
|
||||
void SpyServerList::handleJSON(const QString& url, const QByteArray& bytes)
|
||||
{
|
||||
(void) url;
|
||||
|
||||
QList<SpyServer> sdrs;
|
||||
QJsonDocument document = QJsonDocument::fromJson(bytes);
|
||||
|
||||
|
@ -4526,6 +4526,12 @@ bool WebAPIRequestMapper::getChannelSettings(
|
||||
channelSettings->getDsdDemodSettings()->init();
|
||||
channelSettings->getDsdDemodSettings()->fromJsonObject(settingsJsonObject);
|
||||
}
|
||||
else if (channelSettingsKey == "EndOfTrainDemodSettings")
|
||||
{
|
||||
channelSettings->setEndOfTrainDemodSettings(new SWGSDRangel::SWGEndOfTrainDemodSettings());
|
||||
channelSettings->getEndOfTrainDemodSettings()->init();
|
||||
channelSettings->getEndOfTrainDemodSettings()->fromJsonObject(settingsJsonObject);
|
||||
}
|
||||
else if (channelSettingsKey == "FileSinkSettings")
|
||||
{
|
||||
channelSettings->setFileSinkSettings(new SWGSDRangel::SWGFileSinkSettings());
|
||||
@ -5523,6 +5529,7 @@ void WebAPIRequestMapper::resetChannelSettings(SWGSDRangel::SWGChannelSettings&
|
||||
channelSettings.setDatvModSettings(nullptr);
|
||||
channelSettings.setDabDemodSettings(nullptr);
|
||||
channelSettings.setDsdDemodSettings(nullptr);
|
||||
channelSettings.setEndOfTrainDemodSettings(nullptr);
|
||||
channelSettings.setFreqScannerSettings(nullptr);
|
||||
channelSettings.setFreqTrackerSettings(nullptr);
|
||||
channelSettings.setHeatMapSettings(nullptr);
|
||||
@ -5567,6 +5574,7 @@ void WebAPIRequestMapper::resetChannelReport(SWGSDRangel::SWGChannelReport& chan
|
||||
channelReport.setBfmDemodReport(nullptr);
|
||||
channelReport.setDatvModReport(nullptr);
|
||||
channelReport.setDsdDemodReport(nullptr);
|
||||
channelReport.setEndOfTrainDemodReport(nullptr);
|
||||
channelReport.setFreqScannerReport(nullptr);
|
||||
channelReport.setFreqTrackerReport(nullptr);
|
||||
channelReport.setHeatMapReport(nullptr);
|
||||
|
@ -43,6 +43,7 @@ const QMap<QString, QString> WebAPIUtils::m_channelURIToSettingsKey = {
|
||||
{"sdrangel.channel.doa2", "DOA2Settings"},
|
||||
{"sdrangel.channel.dscdemod", "DSCDemodSettings"},
|
||||
{"sdrangel.channel.dsddemod", "DSDDemodSettings"},
|
||||
{"sdrangel.channel.endoftraindemod", "EndOfTrainDemodSettings"},
|
||||
{"sdrangel.channel.filesink", "FileSinkSettings"},
|
||||
{"sdrangel.channeltx.filesource", "FileSourceSettings"},
|
||||
{"sdrangel.channel.freedvdemod", "FreeDVDemodSettings"},
|
||||
@ -165,6 +166,7 @@ const QMap<QString, QString> WebAPIUtils::m_channelTypeToSettingsKey = {
|
||||
{"DOA2", "DOA2Settings"},
|
||||
{"DSCDemod", "DSCDemodSettings"},
|
||||
{"DSDDemod", "DSDDemodSettings"},
|
||||
{"EndOfTrainDemod", "EndOfTrainDemodSettings"},
|
||||
{"FileSink", "FileSinkSettings"},
|
||||
{"FileSource", "FileSourceSettings"},
|
||||
{"FreeDVDemod", "FreeDVDemodSettings"},
|
||||
|
BIN
sdrgui/resources/clockcurrent.png
Normal file
BIN
sdrgui/resources/clockcurrent.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
sdrgui/resources/clockfile.png
Normal file
BIN
sdrgui/resources/clockfile.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
@ -154,6 +154,8 @@
|
||||
<file>stackvertical.png</file>
|
||||
<file>stackcolumns.png</file>
|
||||
<file>tab.png</file>
|
||||
<file>clockfile.png</file>
|
||||
<file>clockcurrent.png</file>
|
||||
<file>LiberationMono-Regular.ttf</file>
|
||||
<file>LiberationSans-Regular.ttf</file>
|
||||
</qresource>
|
||||
|
@ -32,6 +32,8 @@ AISDemodSettings:
|
||||
type: string
|
||||
logEnabled:
|
||||
type: integer
|
||||
useFileTime:
|
||||
type: integer
|
||||
rgbColor:
|
||||
type: integer
|
||||
title:
|
||||
|
@ -39,6 +39,8 @@ ChannelReport:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/DSCDemod.yaml#/DSCDemodReport"
|
||||
DSDDemodReport:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/DSDDemod.yaml#/DSDDemodReport"
|
||||
EndOfTrainDemodReport:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/EndOfTrainDemod.yaml#/EndOfTrainDemodReport"
|
||||
IEEE_802_15_4_ModReport:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/IEEE_802_15_4_Mod.yaml#/IEEE_802_15_4_ModReport"
|
||||
FileSinkReport:
|
||||
|
@ -55,6 +55,8 @@ ChannelSettings:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/DSCDemod.yaml#/DSCDemodSettings"
|
||||
DSDDemodSettings:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/DSDDemod.yaml#/DSDDemodSettings"
|
||||
EndOfTrainDemodSettings:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/EndOfTrainDemod.yaml#/EndOfTrainDemodSettings"
|
||||
FileSinkSettings:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/FileSink.yaml#/FileSinkSettings"
|
||||
FileSourceSettings:
|
||||
|
@ -23,6 +23,8 @@ DSCDemodSettings:
|
||||
type: string
|
||||
logEnabled:
|
||||
type: integer
|
||||
useFileTime:
|
||||
type: integer
|
||||
rgbColor:
|
||||
type: integer
|
||||
title:
|
||||
|
59
swagger/sdrangel/api/swagger/include/EndOfTrainDemod.yaml
Normal file
59
swagger/sdrangel/api/swagger/include/EndOfTrainDemod.yaml
Normal file
@ -0,0 +1,59 @@
|
||||
EndOfTrainDemodSettings:
|
||||
description: EndOfTrain
|
||||
properties:
|
||||
inputFrequencyOffset:
|
||||
type: integer
|
||||
format: int64
|
||||
rfBandwidth:
|
||||
type: number
|
||||
format: float
|
||||
fmDeviation:
|
||||
type: number
|
||||
format: float
|
||||
udpEnabled:
|
||||
description: "Whether to forward received packets to specified UDP port"
|
||||
type: integer
|
||||
udpAddress:
|
||||
description: "UDP address to forward received packets to"
|
||||
type: string
|
||||
udpPort:
|
||||
description: "UDP port to forward received packets to"
|
||||
type: integer
|
||||
logFilename:
|
||||
type: string
|
||||
logEnabled:
|
||||
type: integer
|
||||
useFileTime:
|
||||
type: integer
|
||||
rgbColor:
|
||||
type: integer
|
||||
title:
|
||||
type: string
|
||||
streamIndex:
|
||||
description: MIMO channel. Not relevant when connected to SI (single Rx).
|
||||
type: integer
|
||||
useReverseAPI:
|
||||
description: Synchronize with reverse API (1 for yes, 0 for no)
|
||||
type: integer
|
||||
reverseAPIAddress:
|
||||
type: string
|
||||
reverseAPIPort:
|
||||
type: integer
|
||||
reverseAPIDeviceIndex:
|
||||
type: integer
|
||||
reverseAPIChannelIndex:
|
||||
type: integer
|
||||
channelMarker:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/ChannelMarker.yaml#/ChannelMarker"
|
||||
rollupState:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/RollupState.yaml#/RollupState"
|
||||
|
||||
EndOfTrainDemodReport:
|
||||
description: EndOfTrainDemod
|
||||
properties:
|
||||
channelPowerDB:
|
||||
description: power received in channel (dB)
|
||||
type: number
|
||||
format: float
|
||||
channelSampleRate:
|
||||
type: integer
|
@ -28,6 +28,8 @@ PacketDemodSettings:
|
||||
type: string
|
||||
logEnabled:
|
||||
type: integer
|
||||
useFileTime:
|
||||
type: integer
|
||||
rgbColor:
|
||||
type: integer
|
||||
title:
|
||||
@ -52,7 +54,7 @@ PacketDemodSettings:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/RollupState.yaml#/RollupState"
|
||||
|
||||
PacketDemodReport:
|
||||
description: AMDemod
|
||||
description: PacketDemod
|
||||
properties:
|
||||
channelPowerDB:
|
||||
description: power received in channel (dB)
|
||||
|
@ -29,6 +29,8 @@ RadiosondeDemodSettings:
|
||||
type: string
|
||||
logEnabled:
|
||||
type: integer
|
||||
useFileTime:
|
||||
type: integer
|
||||
rgbColor:
|
||||
type: integer
|
||||
title:
|
||||
|
@ -1048,6 +1048,9 @@ margin-bottom: 20px;
|
||||
"logEnabled" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"useFileTime" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"rgbColor" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
@ -3836,6 +3839,9 @@ margin-bottom: 20px;
|
||||
"DSDDemodReport" : {
|
||||
"$ref" : "#/definitions/DSDDemodReport"
|
||||
},
|
||||
"EndOfTrainDemodReport" : {
|
||||
"$ref" : "#/definitions/EndOfTrainDemodReport"
|
||||
},
|
||||
"IEEE_802_15_4_ModReport" : {
|
||||
"$ref" : "#/definitions/IEEE_802_15_4_ModReport"
|
||||
},
|
||||
@ -4018,6 +4024,9 @@ margin-bottom: 20px;
|
||||
"DSDDemodSettings" : {
|
||||
"$ref" : "#/definitions/DSDDemodSettings"
|
||||
},
|
||||
"EndOfTrainDemodSettings" : {
|
||||
"$ref" : "#/definitions/EndOfTrainDemodSettings"
|
||||
},
|
||||
"FileSinkSettings" : {
|
||||
"$ref" : "#/definitions/FileSinkSettings"
|
||||
},
|
||||
@ -5170,6 +5179,9 @@ margin-bottom: 20px;
|
||||
"logEnabled" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"useFileTime" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"rgbColor" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
@ -5870,6 +5882,89 @@ margin-bottom: 20px;
|
||||
}
|
||||
},
|
||||
"description" : "Device running state"
|
||||
};
|
||||
defs.EndOfTrainDemodReport = {
|
||||
"properties" : {
|
||||
"channelPowerDB" : {
|
||||
"type" : "number",
|
||||
"format" : "float",
|
||||
"description" : "power received in channel (dB)"
|
||||
},
|
||||
"channelSampleRate" : {
|
||||
"type" : "integer"
|
||||
}
|
||||
},
|
||||
"description" : "EndOfTrainDemod"
|
||||
};
|
||||
defs.EndOfTrainDemodSettings = {
|
||||
"properties" : {
|
||||
"inputFrequencyOffset" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
},
|
||||
"rfBandwidth" : {
|
||||
"type" : "number",
|
||||
"format" : "float"
|
||||
},
|
||||
"fmDeviation" : {
|
||||
"type" : "number",
|
||||
"format" : "float"
|
||||
},
|
||||
"udpEnabled" : {
|
||||
"type" : "integer",
|
||||
"description" : "Whether to forward received packets to specified UDP port"
|
||||
},
|
||||
"udpAddress" : {
|
||||
"type" : "string",
|
||||
"description" : "UDP address to forward received packets to"
|
||||
},
|
||||
"udpPort" : {
|
||||
"type" : "integer",
|
||||
"description" : "UDP port to forward received packets to"
|
||||
},
|
||||
"logFilename" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"logEnabled" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"useFileTime" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"channelMarker" : {
|
||||
"$ref" : "#/definitions/ChannelMarker"
|
||||
},
|
||||
"rollupState" : {
|
||||
"$ref" : "#/definitions/RollupState"
|
||||
}
|
||||
},
|
||||
"description" : "EndOfTrain"
|
||||
};
|
||||
defs.ErrorResponse = {
|
||||
"required" : [ "message" ],
|
||||
@ -10943,7 +11038,7 @@ margin-bottom: 20px;
|
||||
"type" : "integer"
|
||||
}
|
||||
},
|
||||
"description" : "AMDemod"
|
||||
"description" : "PacketDemod"
|
||||
};
|
||||
defs.PacketDemodSettings = {
|
||||
"properties" : {
|
||||
@ -10981,6 +11076,9 @@ margin-bottom: 20px;
|
||||
"logEnabled" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"useFileTime" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"rgbColor" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
@ -12591,6 +12689,9 @@ margin-bottom: 20px;
|
||||
"logEnabled" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"useFileTime" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"rgbColor" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
@ -58672,7 +58773,7 @@ except ApiException as e:
|
||||
</div>
|
||||
<div id="generator">
|
||||
<div class="content">
|
||||
Generated 2024-02-27T15:07:08.970+01:00
|
||||
Generated 2024-03-03T22:27:13.533+01:00
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -50,6 +50,8 @@ SWGAISDemodSettings::SWGAISDemodSettings() {
|
||||
m_log_filename_isSet = false;
|
||||
log_enabled = 0;
|
||||
m_log_enabled_isSet = false;
|
||||
use_file_time = 0;
|
||||
m_use_file_time_isSet = false;
|
||||
rgb_color = 0;
|
||||
m_rgb_color_isSet = false;
|
||||
title = nullptr;
|
||||
@ -102,6 +104,8 @@ SWGAISDemodSettings::init() {
|
||||
m_log_filename_isSet = false;
|
||||
log_enabled = 0;
|
||||
m_log_enabled_isSet = false;
|
||||
use_file_time = 0;
|
||||
m_use_file_time_isSet = false;
|
||||
rgb_color = 0;
|
||||
m_rgb_color_isSet = false;
|
||||
title = new QString("");
|
||||
@ -144,6 +148,7 @@ SWGAISDemodSettings::cleanup() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(title != nullptr) {
|
||||
delete title;
|
||||
}
|
||||
@ -199,6 +204,8 @@ SWGAISDemodSettings::fromJsonObject(QJsonObject &pJson) {
|
||||
|
||||
::SWGSDRangel::setValue(&log_enabled, pJson["logEnabled"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&use_file_time, pJson["useFileTime"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
|
||||
@ -270,6 +277,9 @@ SWGAISDemodSettings::asJsonObject() {
|
||||
if(m_log_enabled_isSet){
|
||||
obj->insert("logEnabled", QJsonValue(log_enabled));
|
||||
}
|
||||
if(m_use_file_time_isSet){
|
||||
obj->insert("useFileTime", QJsonValue(use_file_time));
|
||||
}
|
||||
if(m_rgb_color_isSet){
|
||||
obj->insert("rgbColor", QJsonValue(rgb_color));
|
||||
}
|
||||
@ -417,6 +427,16 @@ SWGAISDemodSettings::setLogEnabled(qint32 log_enabled) {
|
||||
this->m_log_enabled_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGAISDemodSettings::getUseFileTime() {
|
||||
return use_file_time;
|
||||
}
|
||||
void
|
||||
SWGAISDemodSettings::setUseFileTime(qint32 use_file_time) {
|
||||
this->use_file_time = use_file_time;
|
||||
this->m_use_file_time_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGAISDemodSettings::getRgbColor() {
|
||||
return rgb_color;
|
||||
@ -565,6 +585,9 @@ SWGAISDemodSettings::isSet(){
|
||||
if(m_log_enabled_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_use_file_time_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_rgb_color_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
|
@ -78,6 +78,9 @@ public:
|
||||
qint32 getLogEnabled();
|
||||
void setLogEnabled(qint32 log_enabled);
|
||||
|
||||
qint32 getUseFileTime();
|
||||
void setUseFileTime(qint32 use_file_time);
|
||||
|
||||
qint32 getRgbColor();
|
||||
void setRgbColor(qint32 rgb_color);
|
||||
|
||||
@ -148,6 +151,9 @@ private:
|
||||
qint32 log_enabled;
|
||||
bool m_log_enabled_isSet;
|
||||
|
||||
qint32 use_file_time;
|
||||
bool m_use_file_time_isSet;
|
||||
|
||||
qint32 rgb_color;
|
||||
bool m_rgb_color_isSet;
|
||||
|
||||
|
@ -60,6 +60,8 @@ SWGChannelReport::SWGChannelReport() {
|
||||
m_dsc_demod_report_isSet = false;
|
||||
dsd_demod_report = nullptr;
|
||||
m_dsd_demod_report_isSet = false;
|
||||
end_of_train_demod_report = nullptr;
|
||||
m_end_of_train_demod_report_isSet = false;
|
||||
ieee_802_15_4_mod_report = nullptr;
|
||||
m_ieee_802_15_4_mod_report_isSet = false;
|
||||
file_sink_report = nullptr;
|
||||
@ -168,6 +170,8 @@ SWGChannelReport::init() {
|
||||
m_dsc_demod_report_isSet = false;
|
||||
dsd_demod_report = new SWGDSDDemodReport();
|
||||
m_dsd_demod_report_isSet = false;
|
||||
end_of_train_demod_report = new SWGEndOfTrainDemodReport();
|
||||
m_end_of_train_demod_report_isSet = false;
|
||||
ieee_802_15_4_mod_report = new SWGIEEE_802_15_4_ModReport();
|
||||
m_ieee_802_15_4_mod_report_isSet = false;
|
||||
file_sink_report = new SWGFileSinkReport();
|
||||
@ -286,6 +290,9 @@ SWGChannelReport::cleanup() {
|
||||
if(dsd_demod_report != nullptr) {
|
||||
delete dsd_demod_report;
|
||||
}
|
||||
if(end_of_train_demod_report != nullptr) {
|
||||
delete end_of_train_demod_report;
|
||||
}
|
||||
if(ieee_802_15_4_mod_report != nullptr) {
|
||||
delete ieee_802_15_4_mod_report;
|
||||
}
|
||||
@ -433,6 +440,8 @@ SWGChannelReport::fromJsonObject(QJsonObject &pJson) {
|
||||
|
||||
::SWGSDRangel::setValue(&dsd_demod_report, pJson["DSDDemodReport"], "SWGDSDDemodReport", "SWGDSDDemodReport");
|
||||
|
||||
::SWGSDRangel::setValue(&end_of_train_demod_report, pJson["EndOfTrainDemodReport"], "SWGEndOfTrainDemodReport", "SWGEndOfTrainDemodReport");
|
||||
|
||||
::SWGSDRangel::setValue(&ieee_802_15_4_mod_report, pJson["IEEE_802_15_4_ModReport"], "SWGIEEE_802_15_4_ModReport", "SWGIEEE_802_15_4_ModReport");
|
||||
|
||||
::SWGSDRangel::setValue(&file_sink_report, pJson["FileSinkReport"], "SWGFileSinkReport", "SWGFileSinkReport");
|
||||
@ -565,6 +574,9 @@ SWGChannelReport::asJsonObject() {
|
||||
if((dsd_demod_report != nullptr) && (dsd_demod_report->isSet())){
|
||||
toJsonValue(QString("DSDDemodReport"), dsd_demod_report, obj, QString("SWGDSDDemodReport"));
|
||||
}
|
||||
if((end_of_train_demod_report != nullptr) && (end_of_train_demod_report->isSet())){
|
||||
toJsonValue(QString("EndOfTrainDemodReport"), end_of_train_demod_report, obj, QString("SWGEndOfTrainDemodReport"));
|
||||
}
|
||||
if((ieee_802_15_4_mod_report != nullptr) && (ieee_802_15_4_mod_report->isSet())){
|
||||
toJsonValue(QString("IEEE_802_15_4_ModReport"), ieee_802_15_4_mod_report, obj, QString("SWGIEEE_802_15_4_ModReport"));
|
||||
}
|
||||
@ -831,6 +843,16 @@ SWGChannelReport::setDsdDemodReport(SWGDSDDemodReport* dsd_demod_report) {
|
||||
this->m_dsd_demod_report_isSet = true;
|
||||
}
|
||||
|
||||
SWGEndOfTrainDemodReport*
|
||||
SWGChannelReport::getEndOfTrainDemodReport() {
|
||||
return end_of_train_demod_report;
|
||||
}
|
||||
void
|
||||
SWGChannelReport::setEndOfTrainDemodReport(SWGEndOfTrainDemodReport* end_of_train_demod_report) {
|
||||
this->end_of_train_demod_report = end_of_train_demod_report;
|
||||
this->m_end_of_train_demod_report_isSet = true;
|
||||
}
|
||||
|
||||
SWGIEEE_802_15_4_ModReport*
|
||||
SWGChannelReport::getIeee802154ModReport() {
|
||||
return ieee_802_15_4_mod_report;
|
||||
@ -1224,6 +1246,9 @@ SWGChannelReport::isSet(){
|
||||
if(dsd_demod_report && dsd_demod_report->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(end_of_train_demod_report && end_of_train_demod_report->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(ieee_802_15_4_mod_report && ieee_802_15_4_mod_report->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "SWGDOA2Report.h"
|
||||
#include "SWGDSCDemodReport.h"
|
||||
#include "SWGDSDDemodReport.h"
|
||||
#include "SWGEndOfTrainDemodReport.h"
|
||||
#include "SWGFT8DemodReport.h"
|
||||
#include "SWGFileSinkReport.h"
|
||||
#include "SWGFileSourceReport.h"
|
||||
@ -138,6 +139,9 @@ public:
|
||||
SWGDSDDemodReport* getDsdDemodReport();
|
||||
void setDsdDemodReport(SWGDSDDemodReport* dsd_demod_report);
|
||||
|
||||
SWGEndOfTrainDemodReport* getEndOfTrainDemodReport();
|
||||
void setEndOfTrainDemodReport(SWGEndOfTrainDemodReport* end_of_train_demod_report);
|
||||
|
||||
SWGIEEE_802_15_4_ModReport* getIeee802154ModReport();
|
||||
void setIeee802154ModReport(SWGIEEE_802_15_4_ModReport* ieee_802_15_4_mod_report);
|
||||
|
||||
@ -292,6 +296,9 @@ private:
|
||||
SWGDSDDemodReport* dsd_demod_report;
|
||||
bool m_dsd_demod_report_isSet;
|
||||
|
||||
SWGEndOfTrainDemodReport* end_of_train_demod_report;
|
||||
bool m_end_of_train_demod_report_isSet;
|
||||
|
||||
SWGIEEE_802_15_4_ModReport* ieee_802_15_4_mod_report;
|
||||
bool m_ieee_802_15_4_mod_report_isSet;
|
||||
|
||||
|
@ -74,6 +74,8 @@ SWGChannelSettings::SWGChannelSettings() {
|
||||
m_dsc_demod_settings_isSet = false;
|
||||
dsd_demod_settings = nullptr;
|
||||
m_dsd_demod_settings_isSet = false;
|
||||
end_of_train_demod_settings = nullptr;
|
||||
m_end_of_train_demod_settings_isSet = false;
|
||||
file_sink_settings = nullptr;
|
||||
m_file_sink_settings_isSet = false;
|
||||
file_source_settings = nullptr;
|
||||
@ -206,6 +208,8 @@ SWGChannelSettings::init() {
|
||||
m_dsc_demod_settings_isSet = false;
|
||||
dsd_demod_settings = new SWGDSDDemodSettings();
|
||||
m_dsd_demod_settings_isSet = false;
|
||||
end_of_train_demod_settings = new SWGEndOfTrainDemodSettings();
|
||||
m_end_of_train_demod_settings_isSet = false;
|
||||
file_sink_settings = new SWGFileSinkSettings();
|
||||
m_file_sink_settings_isSet = false;
|
||||
file_source_settings = new SWGFileSourceSettings();
|
||||
@ -351,6 +355,9 @@ SWGChannelSettings::cleanup() {
|
||||
if(dsd_demod_settings != nullptr) {
|
||||
delete dsd_demod_settings;
|
||||
}
|
||||
if(end_of_train_demod_settings != nullptr) {
|
||||
delete end_of_train_demod_settings;
|
||||
}
|
||||
if(file_sink_settings != nullptr) {
|
||||
delete file_sink_settings;
|
||||
}
|
||||
@ -527,6 +534,8 @@ SWGChannelSettings::fromJsonObject(QJsonObject &pJson) {
|
||||
|
||||
::SWGSDRangel::setValue(&dsd_demod_settings, pJson["DSDDemodSettings"], "SWGDSDDemodSettings", "SWGDSDDemodSettings");
|
||||
|
||||
::SWGSDRangel::setValue(&end_of_train_demod_settings, pJson["EndOfTrainDemodSettings"], "SWGEndOfTrainDemodSettings", "SWGEndOfTrainDemodSettings");
|
||||
|
||||
::SWGSDRangel::setValue(&file_sink_settings, pJson["FileSinkSettings"], "SWGFileSinkSettings", "SWGFileSinkSettings");
|
||||
|
||||
::SWGSDRangel::setValue(&file_source_settings, pJson["FileSourceSettings"], "SWGFileSourceSettings", "SWGFileSourceSettings");
|
||||
@ -690,6 +699,9 @@ SWGChannelSettings::asJsonObject() {
|
||||
if((dsd_demod_settings != nullptr) && (dsd_demod_settings->isSet())){
|
||||
toJsonValue(QString("DSDDemodSettings"), dsd_demod_settings, obj, QString("SWGDSDDemodSettings"));
|
||||
}
|
||||
if((end_of_train_demod_settings != nullptr) && (end_of_train_demod_settings->isSet())){
|
||||
toJsonValue(QString("EndOfTrainDemodSettings"), end_of_train_demod_settings, obj, QString("SWGEndOfTrainDemodSettings"));
|
||||
}
|
||||
if((file_sink_settings != nullptr) && (file_sink_settings->isSet())){
|
||||
toJsonValue(QString("FileSinkSettings"), file_sink_settings, obj, QString("SWGFileSinkSettings"));
|
||||
}
|
||||
@ -1041,6 +1053,16 @@ SWGChannelSettings::setDsdDemodSettings(SWGDSDDemodSettings* dsd_demod_settings)
|
||||
this->m_dsd_demod_settings_isSet = true;
|
||||
}
|
||||
|
||||
SWGEndOfTrainDemodSettings*
|
||||
SWGChannelSettings::getEndOfTrainDemodSettings() {
|
||||
return end_of_train_demod_settings;
|
||||
}
|
||||
void
|
||||
SWGChannelSettings::setEndOfTrainDemodSettings(SWGEndOfTrainDemodSettings* end_of_train_demod_settings) {
|
||||
this->end_of_train_demod_settings = end_of_train_demod_settings;
|
||||
this->m_end_of_train_demod_settings_isSet = true;
|
||||
}
|
||||
|
||||
SWGFileSinkSettings*
|
||||
SWGChannelSettings::getFileSinkSettings() {
|
||||
return file_sink_settings;
|
||||
@ -1505,6 +1527,9 @@ SWGChannelSettings::isSet(){
|
||||
if(dsd_demod_settings && dsd_demod_settings->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(end_of_train_demod_settings && end_of_train_demod_settings->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(file_sink_settings && file_sink_settings->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "SWGDOA2Settings.h"
|
||||
#include "SWGDSCDemodSettings.h"
|
||||
#include "SWGDSDDemodSettings.h"
|
||||
#include "SWGEndOfTrainDemodSettings.h"
|
||||
#include "SWGFT8DemodSettings.h"
|
||||
#include "SWGFileSinkSettings.h"
|
||||
#include "SWGFileSourceSettings.h"
|
||||
@ -169,6 +170,9 @@ public:
|
||||
SWGDSDDemodSettings* getDsdDemodSettings();
|
||||
void setDsdDemodSettings(SWGDSDDemodSettings* dsd_demod_settings);
|
||||
|
||||
SWGEndOfTrainDemodSettings* getEndOfTrainDemodSettings();
|
||||
void setEndOfTrainDemodSettings(SWGEndOfTrainDemodSettings* end_of_train_demod_settings);
|
||||
|
||||
SWGFileSinkSettings* getFileSinkSettings();
|
||||
void setFileSinkSettings(SWGFileSinkSettings* file_sink_settings);
|
||||
|
||||
@ -359,6 +363,9 @@ private:
|
||||
SWGDSDDemodSettings* dsd_demod_settings;
|
||||
bool m_dsd_demod_settings_isSet;
|
||||
|
||||
SWGEndOfTrainDemodSettings* end_of_train_demod_settings;
|
||||
bool m_end_of_train_demod_settings_isSet;
|
||||
|
||||
SWGFileSinkSettings* file_sink_settings;
|
||||
bool m_file_sink_settings_isSet;
|
||||
|
||||
|
@ -48,6 +48,8 @@ SWGDSCDemodSettings::SWGDSCDemodSettings() {
|
||||
m_log_filename_isSet = false;
|
||||
log_enabled = 0;
|
||||
m_log_enabled_isSet = false;
|
||||
use_file_time = 0;
|
||||
m_use_file_time_isSet = false;
|
||||
rgb_color = 0;
|
||||
m_rgb_color_isSet = false;
|
||||
title = nullptr;
|
||||
@ -98,6 +100,8 @@ SWGDSCDemodSettings::init() {
|
||||
m_log_filename_isSet = false;
|
||||
log_enabled = 0;
|
||||
m_log_enabled_isSet = false;
|
||||
use_file_time = 0;
|
||||
m_use_file_time_isSet = false;
|
||||
rgb_color = 0;
|
||||
m_rgb_color_isSet = false;
|
||||
title = new QString("");
|
||||
@ -141,6 +145,7 @@ SWGDSCDemodSettings::cleanup() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(title != nullptr) {
|
||||
delete title;
|
||||
}
|
||||
@ -194,6 +199,8 @@ SWGDSCDemodSettings::fromJsonObject(QJsonObject &pJson) {
|
||||
|
||||
::SWGSDRangel::setValue(&log_enabled, pJson["logEnabled"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&use_file_time, pJson["useFileTime"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
|
||||
@ -262,6 +269,9 @@ SWGDSCDemodSettings::asJsonObject() {
|
||||
if(m_log_enabled_isSet){
|
||||
obj->insert("logEnabled", QJsonValue(log_enabled));
|
||||
}
|
||||
if(m_use_file_time_isSet){
|
||||
obj->insert("useFileTime", QJsonValue(use_file_time));
|
||||
}
|
||||
if(m_rgb_color_isSet){
|
||||
obj->insert("rgbColor", QJsonValue(rgb_color));
|
||||
}
|
||||
@ -399,6 +409,16 @@ SWGDSCDemodSettings::setLogEnabled(qint32 log_enabled) {
|
||||
this->m_log_enabled_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGDSCDemodSettings::getUseFileTime() {
|
||||
return use_file_time;
|
||||
}
|
||||
void
|
||||
SWGDSCDemodSettings::setUseFileTime(qint32 use_file_time) {
|
||||
this->use_file_time = use_file_time;
|
||||
this->m_use_file_time_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGDSCDemodSettings::getRgbColor() {
|
||||
return rgb_color;
|
||||
@ -544,6 +564,9 @@ SWGDSCDemodSettings::isSet(){
|
||||
if(m_log_enabled_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_use_file_time_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_rgb_color_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
|
@ -75,6 +75,9 @@ public:
|
||||
qint32 getLogEnabled();
|
||||
void setLogEnabled(qint32 log_enabled);
|
||||
|
||||
qint32 getUseFileTime();
|
||||
void setUseFileTime(qint32 use_file_time);
|
||||
|
||||
qint32 getRgbColor();
|
||||
void setRgbColor(qint32 rgb_color);
|
||||
|
||||
@ -142,6 +145,9 @@ private:
|
||||
qint32 log_enabled;
|
||||
bool m_log_enabled_isSet;
|
||||
|
||||
qint32 use_file_time;
|
||||
bool m_use_file_time_isSet;
|
||||
|
||||
qint32 rgb_color;
|
||||
bool m_rgb_color_isSet;
|
||||
|
||||
|
131
swagger/sdrangel/code/qt5/client/SWGEndOfTrainDemodReport.cpp
Normal file
131
swagger/sdrangel/code/qt5/client/SWGEndOfTrainDemodReport.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
/**
|
||||
* SDRangel
|
||||
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
|
||||
*
|
||||
* OpenAPI spec version: 7.0.0
|
||||
* Contact: f4exb06@gmail.com
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
#include "SWGEndOfTrainDemodReport.h"
|
||||
|
||||
#include "SWGHelpers.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
|
||||
namespace SWGSDRangel {
|
||||
|
||||
SWGEndOfTrainDemodReport::SWGEndOfTrainDemodReport(QString* json) {
|
||||
init();
|
||||
this->fromJson(*json);
|
||||
}
|
||||
|
||||
SWGEndOfTrainDemodReport::SWGEndOfTrainDemodReport() {
|
||||
channel_power_db = 0.0f;
|
||||
m_channel_power_db_isSet = false;
|
||||
channel_sample_rate = 0;
|
||||
m_channel_sample_rate_isSet = false;
|
||||
}
|
||||
|
||||
SWGEndOfTrainDemodReport::~SWGEndOfTrainDemodReport() {
|
||||
this->cleanup();
|
||||
}
|
||||
|
||||
void
|
||||
SWGEndOfTrainDemodReport::init() {
|
||||
channel_power_db = 0.0f;
|
||||
m_channel_power_db_isSet = false;
|
||||
channel_sample_rate = 0;
|
||||
m_channel_sample_rate_isSet = false;
|
||||
}
|
||||
|
||||
void
|
||||
SWGEndOfTrainDemodReport::cleanup() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
SWGEndOfTrainDemodReport*
|
||||
SWGEndOfTrainDemodReport::fromJson(QString &json) {
|
||||
QByteArray array (json.toStdString().c_str());
|
||||
QJsonDocument doc = QJsonDocument::fromJson(array);
|
||||
QJsonObject jsonObject = doc.object();
|
||||
this->fromJsonObject(jsonObject);
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
SWGEndOfTrainDemodReport::fromJsonObject(QJsonObject &pJson) {
|
||||
::SWGSDRangel::setValue(&channel_power_db, pJson["channelPowerDB"], "float", "");
|
||||
|
||||
::SWGSDRangel::setValue(&channel_sample_rate, pJson["channelSampleRate"], "qint32", "");
|
||||
|
||||
}
|
||||
|
||||
QString
|
||||
SWGEndOfTrainDemodReport::asJson ()
|
||||
{
|
||||
QJsonObject* obj = this->asJsonObject();
|
||||
|
||||
QJsonDocument doc(*obj);
|
||||
QByteArray bytes = doc.toJson();
|
||||
delete obj;
|
||||
return QString(bytes);
|
||||
}
|
||||
|
||||
QJsonObject*
|
||||
SWGEndOfTrainDemodReport::asJsonObject() {
|
||||
QJsonObject* obj = new QJsonObject();
|
||||
if(m_channel_power_db_isSet){
|
||||
obj->insert("channelPowerDB", QJsonValue(channel_power_db));
|
||||
}
|
||||
if(m_channel_sample_rate_isSet){
|
||||
obj->insert("channelSampleRate", QJsonValue(channel_sample_rate));
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
float
|
||||
SWGEndOfTrainDemodReport::getChannelPowerDb() {
|
||||
return channel_power_db;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodReport::setChannelPowerDb(float channel_power_db) {
|
||||
this->channel_power_db = channel_power_db;
|
||||
this->m_channel_power_db_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGEndOfTrainDemodReport::getChannelSampleRate() {
|
||||
return channel_sample_rate;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodReport::setChannelSampleRate(qint32 channel_sample_rate) {
|
||||
this->channel_sample_rate = channel_sample_rate;
|
||||
this->m_channel_sample_rate_isSet = true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SWGEndOfTrainDemodReport::isSet(){
|
||||
bool isObjectUpdated = false;
|
||||
do{
|
||||
if(m_channel_power_db_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_channel_sample_rate_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
}while(false);
|
||||
return isObjectUpdated;
|
||||
}
|
||||
}
|
||||
|
64
swagger/sdrangel/code/qt5/client/SWGEndOfTrainDemodReport.h
Normal file
64
swagger/sdrangel/code/qt5/client/SWGEndOfTrainDemodReport.h
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* SDRangel
|
||||
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
|
||||
*
|
||||
* OpenAPI spec version: 7.0.0
|
||||
* Contact: f4exb06@gmail.com
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SWGEndOfTrainDemodReport.h
|
||||
*
|
||||
* EndOfTrainDemod
|
||||
*/
|
||||
|
||||
#ifndef SWGEndOfTrainDemodReport_H_
|
||||
#define SWGEndOfTrainDemodReport_H_
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
|
||||
|
||||
#include "SWGObject.h"
|
||||
#include "export.h"
|
||||
|
||||
namespace SWGSDRangel {
|
||||
|
||||
class SWG_API SWGEndOfTrainDemodReport: public SWGObject {
|
||||
public:
|
||||
SWGEndOfTrainDemodReport();
|
||||
SWGEndOfTrainDemodReport(QString* json);
|
||||
virtual ~SWGEndOfTrainDemodReport();
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
virtual QString asJson () override;
|
||||
virtual QJsonObject* asJsonObject() override;
|
||||
virtual void fromJsonObject(QJsonObject &json) override;
|
||||
virtual SWGEndOfTrainDemodReport* fromJson(QString &jsonString) override;
|
||||
|
||||
float getChannelPowerDb();
|
||||
void setChannelPowerDb(float channel_power_db);
|
||||
|
||||
qint32 getChannelSampleRate();
|
||||
void setChannelSampleRate(qint32 channel_sample_rate);
|
||||
|
||||
|
||||
virtual bool isSet() override;
|
||||
|
||||
private:
|
||||
float channel_power_db;
|
||||
bool m_channel_power_db_isSet;
|
||||
|
||||
qint32 channel_sample_rate;
|
||||
bool m_channel_sample_rate_isSet;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* SWGEndOfTrainDemodReport_H_ */
|
534
swagger/sdrangel/code/qt5/client/SWGEndOfTrainDemodSettings.cpp
Normal file
534
swagger/sdrangel/code/qt5/client/SWGEndOfTrainDemodSettings.cpp
Normal file
@ -0,0 +1,534 @@
|
||||
/**
|
||||
* SDRangel
|
||||
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
|
||||
*
|
||||
* OpenAPI spec version: 7.0.0
|
||||
* Contact: f4exb06@gmail.com
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
#include "SWGEndOfTrainDemodSettings.h"
|
||||
|
||||
#include "SWGHelpers.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
|
||||
namespace SWGSDRangel {
|
||||
|
||||
SWGEndOfTrainDemodSettings::SWGEndOfTrainDemodSettings(QString* json) {
|
||||
init();
|
||||
this->fromJson(*json);
|
||||
}
|
||||
|
||||
SWGEndOfTrainDemodSettings::SWGEndOfTrainDemodSettings() {
|
||||
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;
|
||||
udp_enabled = 0;
|
||||
m_udp_enabled_isSet = false;
|
||||
udp_address = nullptr;
|
||||
m_udp_address_isSet = false;
|
||||
udp_port = 0;
|
||||
m_udp_port_isSet = false;
|
||||
log_filename = nullptr;
|
||||
m_log_filename_isSet = false;
|
||||
log_enabled = 0;
|
||||
m_log_enabled_isSet = false;
|
||||
use_file_time = 0;
|
||||
m_use_file_time_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;
|
||||
channel_marker = nullptr;
|
||||
m_channel_marker_isSet = false;
|
||||
rollup_state = nullptr;
|
||||
m_rollup_state_isSet = false;
|
||||
}
|
||||
|
||||
SWGEndOfTrainDemodSettings::~SWGEndOfTrainDemodSettings() {
|
||||
this->cleanup();
|
||||
}
|
||||
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::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;
|
||||
udp_enabled = 0;
|
||||
m_udp_enabled_isSet = false;
|
||||
udp_address = new QString("");
|
||||
m_udp_address_isSet = false;
|
||||
udp_port = 0;
|
||||
m_udp_port_isSet = false;
|
||||
log_filename = new QString("");
|
||||
m_log_filename_isSet = false;
|
||||
log_enabled = 0;
|
||||
m_log_enabled_isSet = false;
|
||||
use_file_time = 0;
|
||||
m_use_file_time_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;
|
||||
channel_marker = new SWGChannelMarker();
|
||||
m_channel_marker_isSet = false;
|
||||
rollup_state = new SWGRollupState();
|
||||
m_rollup_state_isSet = false;
|
||||
}
|
||||
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::cleanup() {
|
||||
|
||||
|
||||
|
||||
|
||||
if(udp_address != nullptr) {
|
||||
delete udp_address;
|
||||
}
|
||||
|
||||
if(log_filename != nullptr) {
|
||||
delete log_filename;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(title != nullptr) {
|
||||
delete title;
|
||||
}
|
||||
|
||||
|
||||
if(reverse_api_address != nullptr) {
|
||||
delete reverse_api_address;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(channel_marker != nullptr) {
|
||||
delete channel_marker;
|
||||
}
|
||||
if(rollup_state != nullptr) {
|
||||
delete rollup_state;
|
||||
}
|
||||
}
|
||||
|
||||
SWGEndOfTrainDemodSettings*
|
||||
SWGEndOfTrainDemodSettings::fromJson(QString &json) {
|
||||
QByteArray array (json.toStdString().c_str());
|
||||
QJsonDocument doc = QJsonDocument::fromJson(array);
|
||||
QJsonObject jsonObject = doc.object();
|
||||
this->fromJsonObject(jsonObject);
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::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(&udp_enabled, pJson["udpEnabled"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&udp_address, pJson["udpAddress"], "QString", "QString");
|
||||
|
||||
::SWGSDRangel::setValue(&udp_port, pJson["udpPort"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&log_filename, pJson["logFilename"], "QString", "QString");
|
||||
|
||||
::SWGSDRangel::setValue(&log_enabled, pJson["logEnabled"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&use_file_time, pJson["useFileTime"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
|
||||
|
||||
::SWGSDRangel::setValue(&stream_index, pJson["streamIndex"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString");
|
||||
|
||||
::SWGSDRangel::setValue(&reverse_api_port, pJson["reverseAPIPort"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&reverse_api_device_index, pJson["reverseAPIDeviceIndex"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&reverse_api_channel_index, pJson["reverseAPIChannelIndex"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&channel_marker, pJson["channelMarker"], "SWGChannelMarker", "SWGChannelMarker");
|
||||
|
||||
::SWGSDRangel::setValue(&rollup_state, pJson["rollupState"], "SWGRollupState", "SWGRollupState");
|
||||
|
||||
}
|
||||
|
||||
QString
|
||||
SWGEndOfTrainDemodSettings::asJson ()
|
||||
{
|
||||
QJsonObject* obj = this->asJsonObject();
|
||||
|
||||
QJsonDocument doc(*obj);
|
||||
QByteArray bytes = doc.toJson();
|
||||
delete obj;
|
||||
return QString(bytes);
|
||||
}
|
||||
|
||||
QJsonObject*
|
||||
SWGEndOfTrainDemodSettings::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_udp_enabled_isSet){
|
||||
obj->insert("udpEnabled", QJsonValue(udp_enabled));
|
||||
}
|
||||
if(udp_address != nullptr && *udp_address != QString("")){
|
||||
toJsonValue(QString("udpAddress"), udp_address, obj, QString("QString"));
|
||||
}
|
||||
if(m_udp_port_isSet){
|
||||
obj->insert("udpPort", QJsonValue(udp_port));
|
||||
}
|
||||
if(log_filename != nullptr && *log_filename != QString("")){
|
||||
toJsonValue(QString("logFilename"), log_filename, obj, QString("QString"));
|
||||
}
|
||||
if(m_log_enabled_isSet){
|
||||
obj->insert("logEnabled", QJsonValue(log_enabled));
|
||||
}
|
||||
if(m_use_file_time_isSet){
|
||||
obj->insert("useFileTime", QJsonValue(use_file_time));
|
||||
}
|
||||
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));
|
||||
}
|
||||
if((channel_marker != nullptr) && (channel_marker->isSet())){
|
||||
toJsonValue(QString("channelMarker"), channel_marker, obj, QString("SWGChannelMarker"));
|
||||
}
|
||||
if((rollup_state != nullptr) && (rollup_state->isSet())){
|
||||
toJsonValue(QString("rollupState"), rollup_state, obj, QString("SWGRollupState"));
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
qint64
|
||||
SWGEndOfTrainDemodSettings::getInputFrequencyOffset() {
|
||||
return input_frequency_offset;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setInputFrequencyOffset(qint64 input_frequency_offset) {
|
||||
this->input_frequency_offset = input_frequency_offset;
|
||||
this->m_input_frequency_offset_isSet = true;
|
||||
}
|
||||
|
||||
float
|
||||
SWGEndOfTrainDemodSettings::getRfBandwidth() {
|
||||
return rf_bandwidth;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setRfBandwidth(float rf_bandwidth) {
|
||||
this->rf_bandwidth = rf_bandwidth;
|
||||
this->m_rf_bandwidth_isSet = true;
|
||||
}
|
||||
|
||||
float
|
||||
SWGEndOfTrainDemodSettings::getFmDeviation() {
|
||||
return fm_deviation;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setFmDeviation(float fm_deviation) {
|
||||
this->fm_deviation = fm_deviation;
|
||||
this->m_fm_deviation_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGEndOfTrainDemodSettings::getUdpEnabled() {
|
||||
return udp_enabled;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setUdpEnabled(qint32 udp_enabled) {
|
||||
this->udp_enabled = udp_enabled;
|
||||
this->m_udp_enabled_isSet = true;
|
||||
}
|
||||
|
||||
QString*
|
||||
SWGEndOfTrainDemodSettings::getUdpAddress() {
|
||||
return udp_address;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setUdpAddress(QString* udp_address) {
|
||||
this->udp_address = udp_address;
|
||||
this->m_udp_address_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGEndOfTrainDemodSettings::getUdpPort() {
|
||||
return udp_port;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setUdpPort(qint32 udp_port) {
|
||||
this->udp_port = udp_port;
|
||||
this->m_udp_port_isSet = true;
|
||||
}
|
||||
|
||||
QString*
|
||||
SWGEndOfTrainDemodSettings::getLogFilename() {
|
||||
return log_filename;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setLogFilename(QString* log_filename) {
|
||||
this->log_filename = log_filename;
|
||||
this->m_log_filename_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGEndOfTrainDemodSettings::getLogEnabled() {
|
||||
return log_enabled;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setLogEnabled(qint32 log_enabled) {
|
||||
this->log_enabled = log_enabled;
|
||||
this->m_log_enabled_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGEndOfTrainDemodSettings::getUseFileTime() {
|
||||
return use_file_time;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setUseFileTime(qint32 use_file_time) {
|
||||
this->use_file_time = use_file_time;
|
||||
this->m_use_file_time_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGEndOfTrainDemodSettings::getRgbColor() {
|
||||
return rgb_color;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setRgbColor(qint32 rgb_color) {
|
||||
this->rgb_color = rgb_color;
|
||||
this->m_rgb_color_isSet = true;
|
||||
}
|
||||
|
||||
QString*
|
||||
SWGEndOfTrainDemodSettings::getTitle() {
|
||||
return title;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setTitle(QString* title) {
|
||||
this->title = title;
|
||||
this->m_title_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGEndOfTrainDemodSettings::getStreamIndex() {
|
||||
return stream_index;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setStreamIndex(qint32 stream_index) {
|
||||
this->stream_index = stream_index;
|
||||
this->m_stream_index_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGEndOfTrainDemodSettings::getUseReverseApi() {
|
||||
return use_reverse_api;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setUseReverseApi(qint32 use_reverse_api) {
|
||||
this->use_reverse_api = use_reverse_api;
|
||||
this->m_use_reverse_api_isSet = true;
|
||||
}
|
||||
|
||||
QString*
|
||||
SWGEndOfTrainDemodSettings::getReverseApiAddress() {
|
||||
return reverse_api_address;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setReverseApiAddress(QString* reverse_api_address) {
|
||||
this->reverse_api_address = reverse_api_address;
|
||||
this->m_reverse_api_address_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGEndOfTrainDemodSettings::getReverseApiPort() {
|
||||
return reverse_api_port;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setReverseApiPort(qint32 reverse_api_port) {
|
||||
this->reverse_api_port = reverse_api_port;
|
||||
this->m_reverse_api_port_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGEndOfTrainDemodSettings::getReverseApiDeviceIndex() {
|
||||
return reverse_api_device_index;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) {
|
||||
this->reverse_api_device_index = reverse_api_device_index;
|
||||
this->m_reverse_api_device_index_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGEndOfTrainDemodSettings::getReverseApiChannelIndex() {
|
||||
return reverse_api_channel_index;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setReverseApiChannelIndex(qint32 reverse_api_channel_index) {
|
||||
this->reverse_api_channel_index = reverse_api_channel_index;
|
||||
this->m_reverse_api_channel_index_isSet = true;
|
||||
}
|
||||
|
||||
SWGChannelMarker*
|
||||
SWGEndOfTrainDemodSettings::getChannelMarker() {
|
||||
return channel_marker;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setChannelMarker(SWGChannelMarker* channel_marker) {
|
||||
this->channel_marker = channel_marker;
|
||||
this->m_channel_marker_isSet = true;
|
||||
}
|
||||
|
||||
SWGRollupState*
|
||||
SWGEndOfTrainDemodSettings::getRollupState() {
|
||||
return rollup_state;
|
||||
}
|
||||
void
|
||||
SWGEndOfTrainDemodSettings::setRollupState(SWGRollupState* rollup_state) {
|
||||
this->rollup_state = rollup_state;
|
||||
this->m_rollup_state_isSet = true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SWGEndOfTrainDemodSettings::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_udp_enabled_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(udp_address && *udp_address != QString("")){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_udp_port_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(log_filename && *log_filename != QString("")){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_log_enabled_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_use_file_time_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;
|
||||
}
|
||||
if(channel_marker && channel_marker->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(rollup_state && rollup_state->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
}while(false);
|
||||
return isObjectUpdated;
|
||||
}
|
||||
}
|
||||
|
169
swagger/sdrangel/code/qt5/client/SWGEndOfTrainDemodSettings.h
Normal file
169
swagger/sdrangel/code/qt5/client/SWGEndOfTrainDemodSettings.h
Normal file
@ -0,0 +1,169 @@
|
||||
/**
|
||||
* SDRangel
|
||||
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
|
||||
*
|
||||
* OpenAPI spec version: 7.0.0
|
||||
* Contact: f4exb06@gmail.com
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SWGEndOfTrainDemodSettings.h
|
||||
*
|
||||
* EndOfTrain
|
||||
*/
|
||||
|
||||
#ifndef SWGEndOfTrainDemodSettings_H_
|
||||
#define SWGEndOfTrainDemodSettings_H_
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
|
||||
#include "SWGChannelMarker.h"
|
||||
#include "SWGRollupState.h"
|
||||
#include <QString>
|
||||
|
||||
#include "SWGObject.h"
|
||||
#include "export.h"
|
||||
|
||||
namespace SWGSDRangel {
|
||||
|
||||
class SWG_API SWGEndOfTrainDemodSettings: public SWGObject {
|
||||
public:
|
||||
SWGEndOfTrainDemodSettings();
|
||||
SWGEndOfTrainDemodSettings(QString* json);
|
||||
virtual ~SWGEndOfTrainDemodSettings();
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
virtual QString asJson () override;
|
||||
virtual QJsonObject* asJsonObject() override;
|
||||
virtual void fromJsonObject(QJsonObject &json) override;
|
||||
virtual SWGEndOfTrainDemodSettings* 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);
|
||||
|
||||
qint32 getUdpEnabled();
|
||||
void setUdpEnabled(qint32 udp_enabled);
|
||||
|
||||
QString* getUdpAddress();
|
||||
void setUdpAddress(QString* udp_address);
|
||||
|
||||
qint32 getUdpPort();
|
||||
void setUdpPort(qint32 udp_port);
|
||||
|
||||
QString* getLogFilename();
|
||||
void setLogFilename(QString* log_filename);
|
||||
|
||||
qint32 getLogEnabled();
|
||||
void setLogEnabled(qint32 log_enabled);
|
||||
|
||||
qint32 getUseFileTime();
|
||||
void setUseFileTime(qint32 use_file_time);
|
||||
|
||||
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);
|
||||
|
||||
SWGChannelMarker* getChannelMarker();
|
||||
void setChannelMarker(SWGChannelMarker* channel_marker);
|
||||
|
||||
SWGRollupState* getRollupState();
|
||||
void setRollupState(SWGRollupState* rollup_state);
|
||||
|
||||
|
||||
virtual bool isSet() override;
|
||||
|
||||
private:
|
||||
qint64 input_frequency_offset;
|
||||
bool m_input_frequency_offset_isSet;
|
||||
|
||||
float rf_bandwidth;
|
||||
bool m_rf_bandwidth_isSet;
|
||||
|
||||
float fm_deviation;
|
||||
bool m_fm_deviation_isSet;
|
||||
|
||||
qint32 udp_enabled;
|
||||
bool m_udp_enabled_isSet;
|
||||
|
||||
QString* udp_address;
|
||||
bool m_udp_address_isSet;
|
||||
|
||||
qint32 udp_port;
|
||||
bool m_udp_port_isSet;
|
||||
|
||||
QString* log_filename;
|
||||
bool m_log_filename_isSet;
|
||||
|
||||
qint32 log_enabled;
|
||||
bool m_log_enabled_isSet;
|
||||
|
||||
qint32 use_file_time;
|
||||
bool m_use_file_time_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;
|
||||
|
||||
SWGChannelMarker* channel_marker;
|
||||
bool m_channel_marker_isSet;
|
||||
|
||||
SWGRollupState* rollup_state;
|
||||
bool m_rollup_state_isSet;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* SWGEndOfTrainDemodSettings_H_ */
|
@ -121,6 +121,8 @@
|
||||
#include "SWGDeviceSetList.h"
|
||||
#include "SWGDeviceSettings.h"
|
||||
#include "SWGDeviceState.h"
|
||||
#include "SWGEndOfTrainDemodReport.h"
|
||||
#include "SWGEndOfTrainDemodSettings.h"
|
||||
#include "SWGErrorResponse.h"
|
||||
#include "SWGFCDProPlusSettings.h"
|
||||
#include "SWGFCDProSettings.h"
|
||||
@ -915,6 +917,16 @@ namespace SWGSDRangel {
|
||||
obj->init();
|
||||
return obj;
|
||||
}
|
||||
if(QString("SWGEndOfTrainDemodReport").compare(type) == 0) {
|
||||
SWGEndOfTrainDemodReport *obj = new SWGEndOfTrainDemodReport();
|
||||
obj->init();
|
||||
return obj;
|
||||
}
|
||||
if(QString("SWGEndOfTrainDemodSettings").compare(type) == 0) {
|
||||
SWGEndOfTrainDemodSettings *obj = new SWGEndOfTrainDemodSettings();
|
||||
obj->init();
|
||||
return obj;
|
||||
}
|
||||
if(QString("SWGErrorResponse").compare(type) == 0) {
|
||||
SWGErrorResponse *obj = new SWGErrorResponse();
|
||||
obj->init();
|
||||
|
@ -13,7 +13,7 @@
|
||||
/*
|
||||
* SWGPacketDemodReport.h
|
||||
*
|
||||
* AMDemod
|
||||
* PacketDemod
|
||||
*/
|
||||
|
||||
#ifndef SWGPacketDemodReport_H_
|
||||
|
@ -46,6 +46,8 @@ SWGPacketDemodSettings::SWGPacketDemodSettings() {
|
||||
m_log_filename_isSet = false;
|
||||
log_enabled = 0;
|
||||
m_log_enabled_isSet = false;
|
||||
use_file_time = 0;
|
||||
m_use_file_time_isSet = false;
|
||||
rgb_color = 0;
|
||||
m_rgb_color_isSet = false;
|
||||
title = nullptr;
|
||||
@ -92,6 +94,8 @@ SWGPacketDemodSettings::init() {
|
||||
m_log_filename_isSet = false;
|
||||
log_enabled = 0;
|
||||
m_log_enabled_isSet = false;
|
||||
use_file_time = 0;
|
||||
m_use_file_time_isSet = false;
|
||||
rgb_color = 0;
|
||||
m_rgb_color_isSet = false;
|
||||
title = new QString("");
|
||||
@ -130,6 +134,7 @@ SWGPacketDemodSettings::cleanup() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(title != nullptr) {
|
||||
delete title;
|
||||
}
|
||||
@ -178,6 +183,8 @@ SWGPacketDemodSettings::fromJsonObject(QJsonObject &pJson) {
|
||||
|
||||
::SWGSDRangel::setValue(&log_enabled, pJson["logEnabled"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&use_file_time, pJson["useFileTime"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
|
||||
@ -241,6 +248,9 @@ SWGPacketDemodSettings::asJsonObject() {
|
||||
if(m_log_enabled_isSet){
|
||||
obj->insert("logEnabled", QJsonValue(log_enabled));
|
||||
}
|
||||
if(m_use_file_time_isSet){
|
||||
obj->insert("useFileTime", QJsonValue(use_file_time));
|
||||
}
|
||||
if(m_rgb_color_isSet){
|
||||
obj->insert("rgbColor", QJsonValue(rgb_color));
|
||||
}
|
||||
@ -365,6 +375,16 @@ SWGPacketDemodSettings::setLogEnabled(qint32 log_enabled) {
|
||||
this->m_log_enabled_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGPacketDemodSettings::getUseFileTime() {
|
||||
return use_file_time;
|
||||
}
|
||||
void
|
||||
SWGPacketDemodSettings::setUseFileTime(qint32 use_file_time) {
|
||||
this->use_file_time = use_file_time;
|
||||
this->m_use_file_time_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGPacketDemodSettings::getRgbColor() {
|
||||
return rgb_color;
|
||||
@ -497,6 +517,9 @@ SWGPacketDemodSettings::isSet(){
|
||||
if(m_log_enabled_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_use_file_time_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_rgb_color_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
|
@ -71,6 +71,9 @@ public:
|
||||
qint32 getLogEnabled();
|
||||
void setLogEnabled(qint32 log_enabled);
|
||||
|
||||
qint32 getUseFileTime();
|
||||
void setUseFileTime(qint32 use_file_time);
|
||||
|
||||
qint32 getRgbColor();
|
||||
void setRgbColor(qint32 rgb_color);
|
||||
|
||||
@ -132,6 +135,9 @@ private:
|
||||
qint32 log_enabled;
|
||||
bool m_log_enabled_isSet;
|
||||
|
||||
qint32 use_file_time;
|
||||
bool m_use_file_time_isSet;
|
||||
|
||||
qint32 rgb_color;
|
||||
bool m_rgb_color_isSet;
|
||||
|
||||
|
@ -48,6 +48,8 @@ SWGRadiosondeDemodSettings::SWGRadiosondeDemodSettings() {
|
||||
m_log_filename_isSet = false;
|
||||
log_enabled = 0;
|
||||
m_log_enabled_isSet = false;
|
||||
use_file_time = 0;
|
||||
m_use_file_time_isSet = false;
|
||||
rgb_color = 0;
|
||||
m_rgb_color_isSet = false;
|
||||
title = nullptr;
|
||||
@ -98,6 +100,8 @@ SWGRadiosondeDemodSettings::init() {
|
||||
m_log_filename_isSet = false;
|
||||
log_enabled = 0;
|
||||
m_log_enabled_isSet = false;
|
||||
use_file_time = 0;
|
||||
m_use_file_time_isSet = false;
|
||||
rgb_color = 0;
|
||||
m_rgb_color_isSet = false;
|
||||
title = new QString("");
|
||||
@ -139,6 +143,7 @@ SWGRadiosondeDemodSettings::cleanup() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(title != nullptr) {
|
||||
delete title;
|
||||
}
|
||||
@ -192,6 +197,8 @@ SWGRadiosondeDemodSettings::fromJsonObject(QJsonObject &pJson) {
|
||||
|
||||
::SWGSDRangel::setValue(&log_enabled, pJson["logEnabled"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&use_file_time, pJson["useFileTime"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
|
||||
@ -260,6 +267,9 @@ SWGRadiosondeDemodSettings::asJsonObject() {
|
||||
if(m_log_enabled_isSet){
|
||||
obj->insert("logEnabled", QJsonValue(log_enabled));
|
||||
}
|
||||
if(m_use_file_time_isSet){
|
||||
obj->insert("useFileTime", QJsonValue(use_file_time));
|
||||
}
|
||||
if(m_rgb_color_isSet){
|
||||
obj->insert("rgbColor", QJsonValue(rgb_color));
|
||||
}
|
||||
@ -397,6 +407,16 @@ SWGRadiosondeDemodSettings::setLogEnabled(qint32 log_enabled) {
|
||||
this->m_log_enabled_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGRadiosondeDemodSettings::getUseFileTime() {
|
||||
return use_file_time;
|
||||
}
|
||||
void
|
||||
SWGRadiosondeDemodSettings::setUseFileTime(qint32 use_file_time) {
|
||||
this->use_file_time = use_file_time;
|
||||
this->m_use_file_time_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGRadiosondeDemodSettings::getRgbColor() {
|
||||
return rgb_color;
|
||||
@ -542,6 +562,9 @@ SWGRadiosondeDemodSettings::isSet(){
|
||||
if(m_log_enabled_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_use_file_time_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_rgb_color_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
|
@ -75,6 +75,9 @@ public:
|
||||
qint32 getLogEnabled();
|
||||
void setLogEnabled(qint32 log_enabled);
|
||||
|
||||
qint32 getUseFileTime();
|
||||
void setUseFileTime(qint32 use_file_time);
|
||||
|
||||
qint32 getRgbColor();
|
||||
void setRgbColor(qint32 rgb_color);
|
||||
|
||||
@ -142,6 +145,9 @@ private:
|
||||
qint32 log_enabled;
|
||||
bool m_log_enabled_isSet;
|
||||
|
||||
qint32 use_file_time;
|
||||
bool m_use_file_time_isSet;
|
||||
|
||||
qint32 rgb_color;
|
||||
bool m_rgb_color_isSet;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user