From a11eca1c28b4e0cdfd317ed6ae549de1b896043a Mon Sep 17 00:00:00 2001 From: sq8vps Date: Sun, 3 Sep 2023 10:49:47 +0200 Subject: [PATCH 1/5] kiss escape chars handling --- Src/ax25.c | 39 +++++++++++++++++++++++++++++++++++---- Src/terminal.c | 22 ++++++++++++++++++---- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/Src/ax25.c b/Src/ax25.c index 3dbce4e..ed69a64 100644 --- a/Src/ax25.c +++ b/Src/ax25.c @@ -154,9 +154,10 @@ void Ax25TxKiss(uint8_t *buf, uint16_t len) } for(uint16_t i = 0; i < len; i++) { - if(buf[i] == 0xC0) //frame start marker + if((buf[i] == 0xC0) && ((buf[i + 1] & 0xF) == 0)) //frame start marker and type is data frame { - uint16_t end = i + 1; + i += 2; //skip 0xC0 and type + uint16_t end = i; while(end < len) { if(buf[end] == 0xC0) @@ -165,8 +166,38 @@ void Ax25TxKiss(uint8_t *buf, uint16_t len) } if(end == len) //no frame end marker found return; - Ax25WriteTxFrame(&buf[i + 2], end - (i + 2)); //skip modem number and send frame - DigiStoreDeDupe(&buf[i + 2], end - (i + 2)); + + uint16_t modifiedEnd = end; + + for(uint16_t j = i; j < modifiedEnd; j++) + { + if(buf[j] == 0xDB) //escape character + { + if(buf[j + 1] == 0xDC) //transposed frame end + { + buf[j] = 0xC0; + } + else if(buf[j + 1] == 0xDD) //transposed frame escape + { + buf[j] = 0xDB; + } + else + { + j++; + continue; + } + + j++; + modifiedEnd--; + for(uint16_t k = j; k < modifiedEnd; k++) + { + buf[k] = buf[k + 1]; + } + } + } + + Ax25WriteTxFrame(&buf[i], modifiedEnd - i); //skip modem number and send frame + DigiStoreDeDupe(&buf[i], modifiedEnd - i); i = end; //move pointer to the next byte if there are more consecutive frames } } diff --git a/Src/terminal.c b/Src/terminal.c index f4ef73f..08aa0a3 100644 --- a/Src/terminal.c +++ b/Src/terminal.c @@ -62,12 +62,26 @@ void TermHandleSpecial(Uart *u) static void sendKiss(Uart *port, uint8_t *buf, uint16_t len) { - if(port->mode == MODE_KISS) //check if KISS mode + if(port->mode == MODE_KISS) { - UartSendByte(port, 0xc0); //send data in kiss format + UartSendByte(port, 0xC0); UartSendByte(port, 0x00); - UartSendString(port, buf, len); - UartSendByte(port, 0xc0); + for(uint16_t i = 0; i < len; i++) + { + if(buf[i] == 0xC0) //frame end in data + { + UartSendByte(port, 0xDB); //frame escape + UartSendByte(port, 0xDC); //transposed frame end + } + else if(buf[i] == 0xDB) //frame escape in data + { + UartSendByte(port, 0xDB); //frame escape + UartSendByte(port, 0xDD); //transposed frame escape + } + else + UartSendByte(port, buf[i]); + } + UartSendByte(port, 0xC0); } } From c0d90a379317f11ae7d8bc18c8699dfd1b193219 Mon Sep 17 00:00:00 2001 From: sq8vps Date: Mon, 4 Sep 2023 09:54:16 +0200 Subject: [PATCH 2/5] KISS handling improvements --- Inc/ax25.h | 9 +---- Inc/drivers/uart.h | 20 ++-------- Inc/kiss.h | 41 +++++++++++++++++++ Src/ax25.c | 70 +++------------------------------ Src/digipeater.c | 3 +- Src/drivers/uart.c | 38 ++++-------------- Src/kiss.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++ Src/main.c | 1 - Src/terminal.c | 43 ++------------------ Src/usbd_cdc_if.c | 13 ++---- 10 files changed, 166 insertions(+), 170 deletions(-) create mode 100644 Inc/kiss.h create mode 100644 Src/kiss.c diff --git a/Inc/ax25.h b/Inc/ax25.h index 1c524db..a87845b 100644 --- a/Inc/ax25.h +++ b/Inc/ax25.h @@ -23,7 +23,8 @@ along with VP-Digi. If not, see . #include #include - +#define AX25_FRAME_MAX_SIZE (308) //single frame max length for RX +//308 bytes is the theoretical max size assuming 2-byte Control, 256-byte info field and 5 digi address fields enum Ax25RxStage @@ -43,12 +44,6 @@ struct Ax25ProtoConfig extern struct Ax25ProtoConfig Ax25Config; -/** - * @brief Transmit one or more frames encoded in KISS format - * @param *buf Inout buffer - * @param len Buffer size - */ -void Ax25TxKiss(uint8_t *buf, uint16_t len); /** * @brief Write frame to transmit buffer diff --git a/Inc/drivers/uart.h b/Inc/drivers/uart.h index 588b373..e369ddd 100644 --- a/Inc/drivers/uart.h +++ b/Inc/drivers/uart.h @@ -25,7 +25,7 @@ along with VP-Digi. If not, see . #include "usbd_cdc_if.h" #include "ax25.h" -#define UART_BUFFER_SIZE 250 +#define UART_BUFFER_SIZE 130 enum UartMode { @@ -37,7 +37,6 @@ enum UartMode enum UartDataType { DATA_NOTHING = 0, - DATA_KISS, DATA_TERM, DATA_USB, }; @@ -55,20 +54,14 @@ typedef struct uint16_t txBufferHead, txBufferTail; uint8_t txBufferFull : 1; enum UartMode mode; - uint32_t kissTimer; uint16_t lastRxBufferHead; //for special characters handling + uint8_t kissBuffer[AX25_FRAME_MAX_SIZE + 1]; + uint16_t kissBufferHead; } Uart; extern Uart Uart1, Uart2, UartUsb; -///** -// * \brief Copy KISS frame(s) from input buffer to APRS TX buffer -// * \param[in] *buf Input buffer -// * \param[in] len Input buffer size -// */ -//uint8_t Uart_txKiss(uint8_t *buf, uint16_t len); - /** * @brief Send byte * @param[in] *port UART @@ -113,11 +106,4 @@ void UartConfig(Uart *port, uint8_t state); */ void UartClearRx(Uart *port); -/** - * @brief Handle KISS timeout - * @param *port UART pointer - * @attention This function must be polled constantly in main loop for USB UART. - */ -void UartHandleKissTimeout(Uart *port); - #endif diff --git a/Inc/kiss.h b/Inc/kiss.h new file mode 100644 index 0000000..bcf48bf --- /dev/null +++ b/Inc/kiss.h @@ -0,0 +1,41 @@ +/* +Copyright 2020-2023 Piotr Wilkon + +This file is part of VP-Digi. + +VP-Digi 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; either version 3 of the License, or +(at your option) any later version. + +VP-Digi 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 for more details. + +You should have received a copy of the GNU General Public License +along with VP-Digi. If not, see . +*/ + +#ifndef KISS_H_ +#define KISS_H_ + +#include +#include "drivers/uart.h" + +/** + * @brief Convert AX.25 frame to KISS and send + * @param *port UART structure + * @param *buf Frame buffer + * @param size Frame size + */ +void KissSend(Uart *port, uint8_t *buf, uint16_t size); + +/** + * @brief Parse bytes received from UART to form a KISS frame (possibly) and send this frame + * @param *port UART structure + * @param data Received byte + */ +void KissParse(Uart *port, uint8_t data); + +#endif /* KISS_H_ */ diff --git a/Src/ax25.c b/Src/ax25.c index ed69a64..0f2d74b 100644 --- a/Src/ax25.c +++ b/Src/ax25.c @@ -27,11 +27,9 @@ along with VP-Digi. If not, see . struct Ax25ProtoConfig Ax25Config; -//values below must be kept consistent so that FRAME_BUFFER_SIZE >= FRAME_MAX_SIZE * FRAME_MAX_COUNT -#define FRAME_MAX_SIZE (308) //single frame max length for RX -//308 bytes is the theoretical max size assuming 2-byte Control, 256-byte info field and 5 digi address fields + #define FRAME_MAX_COUNT (10) //max count of frames in buffer -#define FRAME_BUFFER_SIZE (FRAME_MAX_COUNT * FRAME_MAX_SIZE) //circular frame buffer length +#define FRAME_BUFFER_SIZE (FRAME_MAX_COUNT * AX25_FRAME_MAX_SIZE) //circular frame buffer length #define STATIC_HEADER_FLAG_COUNT 4 //number of flags sent before each frame #define STATIC_FOOTER_FLAG_COUNT 8 //number of flags sent after each frame @@ -98,7 +96,7 @@ static enum TxStage txStage; //current TX stage struct RxState { uint16_t crc; //current CRC - uint8_t frame[FRAME_MAX_SIZE]; //raw frame buffer + uint8_t frame[AX25_FRAME_MAX_SIZE]; //raw frame buffer uint16_t frameIdx; //index for raw frame buffer uint8_t receivedByte; //byte being currently received uint8_t receivedBitIdx; //bit index for recByte @@ -115,7 +113,7 @@ static uint16_t rxMultiplexDelay = 0; //simple delay for decoder multiplexer to static uint16_t txDelay; //number of TXDelay bytes to send static uint16_t txTail; //number of TXTail bytes to send -static uint8_t outputFrameBuffer[FRAME_MAX_SIZE]; +static uint8_t outputFrameBuffer[AX25_FRAME_MAX_SIZE]; #define GET_FREE_SIZE(max, head, tail) (((head) < (tail)) ? ((tail) - (head)) : ((max) - (head) + (tail))) #define GET_USED_SIZE(max, head, tail) (max - GET_FREE_SIZE(max, head, tail)) @@ -146,62 +144,6 @@ void Ax25ClearReceivedFrameBitmap(void) frameReceived = 0; } -void Ax25TxKiss(uint8_t *buf, uint16_t len) -{ - if(len < 18) //frame is too small - { - return; - } - for(uint16_t i = 0; i < len; i++) - { - if((buf[i] == 0xC0) && ((buf[i + 1] & 0xF) == 0)) //frame start marker and type is data frame - { - i += 2; //skip 0xC0 and type - uint16_t end = i; - while(end < len) - { - if(buf[end] == 0xC0) - break; - end++; - } - if(end == len) //no frame end marker found - return; - - uint16_t modifiedEnd = end; - - for(uint16_t j = i; j < modifiedEnd; j++) - { - if(buf[j] == 0xDB) //escape character - { - if(buf[j + 1] == 0xDC) //transposed frame end - { - buf[j] = 0xC0; - } - else if(buf[j + 1] == 0xDD) //transposed frame escape - { - buf[j] = 0xDB; - } - else - { - j++; - continue; - } - - j++; - modifiedEnd--; - for(uint16_t k = j; k < modifiedEnd; k++) - { - buf[k] = buf[k + 1]; - } - } - } - - Ax25WriteTxFrame(&buf[i], modifiedEnd - i); //skip modem number and send frame - DigiStoreDeDupe(&buf[i], modifiedEnd - i); - i = end; //move pointer to the next byte if there are more consecutive frames - } - } -} void *Ax25WriteTxFrame(uint8_t *data, uint16_t size) { @@ -340,7 +282,7 @@ void Ax25BitParse(uint8_t bit, uint8_t modem) } - if((rx->rawData & 0x7F) == 0x7F) //received 7 consecutive ones, this is an error (sometimes called "escape byte") + if((rx->rawData & 0x7F) == 0x7F) //received 7 consecutive ones, this is an error { rx->rx = RX_STAGE_FLAG; ModemClearRMS(modem); @@ -365,7 +307,7 @@ void Ax25BitParse(uint8_t bit, uint8_t modem) if(++rx->receivedBitIdx >= 8) //received full byte { - if(rx->frameIdx > FRAME_MAX_SIZE) //frame is too long + if(rx->frameIdx > AX25_FRAME_MAX_SIZE) //frame is too long { rx->rx = RX_STAGE_IDLE; ModemClearRMS(modem); diff --git a/Src/digipeater.c b/Src/digipeater.c index f167048..fc01194 100644 --- a/Src/digipeater.c +++ b/Src/digipeater.c @@ -52,8 +52,7 @@ static struct DeDupeData deDupe[DEDUPE_SIZE]; //duplicate protection hash buffer static uint8_t deDupeCount = 0; //duplicate protection buffer index -#define DIGI_BUFFER_SIZE 308 //308 is the theoretical max under some assumptions, see ax25.c -static uint8_t buf[DIGI_BUFFER_SIZE]; +static uint8_t buf[AX25_FRAME_MAX_SIZE]; /** * @brief Check if frame with specified hash is already in viscous-delay buffer and delete it if so diff --git a/Src/drivers/uart.c b/Src/drivers/uart.c index 544bcdb..69c544d 100644 --- a/Src/drivers/uart.c +++ b/Src/drivers/uart.c @@ -24,6 +24,7 @@ along with VP-Digi. If not, see . #include "common.h" #include #include "digipeater.h" +#include "kiss.h" Uart Uart1, Uart2, UartUsb; @@ -32,28 +33,21 @@ static void handleInterrupt(Uart *port) if(port->port->SR & USART_SR_RXNE) //byte received { port->port->SR &= ~USART_SR_RXNE; - port->rxBuffer[port->rxBufferHead++] = port->port->DR; //store it + uint8_t data = port->port->DR; + port->rxBuffer[port->rxBufferHead++] = data; //store it port->rxBufferHead %= UART_BUFFER_SIZE; + KissParse(port, data); TermHandleSpecial(port); - - if(port->mode == MODE_KISS) - port->kissTimer = SysTickGet() + (5000 / SYSTICK_INTERVAL); //set timeout to 5s in KISS mode } if(port->port->SR & USART_SR_IDLE) //line is idle, end of data reception { port->port->DR; //reset idle flag by dummy read if(port->rxBufferHead != 0) { - if((port->rxBuffer[0] == 0xC0) && (port->rxBuffer[port->rxBufferHead - 1] == 0xC0)) //data starts with 0xc0 and ends with 0xc0 - this is a KISS frame - { - port->rxType = DATA_KISS; - port->kissTimer = 0; - } - else if(((port->rxBuffer[port->rxBufferHead - 1] == '\r') || (port->rxBuffer[port->rxBufferHead - 1] == '\n'))) //data ends with \r or \n, process as data + if(((port->rxBuffer[port->rxBufferHead - 1] == '\r') || (port->rxBuffer[port->rxBufferHead - 1] == '\n'))) //data ends with \r or \n, process as data { port->rxType = DATA_TERM; - port->kissTimer = 0; } } } @@ -61,7 +55,7 @@ static void handleInterrupt(Uart *port) { if((port->txBufferHead != port->txBufferTail) || port->txBufferFull) //if there is anything to transmit { - port->port->DR = port->txBuffer[port->txBufferTail++]; //push it to the refister + port->port->DR = port->txBuffer[port->txBufferTail++]; //push it to the register port->txBufferTail %= UART_BUFFER_SIZE; port->txBufferFull = 0; } @@ -70,13 +64,6 @@ static void handleInterrupt(Uart *port) port->port->CR1 &= ~USART_CR1_TXEIE; } } - - if((port->kissTimer > 0) && (SysTickGet() >= port->kissTimer)) //KISS timer timeout - { - port->kissTimer = 0; - port->rxBufferHead = 0; - memset(port->rxBuffer, 0, sizeof(port->rxBuffer)); - } } void USART1_IRQHandler(void) __attribute__ ((interrupt)); @@ -160,12 +147,13 @@ void UartInit(Uart *port, USART_TypeDef *uart, uint32_t baud) port->txBufferHead = 0; port->txBufferTail = 0; port->txBufferFull = 0; + port->kissBufferHead = 0; port->mode = MODE_KISS; port->enabled = 0; - port->kissTimer = 0; port->lastRxBufferHead = 0; memset(port->rxBuffer, 0, sizeof(port->rxBuffer)); memset(port->txBuffer, 0, sizeof(port->txBuffer)); + memset(port->kissBuffer, 0, sizeof(port->kissBuffer)); } @@ -236,13 +224,3 @@ void UartClearRx(Uart *port) port->rxBufferHead = 0; port->rxType = DATA_NOTHING; } - -void UartHandleKissTimeout(Uart *port) -{ - if((port->kissTimer > 0) && (SysTickGet() >= port->kissTimer)) //KISS timer timeout - { - port->kissTimer = 0; - port->rxBufferHead = 0; - memset(port->rxBuffer, 0, sizeof(port->rxBuffer)); - } -} diff --git a/Src/kiss.c b/Src/kiss.c new file mode 100644 index 0000000..95d5967 --- /dev/null +++ b/Src/kiss.c @@ -0,0 +1,98 @@ +/* +Copyright 2020-2023 Piotr Wilkon + +This file is part of VP-Digi. + +VP-Digi 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; either version 3 of the License, or +(at your option) any later version. + +VP-Digi 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 for more details. + +You should have received a copy of the GNU General Public License +along with VP-Digi. If not, see . +*/ + +#include "kiss.h" +#include "ax25.h" +#include "digipeater.h" + +void KissSend(Uart *port, uint8_t *buf, uint16_t size) +{ + if(port->mode == MODE_KISS) + { + UartSendByte(port, 0xC0); + UartSendByte(port, 0x00); + for(uint16_t i = 0; i < size; i++) + { + if(buf[i] == 0xC0) //frame end in data + { + UartSendByte(port, 0xDB); //frame escape + UartSendByte(port, 0xDC); //transposed frame end + } + else if(buf[i] == 0xDB) //frame escape in data + { + UartSendByte(port, 0xDB); //frame escape + UartSendByte(port, 0xDD); //transposed frame escape + } + else + UartSendByte(port, buf[i]); + } + UartSendByte(port, 0xC0); + } +} + + +void KissParse(Uart *port, uint8_t data) +{ + if(data == 0xC0) //frame end marker + { + if(port->kissBufferHead < 17) //command+source+destination+PID+Control=17 + { + port->kissBufferHead = 0; + return; + } + + if((port->kissBuffer[0] & 0xF) != 0) //check if this is an actual frame + { + port->kissBufferHead = 0; + return; + } + + //simple sanity check + //check if LSbits in the first 13 bytes are set to 0 + //they should always be in an AX.25 frame + for(uint8_t i = 0; i < 13; i++) + { + if((port->kissBuffer[i + 1] & 1) != 0) + { + port->kissBufferHead = 0; + return; + } + } + + Ax25WriteTxFrame(&port->kissBuffer[1], port->kissBufferHead - 1); + DigiStoreDeDupe(&port->kissBuffer[1], port->kissBufferHead - 1); + port->kissBufferHead = 0; + return; + } + else if(port->kissBufferHead > 0) + { + if((data == 0xDC) && (port->kissBuffer[port->kissBufferHead - 1] == 0xDB)) //escape character with transposed frame end + { + port->kissBuffer[port->kissBufferHead - 1] = 0xC0; + return; + } + else if((data == 0xDD) && (port->kissBuffer[port->kissBufferHead - 1] == 0xDB)) //escape character with transposed escape character + { + port->kissBuffer[port->kissBufferHead - 1] = 0xDB; + return; + } + } + port->kissBuffer[port->kissBufferHead++] = data; + port->kissBufferHead %= sizeof(port->kissBuffer); +} diff --git a/Src/main.c b/Src/main.c index 156dd64..5c9bc9f 100644 --- a/Src/main.c +++ b/Src/main.c @@ -290,7 +290,6 @@ int main(void) TermParse(&Uart2); UartClearRx(&Uart2); } - UartHandleKissTimeout(&UartUsb); BeaconCheck(); //check beacons diff --git a/Src/terminal.c b/Src/terminal.c index 08aa0a3..bfb3a81 100644 --- a/Src/terminal.c +++ b/Src/terminal.c @@ -25,6 +25,7 @@ along with VP-Digi. If not, see . #include "drivers/modem.h" #include "ax25.h" #include "drivers/systick.h" +#include "kiss.h" void TermHandleSpecial(Uart *u) { @@ -60,38 +61,13 @@ void TermHandleSpecial(Uart *u) } -static void sendKiss(Uart *port, uint8_t *buf, uint16_t len) -{ - if(port->mode == MODE_KISS) - { - UartSendByte(port, 0xC0); - UartSendByte(port, 0x00); - for(uint16_t i = 0; i < len; i++) - { - if(buf[i] == 0xC0) //frame end in data - { - UartSendByte(port, 0xDB); //frame escape - UartSendByte(port, 0xDC); //transposed frame end - } - else if(buf[i] == 0xDB) //frame escape in data - { - UartSendByte(port, 0xDB); //frame escape - UartSendByte(port, 0xDD); //transposed frame escape - } - else - UartSendByte(port, buf[i]); - } - UartSendByte(port, 0xC0); - } -} - void TermSendToAll(enum UartMode mode, uint8_t *data, uint16_t size) { if(MODE_KISS == mode) { - sendKiss(&Uart1, data, size); - sendKiss(&Uart2, data, size); - sendKiss(&UartUsb, data, size); + KissSend(&Uart1, data, size); + KissSend(&Uart2, data, size); + KissSend(&UartUsb, data, size); } else if(MODE_MONITOR == mode) { @@ -119,9 +95,6 @@ void TermSendNumberToAll(enum UartMode mode, int32_t n) } - - - static const char monitorHelp[] = "\r\nCommans available in monitor mode:\r\n" "help - shows this help page\r\n" "cal {low|high|alt|stop} - transmits/stops transmitter calibration pattern\r\n" @@ -391,14 +364,6 @@ void TermParse(Uart *src) src->mode = MODE_MONITOR; return; } - /* - * KISS parsing - */ - else if((src->mode == MODE_KISS) && (src->rxType == DATA_KISS)) - { - Ax25TxKiss(src->rxBuffer, src->rxBufferHead); - return; - } /* * Monitor mode handling */ diff --git a/Src/usbd_cdc_if.c b/Src/usbd_cdc_if.c index 0bb8c0e..359b919 100644 --- a/Src/usbd_cdc_if.c +++ b/Src/usbd_cdc_if.c @@ -26,6 +26,7 @@ #include "drivers/uart.h" #include "drivers/systick.h" #include "terminal.h" +#include "kiss.h" /* USER CODE END INCLUDE */ /* Private typedef -----------------------------------------------------------*/ @@ -274,6 +275,7 @@ static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) for(uint16_t i = 0; i < *Len; i++) { UartUsb.rxBuffer[UartUsb.rxBufferHead++] = Buf[i]; + KissParse(&UartUsb, Buf[i]); UartUsb.rxBufferHead %= UART_BUFFER_SIZE; } @@ -322,20 +324,11 @@ uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) /* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */ static void handleUsbInterrupt(Uart *port) { - if(port->mode == MODE_KISS) - port->kissTimer = SysTickGet() + (5000 / SYSTICK_INTERVAL); //set timeout to 5s in KISS mode - if(port->rxBufferHead != 0) { - if((port->rxBuffer[0] == 0xC0) && (port->rxBuffer[port->rxBufferHead - 1] == 0xC0)) //data starts with 0xc0 and ends with 0xc0 - this is a KISS frame - { - port->rxType = DATA_KISS; - port->kissTimer = 0; - } - else if(((port->rxBuffer[port->rxBufferHead - 1] == '\r') || (port->rxBuffer[port->rxBufferHead - 1] == '\n'))) //data ends with \r or \n, process as data + if(((port->rxBuffer[port->rxBufferHead - 1] == '\r') || (port->rxBuffer[port->rxBufferHead - 1] == '\n'))) //data ends with \r or \n, process as data { port->rxType = DATA_TERM; - port->kissTimer = 0; } } } From f23d89dadbea0de7e57f7511938fe305c3706f6c Mon Sep 17 00:00:00 2001 From: sq8vps Date: Mon, 4 Sep 2023 10:25:26 +0200 Subject: [PATCH 3/5] concurrency handling --- Src/ax25.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Src/ax25.c b/Src/ax25.c index 0f2d74b..805366b 100644 --- a/Src/ax25.c +++ b/Src/ax25.c @@ -147,15 +147,11 @@ void Ax25ClearReceivedFrameBitmap(void) void *Ax25WriteTxFrame(uint8_t *data, uint16_t size) { - while(txStage != TX_STAGE_IDLE) - ; - if((GET_FREE_SIZE(FRAME_BUFFER_SIZE, txBufferHead, txBufferTail) < size) || txFrameBufferFull) { return NULL; } - txFrame[txFrameHead].size = size; txFrame[txFrameHead].start = txBufferHead; for(uint16_t i = 0; i < size; i++) @@ -164,10 +160,12 @@ void *Ax25WriteTxFrame(uint8_t *data, uint16_t size) txBufferHead %= FRAME_BUFFER_SIZE; } void *ret = &txFrame[txFrameHead]; + __disable_irq(); txFrameHead++; txFrameHead %= FRAME_MAX_COUNT; if(txFrameHead == txFrameTail) txFrameBufferFull = true; + __enable_irq(); return ret; } @@ -175,7 +173,9 @@ void *Ax25WriteTxFrame(uint8_t *data, uint16_t size) bool Ax25ReadNextRxFrame(uint8_t **dst, uint16_t *size, uint16_t *signalLevel) { if((rxFrameHead == rxFrameTail) && !rxFrameBufferFull) + { return false; + } *dst = outputFrameBuffer; @@ -187,9 +187,11 @@ bool Ax25ReadNextRxFrame(uint8_t **dst, uint16_t *size, uint16_t *signalLevel) *signalLevel = rxFrame[rxFrameTail].signalLevel; *size = rxFrame[rxFrameTail].size; + __disable_irq(); rxFrameBufferFull = false; rxFrameTail++; rxFrameTail %= FRAME_MAX_COUNT; + __enable_irq(); return true; } @@ -253,10 +255,12 @@ void Ax25BitParse(uint8_t bit, uint8_t modem) { rxFrame[rxFrameHead].start = rxBufferHead; rxFrame[rxFrameHead].signalLevel = ModemGetRMS(modem); + __disable_irq(); rxFrame[rxFrameHead++].size = rx->frameIdx; rxFrameHead %= FRAME_MAX_COUNT; - if(rxFrameHead == txFrameHead) + if(rxFrameHead == rxFrameTail) rxFrameBufferFull = true; + __enable_irq(); for(uint16_t i = 0; i < rx->frameIdx; i++) { @@ -369,8 +373,10 @@ uint8_t Ax25GetTxBit(void) if(txStage == TX_STAGE_DATA) //transmitting normal data { transmitNormalData: + __disable_irq(); if((txFrameHead != txFrameTail) || txFrameBufferFull) { + __enable_irq(); if(txByteIdx < txFrame[txFrameTail].size) //send buffer { txByte = txBuffer[(txFrame[txFrameTail].start + txByteIdx) % FRAME_BUFFER_SIZE]; @@ -384,6 +390,7 @@ transmitNormalData: } else //no more frames { + __enable_irq(); txByteIdx = 0; txBitIdx = 0; txStage = TX_STAGE_TAIL; @@ -417,9 +424,11 @@ transmitNormalData: txFlagsElapsed = 0; txByteIdx = 0; txStage = TX_STAGE_DATA; //return to normal data transmission stage. There might be a next frame to transmit + __disable_irq(); txFrameBufferFull = false; txFrameTail++; txFrameTail %= FRAME_MAX_COUNT; + __enable_irq(); goto transmitNormalData; } } From 25a71259324816e51e5449f88d5d84fe9ad18ca2 Mon Sep 17 00:00:00 2001 From: Piotr Wilkon Date: Mon, 4 Sep 2023 10:47:24 +0200 Subject: [PATCH 4/5] changelog and version number --- CHANGELOG.md | 9 +++++++++ Src/common.c | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76fe1c9..b01bc09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# 1.3.3 (2023-09-04) +## New features +* none +## Bug fixes +* RX buffer pointers bug fix +## Other +* New KISS handling method to support long and multiple frames +## Known bugs +* none # 1.3.2 (2023-08-31) ## New features * none diff --git a/Src/common.c b/Src/common.c index 5fea23c..f350127 100644 --- a/Src/common.c +++ b/Src/common.c @@ -32,7 +32,7 @@ struct _GeneralConfig GeneralConfig = .kissMonitor = 0, }; -const char versionString[] = "VP-Digi v. 1.3.2\r\nThe open-source standalone APRS digipeater controller and KISS TNC\r\n"; +const char versionString[] = "VP-Digi v. 1.3.3\r\nThe open-source standalone APRS digipeater controller and KISS TNC\r\n"; static uint64_t pow10i(uint16_t exp) { From 08baecee8a05edf44bdbb26294a180c6487473b3 Mon Sep 17 00:00:00 2001 From: Piotr Wilkon Date: Mon, 4 Sep 2023 11:32:41 +0200 Subject: [PATCH 5/5] tnc2 converter bug fix --- CHANGELOG.md | 1 + Src/common.c | 11 ++++++++--- Src/kiss.c | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b01bc09..7ef9c5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ * none ## Bug fixes * RX buffer pointers bug fix +* AX.25 to TNC2 converter bug with non-UI frames ## Other * New KISS handling method to support long and multiple frames ## Known bugs diff --git a/Src/common.c b/Src/common.c index f350127..0849224 100644 --- a/Src/common.c +++ b/Src/common.c @@ -146,11 +146,16 @@ static void sendTNC2ToUart(Uart *uart, uint8_t *from, uint16_t len) } - UartSendByte(uart, ':'); //separator + UartSendByte(uart, ':'); //separator - nextPathEl += 2; //skip Control and PID + if((from[nextPathEl] & 0b11101111) == 0b00000011) //check if UI packet + { + nextPathEl += 2; //skip Control and PID - UartSendString(uart, &(from[nextPathEl]), len - nextPathEl); //send information field + UartSendString(uart, &(from[nextPathEl]), len - nextPathEl); //send information field + } + else + UartSendString(uart, "", 0); UartSendByte(uart, 0); //terminate with NULL } diff --git a/Src/kiss.c b/Src/kiss.c index 95d5967..18955c6 100644 --- a/Src/kiss.c +++ b/Src/kiss.c @@ -51,7 +51,7 @@ void KissParse(Uart *port, uint8_t data) { if(data == 0xC0) //frame end marker { - if(port->kissBufferHead < 17) //command+source+destination+PID+Control=17 + if(port->kissBufferHead < 16) //command+source+destination+Control=16 { port->kissBufferHead = 0; return;