///////////////////////////////////////////////////////////////////////////////////
// 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 . //
///////////////////////////////////////////////////////////////////////////////////
#include
#include
#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 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(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;
}
}