Skip to content

Commit

Permalink
Merge pull request #29 from sq8vps/dev
Browse files Browse the repository at this point in the history
v.1.3.3
  • Loading branch information
sq8vps authored Sep 4, 2023
2 parents e550e10 + 08baece commit e9a5ebd
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 134 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# 1.3.3 (2023-09-04)
## New features
* 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
* none
# 1.3.2 (2023-08-31)
## New features
* none
Expand Down
9 changes: 2 additions & 7 deletions Inc/ax25.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ along with VP-Digi. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
#include <stdbool.h>


#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
Expand All @@ -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
Expand Down
20 changes: 3 additions & 17 deletions Inc/drivers/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ along with VP-Digi. If not, see <http://www.gnu.org/licenses/>.
#include "usbd_cdc_if.h"
#include "ax25.h"

#define UART_BUFFER_SIZE 250
#define UART_BUFFER_SIZE 130

enum UartMode
{
Expand All @@ -37,7 +37,6 @@ enum UartMode
enum UartDataType
{
DATA_NOTHING = 0,
DATA_KISS,
DATA_TERM,
DATA_USB,
};
Expand All @@ -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
Expand Down Expand Up @@ -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
41 changes: 41 additions & 0 deletions Inc/kiss.h
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/

#ifndef KISS_H_
#define KISS_H_

#include <stdint.h>
#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_ */
58 changes: 20 additions & 38 deletions Src/ax25.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@ along with VP-Digi. If not, see <http://www.gnu.org/licenses/>.

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
Expand Down Expand Up @@ -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
Expand All @@ -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))
Expand Down Expand Up @@ -146,43 +144,14 @@ 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) //frame start marker
{
uint16_t end = i + 1;
while(end < len)
{
if(buf[end] == 0xC0)
break;
end++;
}
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));
i = end; //move pointer to the next byte if there are more consecutive frames
}
}
}

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++)
Expand All @@ -191,18 +160,22 @@ 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;
}


bool Ax25ReadNextRxFrame(uint8_t **dst, uint16_t *size, uint16_t *signalLevel)
{
if((rxFrameHead == rxFrameTail) && !rxFrameBufferFull)
{
return false;
}

*dst = outputFrameBuffer;

Expand All @@ -214,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;
}

Expand Down Expand Up @@ -280,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++)
{
Expand All @@ -309,7 +286,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);
Expand All @@ -334,7 +311,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);
Expand Down Expand Up @@ -396,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];
Expand All @@ -411,6 +390,7 @@ uint8_t Ax25GetTxBit(void)
}
else //no more frames
{
__enable_irq();
txByteIdx = 0;
txBitIdx = 0;
txStage = TX_STAGE_TAIL;
Expand Down Expand Up @@ -444,9 +424,11 @@ uint8_t Ax25GetTxBit(void)
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;
}
}
Expand Down
13 changes: 9 additions & 4 deletions Src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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, "<not UI packet>", 0);

UartSendByte(uart, 0); //terminate with NULL
}
Expand Down
3 changes: 1 addition & 2 deletions Src/digipeater.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit e9a5ebd

Please sign in to comment.