mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-09-08 08:07:54 -04:00
M17: implemented APRS
This commit is contained in:
parent
b69275949a
commit
3cf3938757
@ -45,6 +45,7 @@
|
|||||||
|
|
||||||
MESSAGE_CLASS_DEFINITION(M17Demod::MsgConfigureM17Demod, Message)
|
MESSAGE_CLASS_DEFINITION(M17Demod::MsgConfigureM17Demod, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(M17Demod::MsgReportSMS, Message)
|
MESSAGE_CLASS_DEFINITION(M17Demod::MsgReportSMS, Message)
|
||||||
|
MESSAGE_CLASS_DEFINITION(M17Demod::MsgReportAPRS, Message)
|
||||||
|
|
||||||
const char* const M17Demod::m_channelIdURI = "sdrangel.channel.m17demod";
|
const char* const M17Demod::m_channelIdURI = "sdrangel.channel.m17demod";
|
||||||
const char* const M17Demod::m_channelId = "M17Demod";
|
const char* const M17Demod::m_channelId = "M17Demod";
|
||||||
@ -185,6 +186,27 @@ bool M17Demod::handleMessage(const Message& cmd)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (MsgReportAPRS::match(cmd))
|
||||||
|
{
|
||||||
|
MsgReportAPRS& report = (MsgReportAPRS&) cmd;
|
||||||
|
// Forward to GUI if any
|
||||||
|
if (getMessageQueueToGUI()) {
|
||||||
|
getMessageQueueToGUI()->push(new MsgReportAPRS(report));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward to APRS and other packet features
|
||||||
|
QList<ObjectPipe*> packetsPipes;
|
||||||
|
MainCore::instance()->getMessagePipes().getMessagePipes(this, "packets", packetsPipes);
|
||||||
|
|
||||||
|
for (const auto& pipe : packetsPipes)
|
||||||
|
{
|
||||||
|
MessageQueue *messageQueue = qobject_cast<MessageQueue*>(pipe->m_element);
|
||||||
|
MainCore::MsgPacket *msg = MainCore::MsgPacket::create(this, report.getPacket(), QDateTime::currentDateTime());
|
||||||
|
messageQueue->push(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -85,6 +85,67 @@ public:
|
|||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MsgReportAPRS : public Message {
|
||||||
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
|
public:
|
||||||
|
const QString& getSource() const { return m_source; }
|
||||||
|
const QString& getDest() const { return m_dest; }
|
||||||
|
const QString& getFrom() const { return m_from; }
|
||||||
|
const QString& getTo() const { return m_to; }
|
||||||
|
const QString& getVia() const { return m_via; }
|
||||||
|
const QString& getType() const { return m_type; }
|
||||||
|
const QString& getPID() const { return m_pid; }
|
||||||
|
const QString& getData() const { return m_data; }
|
||||||
|
QByteArray& getPacket() { return m_packet; }
|
||||||
|
|
||||||
|
static MsgReportAPRS* create(
|
||||||
|
const QString& source,
|
||||||
|
const QString& dest,
|
||||||
|
const QString& from,
|
||||||
|
const QString& to,
|
||||||
|
const QString& via,
|
||||||
|
const QString& type,
|
||||||
|
const QString& pid,
|
||||||
|
const QString& data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return new MsgReportAPRS(source, dest, from, to, via, type, pid, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_source;
|
||||||
|
QString m_dest;
|
||||||
|
QString m_from;
|
||||||
|
QString m_to;
|
||||||
|
QString m_via;
|
||||||
|
QString m_type;
|
||||||
|
QString m_pid;
|
||||||
|
QString m_data;
|
||||||
|
QByteArray m_packet;
|
||||||
|
|
||||||
|
MsgReportAPRS(
|
||||||
|
const QString& source,
|
||||||
|
const QString& dest,
|
||||||
|
const QString& from,
|
||||||
|
const QString& to,
|
||||||
|
const QString& via,
|
||||||
|
const QString& type,
|
||||||
|
const QString& pid,
|
||||||
|
const QString& data
|
||||||
|
) :
|
||||||
|
Message(),
|
||||||
|
m_source(source),
|
||||||
|
m_dest(dest),
|
||||||
|
m_from(from),
|
||||||
|
m_to(to),
|
||||||
|
m_via(via),
|
||||||
|
m_type(type),
|
||||||
|
m_pid(pid),
|
||||||
|
m_data(data)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
M17Demod(DeviceAPI *deviceAPI);
|
M17Demod(DeviceAPI *deviceAPI);
|
||||||
virtual ~M17Demod();
|
virtual ~M17Demod();
|
||||||
virtual void destroy() { delete this; }
|
virtual void destroy() { delete this; }
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QFileDialog>
|
||||||
|
|
||||||
#include <complex>
|
#include <complex>
|
||||||
|
|
||||||
@ -30,6 +32,7 @@
|
|||||||
#include "plugin/pluginapi.h"
|
#include "plugin/pluginapi.h"
|
||||||
#include "util/simpleserializer.h"
|
#include "util/simpleserializer.h"
|
||||||
#include "util/db.h"
|
#include "util/db.h"
|
||||||
|
#include "util/csv.h"
|
||||||
#include "gui/basicchannelsettingsdialog.h"
|
#include "gui/basicchannelsettingsdialog.h"
|
||||||
#include "gui/devicestreamselectiondialog.h"
|
#include "gui/devicestreamselectiondialog.h"
|
||||||
#include "gui/crightclickenabler.h"
|
#include "gui/crightclickenabler.h"
|
||||||
@ -131,6 +134,43 @@ bool M17DemodGUI::handleMessage(const Message& message)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (M17Demod::MsgReportAPRS::match(message))
|
||||||
|
{
|
||||||
|
const M17Demod::MsgReportAPRS& report = (M17Demod::MsgReportAPRS&) message;
|
||||||
|
// Is scroll bar at bottom
|
||||||
|
QScrollBar *sb = ui->aprsPackets->verticalScrollBar();
|
||||||
|
bool scrollToBottom = sb->value() == sb->maximum();
|
||||||
|
|
||||||
|
ui->aprsPackets->setSortingEnabled(false);
|
||||||
|
int row = ui->aprsPackets->rowCount();
|
||||||
|
ui->aprsPackets->setRowCount(row + 1);
|
||||||
|
|
||||||
|
QTableWidgetItem *fromItem = new QTableWidgetItem();
|
||||||
|
QTableWidgetItem *toItem = new QTableWidgetItem();
|
||||||
|
QTableWidgetItem *viaItem = new QTableWidgetItem();
|
||||||
|
QTableWidgetItem *typeItem = new QTableWidgetItem();
|
||||||
|
QTableWidgetItem *pidItem = new QTableWidgetItem();
|
||||||
|
QTableWidgetItem *dataASCIIItem = new QTableWidgetItem();
|
||||||
|
ui->aprsPackets->setItem(row, 0, fromItem);
|
||||||
|
ui->aprsPackets->setItem(row, 1, toItem);
|
||||||
|
ui->aprsPackets->setItem(row, 2, viaItem);
|
||||||
|
ui->aprsPackets->setItem(row, 3, typeItem);
|
||||||
|
ui->aprsPackets->setItem(row, 4, pidItem);
|
||||||
|
ui->aprsPackets->setItem(row, 5, dataASCIIItem);
|
||||||
|
fromItem->setText(report.getFrom());
|
||||||
|
toItem->setText(report.getTo());
|
||||||
|
viaItem->setText(report.getVia());
|
||||||
|
typeItem->setText(report.getType());
|
||||||
|
pidItem->setText(report.getPID());
|
||||||
|
dataASCIIItem->setText(report.getData());
|
||||||
|
ui->aprsPackets->setSortingEnabled(true);
|
||||||
|
|
||||||
|
if (scrollToBottom) {
|
||||||
|
ui->aprsPackets->scrollToBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -239,6 +279,11 @@ void M17DemodGUI::on_highPassFilter_toggled(bool checked)
|
|||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void M17DemodGUI::on_aprsClearTable_clicked()
|
||||||
|
{
|
||||||
|
ui->aprsPackets->setRowCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
void M17DemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
void M17DemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||||||
{
|
{
|
||||||
(void) widget;
|
(void) widget;
|
||||||
@ -655,6 +700,7 @@ void M17DemodGUI::makeUIConnections()
|
|||||||
QObject::connect(ui->highPassFilter, &ButtonSwitch::toggled, this, &M17DemodGUI::on_highPassFilter_toggled);
|
QObject::connect(ui->highPassFilter, &ButtonSwitch::toggled, this, &M17DemodGUI::on_highPassFilter_toggled);
|
||||||
QObject::connect(ui->audioMute, &QToolButton::toggled, this, &M17DemodGUI::on_audioMute_toggled);
|
QObject::connect(ui->audioMute, &QToolButton::toggled, this, &M17DemodGUI::on_audioMute_toggled);
|
||||||
QObject::connect(ui->viewStatusLog, &QPushButton::clicked, this, &M17DemodGUI::on_viewStatusLog_clicked);
|
QObject::connect(ui->viewStatusLog, &QPushButton::clicked, this, &M17DemodGUI::on_viewStatusLog_clicked);
|
||||||
|
QObject::connect(ui->aprsClearTable, &QPushButton::clicked, this, &M17DemodGUI::on_aprsClearTable_clicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void M17DemodGUI::updateAbsoluteCenterFrequency()
|
void M17DemodGUI::updateAbsoluteCenterFrequency()
|
||||||
|
@ -111,6 +111,7 @@ private:
|
|||||||
void makeUIConnections();
|
void makeUIConnections();
|
||||||
void updateAbsoluteCenterFrequency();
|
void updateAbsoluteCenterFrequency();
|
||||||
QString getStatus(int status, bool streamElsePacket, int packetProtocol);
|
QString getStatus(int status, bool streamElsePacket, int packetProtocol);
|
||||||
|
void packetReceived(QByteArray packet);
|
||||||
|
|
||||||
void leaveEvent(QEvent*);
|
void leaveEvent(QEvent*);
|
||||||
void enterEvent(QEvent*);
|
void enterEvent(QEvent*);
|
||||||
@ -129,6 +130,7 @@ private slots:
|
|||||||
void on_squelch_valueChanged(int value);
|
void on_squelch_valueChanged(int value);
|
||||||
void on_highPassFilter_toggled(bool checked);
|
void on_highPassFilter_toggled(bool checked);
|
||||||
void on_audioMute_toggled(bool checked);
|
void on_audioMute_toggled(bool checked);
|
||||||
|
void on_aprsClearTable_clicked();
|
||||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||||
void onMenuDialogCalled(const QPoint& p);
|
void onMenuDialogCalled(const QPoint& p);
|
||||||
void on_viewStatusLog_clicked();
|
void on_viewStatusLog_clicked();
|
||||||
|
@ -732,7 +732,7 @@
|
|||||||
<enum>QTabWidget::East</enum>
|
<enum>QTabWidget::East</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="settingsTab">
|
<widget class="QWidget" name="settingsTab">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
@ -1549,6 +1549,90 @@
|
|||||||
<attribute name="toolTip">
|
<attribute name="toolTip">
|
||||||
<string>APRS</string>
|
<string>APRS</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
<widget class="QTableWidget" name="aprsPackets">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>24</y>
|
||||||
|
<width>480</width>
|
||||||
|
<height>186</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Received packets</string>
|
||||||
|
</property>
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>From</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Source callsign/address</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>To</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Destination callsign/address</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Via</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Repeater addresses</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Type</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AX.25 frame type</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>PID</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Layer 3 protocol ID</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Data (ASCII)</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Packet data as ASCII</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="aprsClearTable">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>24</width>
|
||||||
|
<height>21</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Clear packets 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>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "audio/audiofifo.h"
|
#include "audio/audiofifo.h"
|
||||||
|
#include "util/ax25.h"
|
||||||
|
|
||||||
#include "m17/ax25_frame.h"
|
#include "m17/ax25_frame.h"
|
||||||
#include "m17demod.h"
|
#include "m17demod.h"
|
||||||
@ -148,10 +149,6 @@ void M17DemodProcessor::diagnostic_callback(
|
|||||||
oss << buffer;
|
oss << buffer;
|
||||||
qDebug() << "M17DemodProcessor::diagnostic_callback: " << oss.str().c_str();
|
qDebug() << "M17DemodProcessor::diagnostic_callback: " << oss.str().c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == 0) { // unlocked
|
|
||||||
m_this->resetInfo();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool M17DemodProcessor::decode_lich(mobilinkd::M17FrameDecoder::lich_buffer_t const& lich)
|
bool M17DemodProcessor::decode_lich(mobilinkd::M17FrameDecoder::lich_buffer_t const& lich)
|
||||||
@ -361,9 +358,9 @@ bool M17DemodProcessor::decode_packet(mobilinkd::M17FrameDecoder::packet_buffer_
|
|||||||
oss << *it;
|
oss << *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "M17DemodProcessor::decode_packet: "
|
qDebug() << "M17DemodProcessor::decode SMS_packet: "
|
||||||
<< " From:" << getSrcCall()
|
<< " Src:" << getSrcCall()
|
||||||
<< " To:" << getDestcCall()
|
<< " Dest:" << getDestcCall()
|
||||||
<< " SMS:" << oss.str().c_str();
|
<< " SMS:" << oss.str().c_str();
|
||||||
|
|
||||||
if (m_demodInputMessageQueue)
|
if (m_demodInputMessageQueue)
|
||||||
@ -376,6 +373,40 @@ bool M17DemodProcessor::decode_packet(mobilinkd::M17FrameDecoder::packet_buffer_
|
|||||||
m_demodInputMessageQueue->push(msg);
|
m_demodInputMessageQueue->push(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (m_stdPacketProtocol == StdPacketAPRS)
|
||||||
|
{
|
||||||
|
AX25Packet ax25;
|
||||||
|
QByteArray packet = QByteArray(reinterpret_cast<const char*>(&m_currentPacket[1]), m_currentPacket.size()-3);
|
||||||
|
|
||||||
|
if (ax25.decode(packet))
|
||||||
|
{
|
||||||
|
qDebug() << "M17DemodProcessor::decode APRS_packet: "
|
||||||
|
<< " Src:" << getSrcCall()
|
||||||
|
<< " Dest:" << getDestcCall()
|
||||||
|
<< " From:" << ax25.m_from
|
||||||
|
<< " To: " << ax25.m_to
|
||||||
|
<< " Via: " << ax25.m_via
|
||||||
|
<< " Type: " << ax25.m_type
|
||||||
|
<< " PID: " << ax25.m_pid
|
||||||
|
<< " Data: " << ax25.m_dataASCII;
|
||||||
|
|
||||||
|
if (m_demodInputMessageQueue)
|
||||||
|
{
|
||||||
|
M17Demod::MsgReportAPRS *msg = M17Demod::MsgReportAPRS::create(
|
||||||
|
getSrcCall(),
|
||||||
|
getDestcCall(),
|
||||||
|
ax25.m_from,
|
||||||
|
ax25.m_to,
|
||||||
|
ax25.m_via,
|
||||||
|
ax25.m_type,
|
||||||
|
ax25.m_pid,
|
||||||
|
ax25.m_dataASCII
|
||||||
|
);
|
||||||
|
msg->getPacket() = packet;
|
||||||
|
m_demodInputMessageQueue->push(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,8 @@ struct M17DemodSettings
|
|||||||
int m_traceStroke; // [0..255]
|
int m_traceStroke; // [0..255]
|
||||||
int m_traceDecay; // [0..255]
|
int m_traceDecay; // [0..255]
|
||||||
QString m_audioDeviceName;
|
QString m_audioDeviceName;
|
||||||
|
QString m_aprsLogFilename;
|
||||||
|
bool m_aprsLogEnabled;
|
||||||
int m_streamIndex; //!< MIMO channel. Not relevant when connected to SI (single Rx).
|
int m_streamIndex; //!< MIMO channel. Not relevant when connected to SI (single Rx).
|
||||||
bool m_useReverseAPI;
|
bool m_useReverseAPI;
|
||||||
QString m_reverseAPIAddress;
|
QString m_reverseAPIAddress;
|
||||||
|
@ -174,7 +174,10 @@ void M17DemodSink::feed(const SampleVector::const_iterator& begin, const SampleV
|
|||||||
|
|
||||||
if (m_squelchWasOpen)
|
if (m_squelchWasOpen)
|
||||||
{
|
{
|
||||||
m_m17DemodProcessor.resetInfo();
|
if (m_m17DemodProcessor.getStreamElsePacket()) { // if packet kepp last values
|
||||||
|
m_m17DemodProcessor.resetInfo();
|
||||||
|
}
|
||||||
|
|
||||||
m_m17DemodProcessor.setDCDOff(); // indicate loss of carrier
|
m_m17DemodProcessor.setDCDOff(); // indicate loss of carrier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ set(modm17_SOURCES
|
|||||||
m17modprocessor.cpp
|
m17modprocessor.cpp
|
||||||
m17modfifo.cpp
|
m17modfifo.cpp
|
||||||
m17moddecimator.cpp
|
m17moddecimator.cpp
|
||||||
|
m17modax25.cpp
|
||||||
m17modplugin.cpp
|
m17modplugin.cpp
|
||||||
m17modsettings.cpp
|
m17modsettings.cpp
|
||||||
m17modwebapiadapter.cpp
|
m17modwebapiadapter.cpp
|
||||||
@ -19,6 +20,7 @@ set(modm17_HEADERS
|
|||||||
m17modprocessor.h
|
m17modprocessor.h
|
||||||
m17modfifo.h
|
m17modfifo.h
|
||||||
m17moddecimator.h
|
m17moddecimator.h
|
||||||
|
m17modax25.h
|
||||||
m17modplugin.h
|
m17modplugin.h
|
||||||
m17modsettings.h
|
m17modsettings.h
|
||||||
m17modwebapiadapter.h
|
m17modwebapiadapter.h
|
||||||
|
148
plugins/channeltx/modm17/m17modax25.cpp
Normal file
148
plugins/channeltx/modm17/m17modax25.cpp
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (C) 2022 Edouard Griffiths, F4EXB //
|
||||||
|
// //
|
||||||
|
// This program is free software; you can redistribute it and/or modify //
|
||||||
|
// it under the terms of the GNU General Public License as published by //
|
||||||
|
// the Free Software Foundation as version 3 of the License, or //
|
||||||
|
// (at your option) any later version. //
|
||||||
|
// //
|
||||||
|
// This program is distributed in the hope that it will be useful, //
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||||
|
// GNU General Public License V3 for more details. //
|
||||||
|
// //
|
||||||
|
// You should have received a copy of the GNU General Public License //
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <array>
|
||||||
|
#include "util/crc.h"
|
||||||
|
#include "m17modax25.h"
|
||||||
|
|
||||||
|
M17ModAX25::M17ModAX25() :
|
||||||
|
m_ax25Control(3),
|
||||||
|
m_ax25PID(AX25_NO_L3)
|
||||||
|
{}
|
||||||
|
|
||||||
|
M17ModAX25::~M17ModAX25()
|
||||||
|
{}
|
||||||
|
|
||||||
|
QByteArray M17ModAX25::makePacket(const QString& callsign, const QString& to, const QString& via, const QString& data)
|
||||||
|
{
|
||||||
|
std::array<uint8_t, AX25_MAX_BYTES> packet;
|
||||||
|
uint8_t *crc_start;
|
||||||
|
uint8_t *p;
|
||||||
|
crc16x25 crc;
|
||||||
|
uint16_t crcValue;
|
||||||
|
int len;
|
||||||
|
int packet_length;
|
||||||
|
|
||||||
|
// Create AX.25 packet
|
||||||
|
p = packet.data();
|
||||||
|
// Unique preamble flag
|
||||||
|
// *p++ = AX25_FLAG;
|
||||||
|
crc_start = p;
|
||||||
|
// Dest
|
||||||
|
p = ax25_address(p, to, 0xe0);
|
||||||
|
// From
|
||||||
|
p = ax25_address(p, callsign, 0x60);
|
||||||
|
// Via
|
||||||
|
p = ax25_address(p, via, 0x61);
|
||||||
|
// Control
|
||||||
|
*p++ = m_ax25Control;
|
||||||
|
// PID
|
||||||
|
*p++ = m_ax25PID;
|
||||||
|
// Data
|
||||||
|
len = data.length();
|
||||||
|
memcpy(p, data.toUtf8(), len);
|
||||||
|
p += len;
|
||||||
|
// CRC (do not include flags)
|
||||||
|
crc.calculate(crc_start, p-crc_start);
|
||||||
|
crcValue = crc.get();
|
||||||
|
*p++ = crcValue & 0xff;
|
||||||
|
*p++ = (crcValue >> 8);
|
||||||
|
// Unique postamble flag
|
||||||
|
// *p++ = AX25_FLAG;
|
||||||
|
|
||||||
|
packet_length = p-&packet[0];
|
||||||
|
|
||||||
|
return QByteArray(reinterpret_cast<const char*>(packet.data()), packet_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *M17ModAX25::ax25_address(uint8_t *p, QString address, uint8_t crrl)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
int i;
|
||||||
|
QByteArray b;
|
||||||
|
uint8_t ssid = 0;
|
||||||
|
bool hyphenSeen = false;
|
||||||
|
|
||||||
|
len = address.length();
|
||||||
|
b = address.toUtf8();
|
||||||
|
ssid = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
if ((i < len) && !hyphenSeen)
|
||||||
|
{
|
||||||
|
if (b[i] == '-')
|
||||||
|
{
|
||||||
|
ax25_ssid(b, i, len, ssid);
|
||||||
|
hyphenSeen = true;
|
||||||
|
*p++ = ' ' << 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*p++ = b[i] << 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*p++ = ' ' << 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b[i] == '-') {
|
||||||
|
ax25_ssid(b, i, len, ssid);
|
||||||
|
}
|
||||||
|
|
||||||
|
*p++ = crrl | (ssid << 1);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool M17ModAX25::ax25_ssid(QByteArray& b, int i, int len, uint8_t& ssid)
|
||||||
|
{
|
||||||
|
if (b[i] == '-')
|
||||||
|
{
|
||||||
|
if (len > i + 1)
|
||||||
|
{
|
||||||
|
ssid = b[i+1] - '0';
|
||||||
|
|
||||||
|
if ((len > i + 2) && isdigit(b[i+2])) {
|
||||||
|
ssid = (ssid*10) + (b[i+2] - '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssid >= 16)
|
||||||
|
{
|
||||||
|
qDebug("M17ModAX25::ax25_ssid: ax25_address: SSID greater than 15 not supported");
|
||||||
|
ssid = ssid & 0xf;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug("M17ModAX25::ax25_ssid: ax25_address: SSID number missing");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
50
plugins/channeltx/modm17/m17modax25.h
Normal file
50
plugins/channeltx/modm17/m17modax25.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (C) 2022 Edouard Griffiths, F4EXB //
|
||||||
|
// //
|
||||||
|
// This program is free software; you can redistribute it and/or modify //
|
||||||
|
// it under the terms of the GNU General Public License as published by //
|
||||||
|
// the Free Software Foundation as version 3 of the License, or //
|
||||||
|
// (at your option) any later version. //
|
||||||
|
// //
|
||||||
|
// This program is distributed in the hope that it will be useful, //
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||||
|
// GNU General Public License V3 for more details. //
|
||||||
|
// //
|
||||||
|
// You should have received a copy of the GNU General Public License //
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef PLUGINS_CHANNELTX_MODM17_M17MODAX25_H_
|
||||||
|
#define PLUGINS_CHANNELTX_MODM17_M17MODAX25_H_
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
class QString;
|
||||||
|
|
||||||
|
class M17ModAX25
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
M17ModAX25();
|
||||||
|
~M17ModAX25();
|
||||||
|
void setAX25Control(int ax25Control) { m_ax25Control = ax25Control; }
|
||||||
|
void setAX25PID(int ax25PID) { m_ax25PID = ax25PID; }
|
||||||
|
QByteArray makePacket(const QString& callsign, const QString& to, const QString& via, const QString& data);
|
||||||
|
|
||||||
|
static const int AX25_MAX_FLAGS = 1024;
|
||||||
|
static const int AX25_MAX_BYTES = (2*AX25_MAX_FLAGS+1+28+2+256+2+1);
|
||||||
|
static const int AX25_MAX_BITS = (AX25_MAX_BYTES*2);
|
||||||
|
static const uint8_t AX25_FLAG = 0x7e;
|
||||||
|
static const uint8_t AX25_NO_L3 = 0xf0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_ax25Control;
|
||||||
|
int m_ax25PID;
|
||||||
|
|
||||||
|
static uint8_t *ax25_address(uint8_t *p, QString address, uint8_t crrl);
|
||||||
|
static bool ax25_ssid(QByteArray& b, int i, int len, uint8_t& ssid);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PLUGINS_CHANNELTX_MODM17_M17MODAX25_H_
|
||||||
|
|
@ -347,6 +347,36 @@ void M17ModGUI::on_smsText_editingFinished()
|
|||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void M17ModGUI::on_aprsFromText_editingFinished()
|
||||||
|
{
|
||||||
|
m_settings.m_aprsCallsign = ui->aprsFromText->text();
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void M17ModGUI::on_aprsTo_currentTextChanged(const QString &text)
|
||||||
|
{
|
||||||
|
m_settings.m_aprsTo = text;
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void M17ModGUI::on_aprsVia_currentTextChanged(const QString &text)
|
||||||
|
{
|
||||||
|
m_settings.m_aprsVia = text;
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void M17ModGUI::on_aprsData_editingFinished()
|
||||||
|
{
|
||||||
|
m_settings.m_aprsData = ui->aprsData->text();
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void M17ModGUI::on_aprsInsertPosition_toggled(bool checked)
|
||||||
|
{
|
||||||
|
m_settings.m_aprsInsertPosition = checked;
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
void M17ModGUI::configureFileName()
|
void M17ModGUI::configureFileName()
|
||||||
{
|
{
|
||||||
qDebug() << "M17ModGUI::configureFileName: " << m_fileName.toStdString().c_str();
|
qDebug() << "M17ModGUI::configureFileName: " << m_fileName.toStdString().c_str();
|
||||||
@ -556,6 +586,7 @@ void M17ModGUI::displaySettings()
|
|||||||
ui->aprsData->setText(m_settings.m_aprsData);
|
ui->aprsData->setText(m_settings.m_aprsData);
|
||||||
ui->aprsTo->lineEdit()->setText(m_settings.m_aprsTo);
|
ui->aprsTo->lineEdit()->setText(m_settings.m_aprsTo);
|
||||||
ui->aprsVia->lineEdit()->setText(m_settings.m_aprsVia);
|
ui->aprsVia->lineEdit()->setText(m_settings.m_aprsVia);
|
||||||
|
ui->aprsInsertPosition->setChecked(m_settings.m_aprsInsertPosition);
|
||||||
|
|
||||||
getRollupContents()->restoreState(m_rollupState);
|
getRollupContents()->restoreState(m_rollupState);
|
||||||
updateAbsoluteCenterFrequency();
|
updateAbsoluteCenterFrequency();
|
||||||
@ -764,7 +795,13 @@ void M17ModGUI::makeUIConnections()
|
|||||||
QObject::connect(ui->sendPacket, &QPushButton::clicked, this, &M17ModGUI::on_sendPacket_clicked);
|
QObject::connect(ui->sendPacket, &QPushButton::clicked, this, &M17ModGUI::on_sendPacket_clicked);
|
||||||
QObject::connect(ui->loopPacket, &ButtonSwitch::toggled, this, &M17ModGUI::on_loopPacket_toggled);
|
QObject::connect(ui->loopPacket, &ButtonSwitch::toggled, this, &M17ModGUI::on_loopPacket_toggled);
|
||||||
QObject::connect(ui->loopPacketInterval, &QDial::valueChanged, this, &M17ModGUI::on_loopPacketInterval_valueChanged);
|
QObject::connect(ui->loopPacketInterval, &QDial::valueChanged, this, &M17ModGUI::on_loopPacketInterval_valueChanged);
|
||||||
|
QObject::connect(ui->packetDataWidget, &QTabWidget::currentChanged, this, &M17ModGUI::on_packetDataWidget_currentChanged);
|
||||||
QObject::connect(ui->smsText, &CustomTextEdit::editingFinished, this, &M17ModGUI::on_smsText_editingFinished);
|
QObject::connect(ui->smsText, &CustomTextEdit::editingFinished, this, &M17ModGUI::on_smsText_editingFinished);
|
||||||
|
QObject::connect(ui->aprsFromText, &QLineEdit::editingFinished, this, &M17ModGUI::on_aprsFromText_editingFinished);
|
||||||
|
QObject::connect(ui->aprsTo, &QComboBox::currentTextChanged, this, &M17ModGUI::on_aprsTo_currentTextChanged);
|
||||||
|
QObject::connect(ui->aprsVia, &QComboBox::currentTextChanged, this, &M17ModGUI::on_aprsVia_currentTextChanged);
|
||||||
|
QObject::connect(ui->aprsData, &QLineEdit::editingFinished, this, &M17ModGUI::on_aprsData_editingFinished);
|
||||||
|
QObject::connect(ui->aprsInsertPosition, &ButtonSwitch::toggled, this, &M17ModGUI::on_aprsInsertPosition_toggled);
|
||||||
QObject::connect(ui->source, &QLineEdit::editingFinished, this, &M17ModGUI::on_source_editingFinished);
|
QObject::connect(ui->source, &QLineEdit::editingFinished, this, &M17ModGUI::on_source_editingFinished);
|
||||||
QObject::connect(ui->destination, &QLineEdit::editingFinished, this, &M17ModGUI::on_destination_editingFinished);
|
QObject::connect(ui->destination, &QLineEdit::editingFinished, this, &M17ModGUI::on_destination_editingFinished);
|
||||||
QObject::connect(ui->can, QOverload<int>::of(&QSpinBox::valueChanged), this, &M17ModGUI::on_can_valueChanged);
|
QObject::connect(ui->can, QOverload<int>::of(&QSpinBox::valueChanged), this, &M17ModGUI::on_can_valueChanged);
|
||||||
|
@ -142,8 +142,15 @@ private slots:
|
|||||||
void on_destination_editingFinished();
|
void on_destination_editingFinished();
|
||||||
void on_insertPosition_toggled(bool checked);
|
void on_insertPosition_toggled(bool checked);
|
||||||
void on_can_valueChanged(int value);
|
void on_can_valueChanged(int value);
|
||||||
|
|
||||||
void on_smsText_editingFinished();
|
void on_smsText_editingFinished();
|
||||||
|
|
||||||
|
void on_aprsFromText_editingFinished();
|
||||||
|
void on_aprsTo_currentTextChanged(const QString &text);
|
||||||
|
void on_aprsVia_currentTextChanged(const QString &text);
|
||||||
|
void on_aprsData_editingFinished();
|
||||||
|
void on_aprsInsertPosition_toggled(bool checked);
|
||||||
|
|
||||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||||
void onMenuDialogCalled(const QPoint& p);
|
void onMenuDialogCalled(const QPoint& p);
|
||||||
|
|
||||||
|
@ -18,10 +18,13 @@
|
|||||||
#include <codec2/codec2.h>
|
#include <codec2/codec2.h>
|
||||||
|
|
||||||
#include "m17/M17Modulator.h"
|
#include "m17/M17Modulator.h"
|
||||||
|
#include "maincore.h"
|
||||||
|
|
||||||
|
#include "m17modax25.h"
|
||||||
#include "m17modprocessor.h"
|
#include "m17modprocessor.h"
|
||||||
|
|
||||||
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgSendSMS, Message)
|
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgSendSMS, Message)
|
||||||
|
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgSendAPRS, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgSendAudioFrame, Message)
|
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgSendAudioFrame, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgStartAudio, Message)
|
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgStartAudio, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgStopAudio, Message)
|
MESSAGE_CLASS_DEFINITION(M17ModProcessor::MsgStopAudio, Message)
|
||||||
@ -57,6 +60,24 @@ bool M17ModProcessor::handleMessage(const Message& cmd)
|
|||||||
// test(notif.getSourceCall(), notif.getDestCall());
|
// test(notif.getSourceCall(), notif.getDestCall());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (MsgSendAPRS::match(cmd))
|
||||||
|
{
|
||||||
|
const MsgSendAPRS& notif = (const MsgSendAPRS&) cmd;
|
||||||
|
M17ModAX25 modAX25;
|
||||||
|
QString strData;
|
||||||
|
|
||||||
|
if (notif.getInsertPosition()) {
|
||||||
|
strData += "!" + formatAPRSPosition();
|
||||||
|
} else {
|
||||||
|
strData = notif.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray packetBytes = modAX25.makePacket(notif.getCall(), notif.getTo(), notif.getVia(), strData);
|
||||||
|
packetBytes.prepend(0x02); // APRS standard type
|
||||||
|
packetBytes.truncate(798); // Maximum packet size is 798 payload + 2 bytes CRC = 800 bytes (32*25)
|
||||||
|
processPacket(notif.getSourceCall(), notif.getDestCall(), notif.getCAN(), packetBytes);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else if (MsgSendAudioFrame::match(cmd))
|
else if (MsgSendAudioFrame::match(cmd))
|
||||||
{
|
{
|
||||||
MsgSendAudioFrame& notif = (MsgSendAudioFrame&) cmd;
|
MsgSendAudioFrame& notif = (MsgSendAudioFrame&) cmd;
|
||||||
@ -248,3 +269,47 @@ void M17ModProcessor::output_baseband(std::array<uint8_t, 2> sync_word, const st
|
|||||||
std::array<int16_t, 1920> baseband = m_m17Modulator.symbols_to_baseband(temp); // 1920 48 kS/s int16_t samples
|
std::array<int16_t, 1920> baseband = m_m17Modulator.symbols_to_baseband(temp); // 1920 48 kS/s int16_t samples
|
||||||
m_basebandFifo.write(baseband.data(), 1920);
|
m_basebandFifo.write(baseband.data(), 1920);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString M17ModProcessor::formatAPRSPosition()
|
||||||
|
{
|
||||||
|
float latitude = MainCore::instance()->getSettings().getLatitude();
|
||||||
|
float longitude = MainCore::instance()->getSettings().getLongitude();
|
||||||
|
|
||||||
|
int latDeg, latMin, latFrac, latNorth;
|
||||||
|
int longDeg, longMin, longFrac, longEast;
|
||||||
|
|
||||||
|
// Convert decimal latitude to degrees, min and hundreths of a minute
|
||||||
|
latNorth = latitude >= 0.0f;
|
||||||
|
latitude = abs(latitude);
|
||||||
|
latDeg = (int) latitude;
|
||||||
|
latitude -= (float) latDeg;
|
||||||
|
latitude *= 60.0f;
|
||||||
|
latMin = (int) latitude;
|
||||||
|
latitude -= (float) latMin;
|
||||||
|
latitude *= 100.0f;
|
||||||
|
latFrac = round(latitude);
|
||||||
|
|
||||||
|
// Convert decimal longitude
|
||||||
|
longEast = longitude >= 0.0f;
|
||||||
|
longitude = abs(longitude);
|
||||||
|
longDeg = (int) longitude;
|
||||||
|
longitude -= (float) longDeg;
|
||||||
|
longitude *= 60.0f;
|
||||||
|
longMin = (int) longitude;
|
||||||
|
longitude -= (float) longMin;
|
||||||
|
longitude *= 100.0f;
|
||||||
|
longFrac = round(longitude);
|
||||||
|
|
||||||
|
// Insert position with house symbol (-) in to data field
|
||||||
|
QString latStr = QString("%1%2.%3%4")
|
||||||
|
.arg(latDeg, 2, 10, QChar('0'))
|
||||||
|
.arg(latMin, 2, 10, QChar('0'))
|
||||||
|
.arg(latFrac, 2, 10, QChar('0'))
|
||||||
|
.arg(latNorth ? 'N' : 'S');
|
||||||
|
QString longStr = QString("%1%2.%3%4")
|
||||||
|
.arg(longDeg, 3, 10, QChar('0'))
|
||||||
|
.arg(longMin, 2, 10, QChar('0'))
|
||||||
|
.arg(longFrac, 2, 10, QChar('0'))
|
||||||
|
.arg(longEast ? 'E' : 'W');
|
||||||
|
return QString("%1/%2-").arg(latStr).arg(longStr);
|
||||||
|
}
|
||||||
|
@ -60,6 +60,65 @@ public:
|
|||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MsgSendAPRS : public Message {
|
||||||
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
|
public:
|
||||||
|
const QString& getSourceCall() const { return m_sourceCall; }
|
||||||
|
const QString& getDestCall() const { return m_destCall; }
|
||||||
|
uint8_t getCAN() const { return m_can; }
|
||||||
|
const QString& getCall() const { return m_call; }
|
||||||
|
const QString& getTo() const { return m_to; }
|
||||||
|
const QString& getVia() const { return m_via; }
|
||||||
|
const QString& getData() const { return m_data; }
|
||||||
|
bool getInsertPosition() const { return m_insertPosition; }
|
||||||
|
|
||||||
|
static MsgSendAPRS* create(
|
||||||
|
const QString& sourceCall,
|
||||||
|
const QString& destCall,
|
||||||
|
uint8_t can,
|
||||||
|
const QString& call,
|
||||||
|
const QString& to,
|
||||||
|
const QString& via,
|
||||||
|
const QString& data,
|
||||||
|
bool insertPosition
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return new MsgSendAPRS(sourceCall, destCall, can, call, to, via, data, insertPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_sourceCall;
|
||||||
|
QString m_destCall;
|
||||||
|
uint8_t m_can;
|
||||||
|
QString m_call;
|
||||||
|
QString m_to;
|
||||||
|
QString m_via;
|
||||||
|
QString m_data;
|
||||||
|
bool m_insertPosition;
|
||||||
|
|
||||||
|
MsgSendAPRS(
|
||||||
|
const QString& sourceCall,
|
||||||
|
const QString& destCall,
|
||||||
|
uint8_t can,
|
||||||
|
const QString& call,
|
||||||
|
const QString& to,
|
||||||
|
const QString& via,
|
||||||
|
const QString& data,
|
||||||
|
bool insertPosition
|
||||||
|
) :
|
||||||
|
Message(),
|
||||||
|
m_sourceCall(sourceCall),
|
||||||
|
m_destCall(destCall),
|
||||||
|
m_can(can),
|
||||||
|
m_call(call),
|
||||||
|
m_to(to),
|
||||||
|
m_via(via),
|
||||||
|
m_data(data),
|
||||||
|
m_insertPosition(insertPosition)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
class MsgSendAudioFrame : public Message {
|
class MsgSendAudioFrame : public Message {
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
@ -154,6 +213,7 @@ private:
|
|||||||
void send_preamble();
|
void send_preamble();
|
||||||
void send_eot();
|
void send_eot();
|
||||||
void output_baseband(std::array<uint8_t, 2> sync_word, const std::array<int8_t, 368>& frame);
|
void output_baseband(std::array<uint8_t, 2> sync_word, const std::array<int8_t, 368>& frame);
|
||||||
|
QString formatAPRSPosition();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleInputMessages();
|
void handleInputMessages();
|
||||||
|
@ -577,4 +577,18 @@ void M17ModSource::sendPacket()
|
|||||||
);
|
);
|
||||||
m_processor->getInputMessageQueue()->push(msg);
|
m_processor->getInputMessageQueue()->push(msg);
|
||||||
}
|
}
|
||||||
|
else if (m_settings.m_packetType == M17ModSettings::PacketType::PacketAPRS)
|
||||||
|
{
|
||||||
|
M17ModProcessor::MsgSendAPRS *msg = M17ModProcessor::MsgSendAPRS::create(
|
||||||
|
m_settings.m_sourceCall,
|
||||||
|
m_settings.m_destCall,
|
||||||
|
m_settings.m_can,
|
||||||
|
m_settings.m_aprsCallsign,
|
||||||
|
m_settings.m_aprsTo,
|
||||||
|
m_settings.m_aprsVia,
|
||||||
|
m_settings.m_aprsData,
|
||||||
|
m_settings.m_aprsInsertPosition
|
||||||
|
);
|
||||||
|
m_processor->getInputMessageQueue()->push(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,14 @@
|
|||||||
|
|
||||||
const QStringList APRSSettings::m_pipeTypes = {
|
const QStringList APRSSettings::m_pipeTypes = {
|
||||||
QStringLiteral("PacketDemod"),
|
QStringLiteral("PacketDemod"),
|
||||||
QStringLiteral("ChirpChatDemod")
|
QStringLiteral("ChirpChatDemod"),
|
||||||
|
QStringLiteral("M17Demod")
|
||||||
};
|
};
|
||||||
|
|
||||||
const QStringList APRSSettings::m_pipeURIs = {
|
const QStringList APRSSettings::m_pipeURIs = {
|
||||||
QStringLiteral("sdrangel.channel.packetdemod"),
|
QStringLiteral("sdrangel.channel.packetdemod"),
|
||||||
QStringLiteral("sdrangel.channel.chirpchatdemod")
|
QStringLiteral("sdrangel.channel.chirpchatdemod"),
|
||||||
|
QStringLiteral("sdrangel.channel.m17demod")
|
||||||
};
|
};
|
||||||
|
|
||||||
const QStringList APRSSettings::m_altitudeUnitNames = {
|
const QStringList APRSSettings::m_altitudeUnitNames = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user