diff --git a/src/ax25_utils.cpp b/src/ax25_utils.cpp index 8a2292f..d58ef38 100644 --- a/src/ax25_utils.cpp +++ b/src/ax25_utils.cpp @@ -1,4 +1,6 @@ #include "ax25_utils.h" +#include "kiss_utils.h" + namespace AX25_Utils { @@ -162,4 +164,89 @@ namespace AX25_Utils { return encodedPacket; } + //************************************** + + String encapsulateKISS(const String& ax25Frame, uint8_t cmd) { + String kissFrame = ""; + kissFrame += (char)FEND; + kissFrame += (char)(0x0f & cmd); + + for (int i = 0; i < ax25Frame.length(); ++i) { + char currentChar = ax25Frame.charAt(i); + if (currentChar == (char)FEND) { + kissFrame += (char)FESC; + kissFrame += (char)TFEND; + } else if (currentChar == (char)FESC) { + kissFrame += (char)FESC; + kissFrame += (char)TFESC; + } else { + kissFrame += currentChar; + } + } + kissFrame += (char)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); + } else { + addressChar = ' '; + } + kissAddress += (char)(addressChar << 1); + } + + kissAddress += (char)((ssid << 1) | 0b01100000 | (hasBeenDigipited ? HAS_BEEN_DIGIPITED_MASK : 0)); + return kissAddress; + } + + String encodeKISS(const String& frame) { + String ax25Frame = ""; + + if (KISS_Utils::validateTNC2Frame(frame)) { + int colonIndex = frame.indexOf(':'); + + String address = ""; + bool dstAddresWritten = false; + for (int i = 0; i <= colonIndex; i++) { + char currentChar = frame.charAt(i); + if (currentChar == ':' || currentChar == '>' || currentChar == ',') { + if (!dstAddresWritten && (currentChar == ',' || currentChar == ':')) { + ax25Frame = encodeAddressAX25(address) + ax25Frame; + dstAddresWritten = 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)APRS_CONTROL_FIELD; + ax25Frame += (char)APRS_INFORMATION_FIELD; + ax25Frame += frame.substring(colonIndex + 1); + } + + String kissFrame = encapsulateKISS(ax25Frame, CMD_DATA); + return kissFrame; + } + } \ No newline at end of file diff --git a/src/ax25_utils.h b/src/ax25_utils.h index dfcf864..8849024 100644 --- a/src/ax25_utils.h +++ b/src/ax25_utils.h @@ -43,6 +43,7 @@ namespace AX25_Utils { String encodeAX25Address(const String& frame, uint8_t type, const bool lastAddress); String LoRaPacketToAX25Frame(const String& packet); + String encodeKISS(const String& frame); } #endif \ No newline at end of file diff --git a/src/ble_utils.cpp b/src/ble_utils.cpp index c0f81ac..6c3d655 100644 --- a/src/ble_utils.cpp +++ b/src/ble_utils.cpp @@ -126,7 +126,7 @@ namespace BLE_Utils { delay(3); } - void txToPhoneOverBLE(const String& frame) { + /*void txToPhoneOverBLE(const String& frame) { if (Config.bluetooth.type == 0) { txBLE((byte)KissChar::Fend); txBLE((byte)KissCmd::Data); @@ -152,6 +152,37 @@ namespace BLE_Utils { } else if (Config.bluetooth.type == 2) { txBLE('\n'); } + }*/ + + void txToPhoneOverBLE(const String& frame) { + if (Config.bluetooth.type == 0) { // AX25 KISS + const String kissEncodedFrame = AX25_Utils::encodeKISS(frame); + //const String kissEncodedFrame = AX25_Utils::LoRaPacketToAX25Frame(frame); // aqui faltaria el paso de transformalo en KISS + + const char* t = kissEncodedFrame.c_str(); + int length = kissEncodedFrame.length(); + + const int CHUNK_SIZE = 64; + + for (int i = 0; i < length; i += CHUNK_SIZE) { + int chunkSize = (length - i < CHUNK_SIZE) ? (length - i) : CHUNK_SIZE; + + uint8_t* chunk = new uint8_t[chunkSize]; + memcpy(chunk, t + i, chunkSize); + + pCharacteristicTx->setValue(chunk, chunkSize); + pCharacteristicTx->notify(); + + delete[] chunk; + + delay(200); + } + } else { // TNC2 + for(int n = 0; n < frame.length(); n++) { + txBLE(frame[n]); + } + txBLE('\n'); + } } void sendToPhone(const String& packet) { @@ -161,11 +192,12 @@ namespace BLE_Utils { for (int i = 0; i < packet.length(); i++) { receivedPacketString += packet[i]; } - if (Config.bluetooth.type == 0) { + /*if (Config.bluetooth.type == 0) { // mod de Damian ? pero perder encodeador? txToPhoneOverBLE(AX25_Utils::LoRaPacketToAX25Frame(receivedPacketString)); } else if (Config.bluetooth.type == 2) { txToPhoneOverBLE(receivedPacketString); - } + }*/ + txToPhoneOverBLE(receivedPacketString); } } diff --git a/src/kiss_utils.cpp b/src/kiss_utils.cpp new file mode 100644 index 0000000..09cbe5d --- /dev/null +++ b/src/kiss_utils.cpp @@ -0,0 +1,12 @@ +#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); + } + +} \ No newline at end of file diff --git a/src/kiss_protocol.h b/src/kiss_utils.h similarity index 77% rename from src/kiss_protocol.h rename to src/kiss_utils.h index 7149bea..7de956c 100644 --- a/src/kiss_protocol.h +++ b/src/kiss_utils.h @@ -1,3 +1,9 @@ +#ifndef KISS_UTILS_H +#define KISS_UTILS_H + +#include + + #define DCD_ON 0x03 #define FEND 0xC0 @@ -20,4 +26,13 @@ #define APRS_INFORMATION_FIELD 0xf0 #define HAS_BEEN_DIGIPITED_MASK 0b10000000 -#define IS_LAST_ADDRESS_POSITION_MASK 0b1 \ No newline at end of file +#define IS_LAST_ADDRESS_POSITION_MASK 0b1 + + +namespace KISS_Utils { + + bool validateTNC2Frame(const String& tnc2FormattedFrame); + +} + +#endif