LoRa_APRS_Tracker111/src/kiss_utils.cpp

155 lines
6.1 KiB
C++

#include "kiss_utils.h"
namespace KISS_Utils {
bool validateTNC2Frame(const String& tnc2FormattedFrame) {
int colonPos = tnc2FormattedFrame.indexOf(':');
int greaterThanPos = tnc2FormattedFrame.indexOf('>');
return (colonPos != -1) && (greaterThanPos != -1) && (colonPos > greaterThanPos);
}
bool validateKISSFrame(const String& kissFormattedFrame) {
return kissFormattedFrame.charAt(0) == (char)KissChar::FEND && kissFormattedFrame.charAt(kissFormattedFrame.length() - 1) == (char)KissChar::FEND;
}
String decodeAddressAX25(const String& ax25Address, bool& isLastAddress, bool isRelay) {
String address = "";
for (int i = 0; i < 6; ++i) {
uint8_t currentCharacter = ax25Address.charAt(i);
currentCharacter >>= 1;
if (currentCharacter != ' ') address += (char)currentCharacter;
}
auto ssidChar = (uint8_t)ax25Address.charAt(6);
bool hasBeenDigipited = ssidChar & HAS_BEEN_DIGIPITED_MASK;
isLastAddress = ssidChar & IS_LAST_ADDRESS_POSITION_MASK;
ssidChar >>= 1;
int ssid = 0b1111 & ssidChar;
if (ssid) {
address += '-';
address += ssid;
}
if (isRelay && hasBeenDigipited) address += '*';
return address;
}
String decapsulateKISS(const String& frame) {
String ax25Frame = "";
for (int i = 2; i < frame.length() - 1; ++i) {
char currentChar = frame.charAt(i);
if (currentChar == (char)KissChar::FESC) {
char nextChar = frame.charAt(i + 1);
if (nextChar == (char)KissChar::TFEND) {
ax25Frame += (char)KissChar::FEND;
} else if (nextChar == (char)KissChar::TFESC) {
ax25Frame += (char)KissChar::FESC;
}
i++;
} else {
ax25Frame += currentChar;
}
}
return ax25Frame;
}
String encapsulateKISS(const String& ax25Frame, uint8_t command) {
String kissFrame = "";
kissFrame += (char)KissChar::FEND;
kissFrame += (char)(0x0f & command);
for (int i = 0; i < ax25Frame.length(); ++i) {
char currentChar = ax25Frame.charAt(i);
if (currentChar == (char)KissChar::FEND) {
kissFrame += (char)KissChar::FESC;
kissFrame += (char)KissChar::TFEND;
} else if (currentChar == (char)KissChar::FESC) {
kissFrame += (char)KissChar::FESC;
kissFrame += (char)KissChar::TFESC;
} else {
kissFrame += currentChar;
}
}
kissFrame += (char)KissChar::FEND; // end of frame
return kissFrame;
}
String encodeAddressAX25(String address) {
bool hasBeenDigipited = address.indexOf('*') != -1;
if (address.indexOf('-') == -1) {
if (hasBeenDigipited) address = address.substring(0, address.length() - 1);
address += "-0";
}
int separatorIndex = address.indexOf('-');
int ssid = address.substring(separatorIndex + 1).toInt();
String kissAddress = "";
for (int i = 0; i < 6; ++i) {
char addressChar = ' ';
if (address.length() > i && i < separatorIndex) addressChar = address.charAt(i);
kissAddress += (char)(addressChar << 1);
}
kissAddress += (char)((ssid << 1) | 0b01100000 | (hasBeenDigipited ? HAS_BEEN_DIGIPITED_MASK : 0));
return kissAddress;
}
String decodeKISS(const String& inputFrame, bool& dataFrame) {
String frame = "";
if (KISS_Utils::validateKISSFrame(inputFrame)) {
dataFrame = inputFrame.charAt(1) == KissCmd::Data;
if (dataFrame) {
String ax25Frame = decapsulateKISS(inputFrame);
bool isLastAddress = false;
String dstAddr = decodeAddressAX25(ax25Frame.substring(0, 7), isLastAddress, false);
String srcAddr = decodeAddressAX25(ax25Frame.substring(7, 14), isLastAddress, false);
frame = srcAddr + ">" + dstAddr;
int digiInfoIndex = 14;
while (!isLastAddress && digiInfoIndex + 7 < ax25Frame.length()) {
String digiAddr = decodeAddressAX25(ax25Frame.substring(digiInfoIndex, digiInfoIndex + 7), isLastAddress, true);
frame += ',' + digiAddr;
digiInfoIndex += 7;
}
frame += ':';
frame += ax25Frame.substring(digiInfoIndex + 2);
} else {
frame += inputFrame;
}
}
return frame;
}
String encodeKISS(const String& frame) {
String ax25Frame = "";
if (KISS_Utils::validateTNC2Frame(frame)) {
int colonIndex = frame.indexOf(':');
String address = "";
bool destinationAddressWritten = false;
for (int i = 0; i <= colonIndex; i++) {
char currentChar = frame.charAt(i);
if (currentChar == ':' || currentChar == '>' || currentChar == ',') {
if (!destinationAddressWritten && (currentChar == ',' || currentChar == ':')) {
ax25Frame = encodeAddressAX25(address) + ax25Frame;
destinationAddressWritten = true;
} else {
ax25Frame += encodeAddressAX25(address);
}
address = "";
} else {
address += currentChar;
}
}
auto lastAddressChar = (uint8_t)ax25Frame.charAt(ax25Frame.length() - 1);
ax25Frame.setCharAt(ax25Frame.length() - 1, (char)(lastAddressChar | IS_LAST_ADDRESS_POSITION_MASK));
ax25Frame += (char)AX25Char::ControlField;
ax25Frame += (char)AX25Char::InformationField;
ax25Frame += frame.substring(colonIndex + 1);
}
String kissFrame = encapsulateKISS(ax25Frame, KissCmd::Data);
return kissFrame;
}
}