Fully functioning KISS TNC

This commit is contained in:
2022-05-13 16:24:49 +02:00
parent fcaf1e7d1d
commit 043fdf6e54
13 changed files with 32149 additions and 30664 deletions

View File

@@ -4,7 +4,7 @@
* KISS encoder uses two steps:
*
* Step 1: encodes the LoRa APRS frame into an AX.25 frame. DONE
* Step 2: encapsulates the AX.25 frame into a KISS frame. TODO
* Step 2: encapsulates the AX.25 frame into a KISS frame. DONE
*
* struct aprs_frame {
* uint8_t source_address[10];
@@ -27,6 +27,9 @@ uint16_t KissClass::EncodeFrame(struct aprs_frame *aprsframe, struct ax25_frame
uint16_t cnt=0;
uint16_t position = 0;
uint8_t digi_cnt = 0;
uint8_t escaped_string_cnt=0;
//printf("Encode KISS");
// Destination call
//printf("Destination: ");
@@ -35,7 +38,7 @@ uint16_t KissClass::EncodeFrame(struct aprs_frame *aprsframe, struct ax25_frame
while (cnt < 7)
{
ax25frame->complete[position] = *(encoded_call+cnt);
////printf("0x%X ", *(encoded_call+cnt));
//printf("0x%X ", *(encoded_call+cnt));
//printf("0x%X ", ax25frame->complete[position]);
cnt++;
position++;
@@ -49,7 +52,7 @@ uint16_t KissClass::EncodeFrame(struct aprs_frame *aprsframe, struct ax25_frame
while (cnt < 7)
{
ax25frame->complete[position] = *(encoded_call+cnt);
////printf("0x%X ", *(encoded_call+cnt));
//printf("0x%X ", *(encoded_call+cnt));
//printf("0x%X ", ax25frame->complete[position]);
cnt++;
position++;
@@ -73,7 +76,7 @@ uint16_t KissClass::EncodeFrame(struct aprs_frame *aprsframe, struct ax25_frame
encoded_call = EncodeCall(aprsframe->digis[digi_cnt]);
while (cnt < 7) {
ax25frame->complete[position] = *(encoded_call+cnt);
////printf("0x%X ", *(encoded_call+cnt));
//printf("0x%X ", *(encoded_call+cnt));
//printf("0x%X ", ax25frame->complete[position]);
cnt++;
position++;
@@ -109,6 +112,9 @@ uint16_t KissClass::EncodeFrame(struct aprs_frame *aprsframe, struct ax25_frame
// Encapsulate AX.25 frame in KISS frame (including escaping FEND codes)
putchar(FEND);
putchar(CMD_DATA);
escaped_string_cnt=0;
ax25frame->encoded_kiss_frame[escaped_string_cnt++] = FEND;
ax25frame->encoded_kiss_frame[escaped_string_cnt++] = CMD_DATA;
cnt=0;
position=ax25frame->lenght;
while (position-- != 0)
@@ -117,15 +123,21 @@ uint16_t KissClass::EncodeFrame(struct aprs_frame *aprsframe, struct ax25_frame
if (ax25frame->complete[cnt] == FEND) {
putchar(FESC);
putchar(TFEND);
ax25frame->encoded_kiss_frame[escaped_string_cnt++] = FESC;
ax25frame->encoded_kiss_frame[escaped_string_cnt++] = TFEND;
} else if (ax25frame->complete[cnt] == FESC) {
putchar(FESC);
putchar(TFESC);
ax25frame->encoded_kiss_frame[escaped_string_cnt++] = FESC;
ax25frame->encoded_kiss_frame[escaped_string_cnt++] = TFESC;
} else {
putchar(ax25frame->complete[cnt]);
ax25frame->encoded_kiss_frame[escaped_string_cnt++] = ax25frame->complete[cnt];
}
cnt++;
}
putchar(FEND);
ax25frame->encoded_kiss_frame[escaped_string_cnt++] = FEND;
//printf("\n");
@@ -136,13 +148,21 @@ uint16_t KissClass::EncodeFrame(struct aprs_frame *aprsframe, struct ax25_frame
* Decodes a KISS frame from the usb serial port
*
* Input : string starting with FEND and ending with FEND
* Output: ax25frame->decoded_kiss_frame terminated with NULL
* Output: filled struct AprsFrame
* Return: 0 = OK, 1 = ERROR, 2 = EXIT KISS MODE
*/
uint16_t KissClass::DecodeFrame(uint8_t string[], struct ax25_frame *ax25frame)
uint16_t KissClass::DecodeFrame(uint8_t string[], struct kiss_tx_frame *kisstxframe)
{
uint16_t position =0 ;
uint16_t loop_counter = 0;
uint16_t cnt =0 ;
uint16_t ssid = 0;
uint16_t last_digi = 0;
uint16_t digi_cnt = 0;
//printf("Decode KISS");
kisstxframe->valid_data = false;
// Not a valid frame
if (string[position] != FEND)
@@ -182,6 +202,176 @@ uint16_t KissClass::DecodeFrame(uint8_t string[], struct ax25_frame *ax25frame)
}
// If we are here we have a valid AX.25 frame in 'string' which is decapsulated from its KISS frame
/*
0-5 destination
6 destination ssid
7-12 source
13 desitination sidd
vanaf byte 13 LAST FLAG zoeken
03
f0
payload tot aan NULL
*/
// Decode destination call
position = 0;
cnt = 0;
loop_counter = 0;
while (loop_counter < 6)
{
kisstxframe->digis[0][cnt] = string[position] >> 1;
// Remove space
if (kisstxframe->digis[0][cnt] == ' ')
cnt--;
position++;
loop_counter++;
cnt++;
//printf("%u ", position);
}
// Extract SSID
//printf("position: %u\n", position);
ssid = (string[position] & 0b00011110) >> 1;
//printf("DIGI SSID: %u (%u)\n", ssid, position);
// Place SSID behind call or not if it is zero
if (ssid != 0) {
kisstxframe->digis[0][cnt++] = '-';
if (ssid < 10)
{
kisstxframe->digis[0][cnt++] = ssid + 48;
}
else
{
kisstxframe->digis[0][cnt++] = '1';
kisstxframe->digis[0][cnt++] = (ssid%10)+48;
}
}
// Is has-been-repeated flag set?
if(string[position] & 0b10000000) {
kisstxframe->digis[0][cnt] = '*';
cnt++;
}
kisstxframe->digis[0][cnt] = 0; //terminate string
position++;
// Decode source call
cnt = 0;
loop_counter=0;
while (loop_counter < 6)
{
kisstxframe->source_address[cnt] = string[position] >> 1;
// Remove space
if (kisstxframe->source_address[cnt] == ' ')
cnt--;
position++;
loop_counter++;
cnt++;
//printf("%u ", position);
}
// Extract SSID
ssid = (string[position] & 0b00011110) >> 1;
//printf("sources SSID: %u (%u)\n", ssid, position);
// Place SSID behind call or not if it is zero
if (ssid != 0) {
kisstxframe->source_address[cnt++] = '-';
if (ssid < 10)
{
kisstxframe->source_address[cnt++] = ssid + 48;
}
else
{
kisstxframe->source_address[cnt++] = '1';
kisstxframe->source_address[cnt++] = (ssid%10)+48;
}
}
// Is has-been-repeated flag set?
if(string[position] & 0b10000000) {
kisstxframe->source_address[cnt] = '*';
cnt++;
}
kisstxframe->source_address[cnt] = 0; //terminate string
// Check LAST flag
if ( (string[position] & 0b00000001))
last_digi = 1;
position++;
// Decode digi path
digi_cnt=1;
while (last_digi == 0) {
cnt = 0;
loop_counter=0;
while (loop_counter < 6)
{
kisstxframe->digis[digi_cnt][cnt] = string[position] >> 1;
// Remove space
if (kisstxframe->digis[digi_cnt][cnt] == ' ')
cnt--;
position++;
loop_counter++;
cnt++;
//printf("%u ", position);
}
// Extract SSID
ssid = (string[position] & 0b00011110) >> 1;
//printf("DIGI SSID: %u (%u)\n", ssid, position);
// Place SSID behind call or not if it is zero
if (ssid != 0) {
kisstxframe->digis[digi_cnt][cnt++] = '-';
if (ssid < 10)
{
kisstxframe->digis[digi_cnt][cnt++] = ssid + 48;
}
else
{
kisstxframe->digis[digi_cnt][cnt++] = '1';
kisstxframe->digis[digi_cnt][cnt++] = (ssid%10) + 48;
}
}
// Is has-been-repeated flag set?
if(string[position] & 0b10000000) {
kisstxframe->digis[digi_cnt][cnt] = '*';
cnt++;
}
kisstxframe->digis[digi_cnt][cnt] = 0; //terminate string
// Check LAST flag (also ends when more than 10 digis)
if ( (string[position] & 0b00000001) || digi_cnt > 8)
last_digi = 1;
digi_cnt++;
position++;
}
kisstxframe->number_of_digipeaters = digi_cnt-1;
//printf("Digipeaters: %u \n",kisstxframe->number_of_digipeaters );
//Skip the two control fields
position++;
position++;
//Rest of string up to NULL is payload
cnt = 0;
kisstxframe->data_field[cnt++] = ':';
while (string[position] != 0 && position < 512)
{
kisstxframe->data_field[cnt] = string[position];
position++;
cnt++;
}
kisstxframe->data_field[cnt] = 0; //terminate string
kisstxframe->valid_data = true;
return 0;
}
@@ -197,10 +387,26 @@ uint8_t * KissClass::EncodeCall(uint8_t string[])
{
uint8_t position = 0;
uint8_t cnt = 0;
uint8_t repeat_flag = 0;
static uint8_t call[7] = { 0,0,0,0,0,0,0} ;
uint8_t ssid = 0;
// if asterix is pressent in string, than the message has been repeated, so set the 'has been repeated' flag in the ssid register
// At the same time delete the asterix and place a NULL (string terminator) at its place. As the asterix should be the last character in the string, this should work.
position = 0;
while( string[position] != 0)
{
if (string[position] == '*') {
repeat_flag = 1;
string[position] == 0;
break;
}
position++;
}
position = 0;
// extract call
while( string[position] != 0 || cnt < 6)
{
@@ -229,17 +435,11 @@ uint8_t * KissClass::EncodeCall(uint8_t string[])
}
}
// if asterix is pressent in string, than the message has been repeated, so set the 'has been repeated' flag in the ssid register
position = 0;
while( string[position] != 0)
{
if (string[position] == '*')
ssid = 0b10000000;
position++;
}
ssid = ssid << 1;
ssid |= 0b01100000;
ssid = (ssid << 1) | 0b01100000;
if (repeat_flag == 1)
ssid |= 0b10000000;
// add encoded ssid to encoded call array
call[6] = ssid;

View File

@@ -39,15 +39,27 @@
struct ax25_frame {
uint8_t complete[512];
uint16_t lenght = 0;
uint8_t encoded_kiss_frame[512];
uint8_t decoded_kiss_frame[512];
uint16_t kiss_length = 0;
};
struct kiss_tx_frame {
uint8_t source_address[10];
uint8_t data_field[512];
uint8_t digis[10][10];
uint16_t number_of_digipeaters = 0;
uint8_t lora_string[512];
uint8_t valid_data = false;
};
class KissClass
{
public:
uint16_t EncodeFrame(struct aprs_frame *frame, struct ax25_frame *ax25frame);
uint16_t DecodeFrame(uint8_t string[], struct ax25_frame *ax25frame);
uint16_t DecodeFrame(uint8_t string[], struct kiss_tx_frame *kisstxframe);
private:
uint8_t * EncodeCall(uint8_t string[]);
};

View File

@@ -11,7 +11,9 @@
#include "hardware/claim.h"
KissClass Kiss;
struct ax25_frame AX25Frame; //defined in kiss.h
struct ax25_frame AX25Frame; //defined in kiss.h
struct aprs_frame AprsFrame; //defined in kiss.h
struct kiss_tx_frame KissTxFrame; //defined in kiss.h
bool startRadio();
void getPacketData(int packetLength);
@@ -23,6 +25,7 @@ uint16_t decode_packet ();
/* declaration for transmit functions */
void ComposeAprsFrame(uint8_t payload[]);
void ComposeAprsFrameFromKiss();
bool TransmitRequest = false;
void transmit();
@@ -433,6 +436,7 @@ void ReadUSBSerial(void)
static char strg[512];
int chr;
static int lp = 0;
uint16_t tmp;
if (Status.KissMode == OFF) {
// Read serial port (USB) - non-blocking!
@@ -472,15 +476,21 @@ void ReadUSBSerial(void)
// Received FEND (=begin or end frame)
if(chr == FEND)
{
// Valid FISS frame received
// Valid KISS frame received
if (strg[0] == FEND && lp > 1)
{
if (Kiss.DecodeFrame((uint8_t *) strg, &AX25Frame) == 2)
tmp = Kiss.DecodeFrame((uint8_t *) strg, &KissTxFrame);
if ( tmp == 2)
{
//exit KISS MODE
stdio_set_translate_crlf(&stdio_usb, true);
Status.KissMode = OFF;
}
// Valid KISS data frame, so lets send it
else if (tmp == 0)
{
ComposeAprsFrameFromKiss();
}
lp = 0; //reset string buffer pointer
}
// We received a FEND byte,so we are probably between two KISS frames. Let's assume the latest FEND is the beginning of a new frame
@@ -682,8 +692,6 @@ uint16_t decode_packet ()
int position = 0;
int cnt = 0;
struct aprs_frame AprsFrame; //defined in kiss.h
memset(AprsFrame.source_address, 0, sizeof(AprsFrame.source_address));
memset(AprsFrame.digi_path, 0, sizeof(AprsFrame.digi_path));
memset(AprsFrame.data_field, 0, sizeof(AprsFrame.data_field));
@@ -809,8 +817,11 @@ uint16_t decode_packet ()
log_out("Source address: %s\nDigipeaters (%u): %s %s %s %s\nData: %s\n", AprsFrame.source_address, AprsFrame.number_of_digipeaters+1, AprsFrame.digis[0], AprsFrame.digis[1], AprsFrame.digis[2], AprsFrame.digis[3], AprsFrame.data_field);
// If in KISS mode the struct AprsFrame is handed over to the KISS encoder
if (Status.KissMode == ON)
if (Status.KissMode == ON) {
Kiss.EncodeFrame(&AprsFrame, &AX25Frame);
//if (Kiss.DecodeFrame(AX25Frame.encoded_kiss_frame, &KissTxFrame) == 0)
//ComposeAprsFrameFromKiss();
}
if (AprsFrame.message[0])
{
@@ -960,6 +971,61 @@ void ComposeAprsFrame(uint8_t payload[])
log_out("%s\n", txBuffer);
}
void ComposeAprsFrameFromKiss()
{
uint16_t BufferPosition = 0;
uint16_t cnt = 0;
uint8_t digi_cnt=0;
log_out( "Compose APRS from KISS frame");
memset(txBuffer, 0, sizeof(txBuffer));
// APRS header
txBuffer[BufferPosition++] = '<';
txBuffer[BufferPosition++] = 0xff;
txBuffer[BufferPosition++] = 0x01;
while ( KissTxFrame.source_address[cnt] != 0 && BufferPosition<MTU )
{
txBuffer[BufferPosition] = KissTxFrame.source_address[cnt];
BufferPosition++;
cnt++;
}
txBuffer[BufferPosition++] = '>';
digi_cnt=0;
while(digi_cnt <= KissTxFrame.number_of_digipeaters) {
cnt=0;
while ( KissTxFrame.digis[digi_cnt][cnt] != 0 && BufferPosition<MTU )
{
txBuffer[BufferPosition++] = KissTxFrame.digis[digi_cnt][cnt];
cnt++;
}
txBuffer[BufferPosition++] = ',';
digi_cnt++;
}
// Overwrite last command with colon
txBuffer[--BufferPosition] = ':';
cnt=0;
while ( KissTxFrame.data_field[cnt] != 0 && BufferPosition<MTU )
{
txBuffer[BufferPosition++] = KissTxFrame.data_field[cnt];
cnt++;
}
// Set variable to indicate a send request
TransmitRequest = true;
// Ready for next input KISS frame.
KissTxFrame.valid_data = false;
log_out("%s\n", txBuffer);
}
void transmit() {
uint16_t position = 0;