diff --git a/Inc/ax25.h b/Inc/ax25.h
index bb2a910..fb26893 100644
--- a/Inc/ax25.h
+++ b/Inc/ax25.h
@@ -41,6 +41,13 @@ 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
* @param *data Data to transmit
@@ -63,7 +70,7 @@ void Ax25ClearReceivedFrameBitmap(void);
/**
* @brief Get next received frame (if available)
- * @param **dst Destination buffer that this function allocates and fills
+ * @param **dst Pointer to internal buffer
* @param *size Actual frame size
* @param *signalLevel Frame signal level (RMS)
* @return True if frame was read, false if no more frames to read
diff --git a/Inc/drivers/systick.h b/Inc/drivers/systick.h
index 93a5378..5367e6e 100644
--- a/Inc/drivers/systick.h
+++ b/Inc/drivers/systick.h
@@ -26,8 +26,10 @@ along with VP-Digi. If not, see .
extern volatile uint32_t ticks;
-//void SysTick_Handler(void);
-
void SysTickInit(void);
+uint32_t SysTickGet(void);
+
+void Delay(uint32_t ms);
+
#endif /* SYSTICK_H_ */
diff --git a/Inc/drivers/uart.h b/Inc/drivers/uart.h
index 3d967cb..e8153eb 100644
--- a/Inc/drivers/uart.h
+++ b/Inc/drivers/uart.h
@@ -37,6 +37,7 @@ enum UartDataType
DATA_NOTHING = 0,
DATA_KISS,
DATA_TERM,
+ DATA_USB,
};
typedef struct
@@ -53,6 +54,7 @@ typedef struct
uint8_t txBufferFull : 1;
enum UartMode mode;
uint32_t kissTimer;
+ uint16_t lastRxBufferHead; //for special characters handling
} Uart;
extern Uart Uart1, Uart2, UartUsb;
diff --git a/Inc/terminal.h b/Inc/terminal.h
index 45623ce..001e36a 100644
--- a/Inc/terminal.h
+++ b/Inc/terminal.h
@@ -29,30 +29,24 @@ along with VP-Digi. If not, see .
*/
void TermSendToAll(enum UartMode mode, uint8_t *data, uint16_t size);
+/**
+ * @brief Send signed number to all available ports
+ * @param mode Output mode/data type
+ * @param n Number to send
+ */
void TermSendNumberToAll(enum UartMode mode, int32_t n);
-//typedef enum
-//{
-// TERM_ANY,
-// TERM_USB,
-// TERM_UART1,
-// TERM_UART2
-//} Terminal_stream;
-//
-//#define TERMBUFLEN 300
-//
-///**
-// * @brief Handle "special" terminal cases like backspace or local echo
-// * @param[in] src Source: TERM_USB, TERM_UART1, TERM_UART2
-// * @attention Must be called for every received data
-// */
-//void term_handleSpecial(Terminal_stream src);
-//
-//
/**
- * \brief Parse and process received data
- * \param *src UART structure
+ * @brief Handle "special" terminal cases like backspace or local echo
+ * @param *u UART structure
+ * @attention Must be called for every received data
+ */
+void TermHandleSpecial(Uart *u);
+
+/**
+ * @brief Parse and process received data
+ * @param *src UART structure
*/
void TermParse(Uart *src);
diff --git a/STM32F103C8Tx_FLASH.ld b/STM32F103C8Tx_FLASH.ld
index 529d412..e9b1ef0 100644
--- a/STM32F103C8Tx_FLASH.ld
+++ b/STM32F103C8Tx_FLASH.ld
@@ -55,8 +55,8 @@ ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20005000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
-_Min_Heap_Size = 0x200; /* required amount of heap */
-_Min_Stack_Size = 0x400; /* required amount of stack */
+_Min_Heap_Size = 0x080; /* required amount of heap */
+_Min_Stack_Size = 0x200; /* required amount of stack */
/* Specify the memory areas */
MEMORY
diff --git a/Src/ax25.c b/Src/ax25.c
index 941c907..4dd5e10 100644
--- a/Src/ax25.c
+++ b/Src/ax25.c
@@ -21,11 +21,13 @@ along with VP-Digi. If not, see .
#include "common.h"
#include "drivers/systick.h"
#include
+#include "digipeater.h"
struct Ax25ProtoConfig Ax25Config;
//values below must be kept consistent so that FRAME_BUFFER_SIZE >= FRAME_MAX_SIZE * FRAME_MAX_COUNT
-#define FRAME_MAX_SIZE (150) //single frame max length for RX
+#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
@@ -111,6 +113,8 @@ 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];
+
#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))
@@ -140,6 +144,32 @@ 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)
@@ -172,12 +202,7 @@ bool Ax25ReadNextRxFrame(uint8_t **dst, uint16_t *size, uint16_t *signalLevel)
if((rxFrameHead == rxFrameTail) && !rxFrameBufferFull)
return false;
- *dst = malloc(rxFrame[rxFrameTail].size);
- if(NULL == dst)
- {
- *size = 0;
- return false;
- }
+ *dst = outputFrameBuffer;
for(uint16_t i = 0; i < rxFrame[rxFrameTail].size; i++)
{
@@ -494,7 +519,7 @@ void Ax25TransmitBuffer(void)
if((txFrameHead != txFrameTail) || txFrameBufferFull)
{
- txQuiet = (ticks + (Ax25Config.quietTime / SYSTICK_INTERVAL) + Random(0, 200 / SYSTICK_INTERVAL)); //calculate required delay
+ txQuiet = (SysTickGet() + (Ax25Config.quietTime / SYSTICK_INTERVAL) + Random(0, 200 / SYSTICK_INTERVAL)); //calculate required delay
txInitStage = TX_INIT_WAITING;
}
}
@@ -530,7 +555,7 @@ void Ax25TransmitCheck(void)
if(ModemIsTxTestOngoing()) //TX test is enabled, wait for now
return;
- if(txQuiet < ticks) //quit time has elapsed
+ if(txQuiet < SysTickGet()) //quit time has elapsed
{
if(!ModemDcdState()) //channel is free
{
@@ -548,7 +573,7 @@ void Ax25TransmitCheck(void)
}
else //still trying
{
- txQuiet = ticks + Random(100 / SYSTICK_INTERVAL, 500 / SYSTICK_INTERVAL); //try again after some random time
+ txQuiet = SysTickGet() + Random(100 / SYSTICK_INTERVAL, 500 / SYSTICK_INTERVAL); //try again after some random time
txRetries++;
}
}
diff --git a/Src/beacon.c b/Src/beacon.c
index 02ccf80..9462b0c 100644
--- a/Src/beacon.c
+++ b/Src/beacon.c
@@ -102,11 +102,11 @@ void BeaconCheck(void)
if(beacon[i].enable == 0)
continue;
- if((beacon[i].interval > 0) && ((ticks >= beacon[i].next) || (beacon[i].next == 0)))
+ if((beacon[i].interval > 0) && ((SysTickGet() >= beacon[i].next) || (beacon[i].next == 0)))
{
- if(beaconDelay[i] > ticks) //check for beacon delay (only for the very first transmission)
+ if(beaconDelay[i] > SysTickGet()) //check for beacon delay (only for the very first transmission)
return;
- beacon[i].next = ticks + beacon[i].interval; //save next beacon timestamp
+ beacon[i].next = SysTickGet() + beacon[i].interval; //save next beacon timestamp
beaconDelay[i] = 0;
BeaconSend(i);
}
@@ -121,7 +121,7 @@ void BeaconInit(void)
{
for(uint8_t i = 0; i < 8; i++)
{
- beaconDelay[i] = (beacon[i].delay * SYSTICK_FREQUENCY) + ticks + (30000 / SYSTICK_INTERVAL); //set delay for beacons and add constant 30 seconds of delay
+ beaconDelay[i] = (beacon[i].delay * SYSTICK_FREQUENCY) + SysTickGet() + (30000 / SYSTICK_INTERVAL); //set delay for beacons and add constant 30 seconds of delay
beacon[i].next = 0;
}
}
diff --git a/Src/config.c b/Src/config.c
index c190440..1839b18 100644
--- a/Src/config.c
+++ b/Src/config.c
@@ -1,5 +1,5 @@
/*
-This file is part of VP-DigiConfig.
+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
diff --git a/Src/digipeater.c b/Src/digipeater.c
index 15f9ee5..78c925c 100644
--- a/Src/digipeater.c
+++ b/Src/digipeater.c
@@ -26,14 +26,14 @@ along with VP-DigiConfig. If not, see .
struct _DigiConfig DigiConfig;
-#define VISCOUS_MAX_FRAME_COUNT 20 //max frames in viscous-delay buffer
+#define VISCOUS_MAX_FRAME_COUNT 10 //max frames in viscous-delay buffer
#define VISCOUS_MAX_FRAME_SIZE 150
struct ViscousData
{
uint32_t hash;
uint32_t timeLimit;
- uint8_t *frame;
+ uint8_t frame[VISCOUS_MAX_FRAME_SIZE];
uint16_t size;
};
static struct ViscousData viscous[VISCOUS_MAX_FRAME_COUNT];
@@ -45,12 +45,12 @@ struct DeDupeData
uint32_t timeLimit;
};
-#define DEDUPE_SIZE (40) //duplicate protection buffer size (number of hashes)
+#define DEDUPE_SIZE (50) //duplicate protection buffer size (number of hashes)
static struct DeDupeData deDupe[DEDUPE_SIZE]; //duplicate protection hash buffer
static uint8_t deDupeCount = 0; //duplicate protection buffer index
-#define DIGI_BUFFER_SIZE 200
+#define DIGI_BUFFER_SIZE 308 //308 is the theoretical max under some assumptions, see ax25.c
static uint8_t buf[DIGI_BUFFER_SIZE];
/**
@@ -66,9 +66,8 @@ static uint8_t viscousCheckAndRemove(uint32_t hash)
{
viscous[i].hash = 0; //clear slot
viscous[i].timeLimit = 0;
- free(viscous[i].frame);
viscous[i].size = 0;
- //term_sendMonitor((uint8_t*)"Digipeated frame received, dropping old frame from viscous-delay buffer\r\n", 0);
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"Digipeated frame received, dropping old frame from viscous-delay buffer\r\n", 0);
return 1;
}
}
@@ -86,7 +85,7 @@ void DigiViscousRefresh(void)
for(uint8_t i = 0; i < VISCOUS_MAX_FRAME_COUNT; i++)
{
- if((viscous[i].timeLimit > 0) && (ticks >= viscous[i].timeLimit)) //it's time to transmit this frame
+ if((viscous[i].timeLimit > 0) && (SysTickGet() >= viscous[i].timeLimit)) //it's time to transmit this frame
{
void *handle = NULL;
if(NULL != (handle = Ax25WriteTxFrame(viscous[i].frame, viscous[i].size)))
@@ -103,7 +102,6 @@ void DigiViscousRefresh(void)
viscous[i].hash = 0; //clear slot
viscous[i].timeLimit = 0;
- free(viscous[i].frame);
viscous[i].size = 0;
}
}
@@ -194,9 +192,6 @@ static void makeFrame(uint8_t *frame, uint16_t elStart, uint16_t len, uint32_t h
if((len + 7) > VISCOUS_MAX_FRAME_SIZE) //if frame length (+ 7 bytes for inserted call) is bigger than buffer size
return; //drop
- viscous[viscousSlot].frame = malloc(len + 7);
- if(NULL == viscous[viscousSlot].frame)
- return;
buffer = viscous[viscousSlot].frame;
index = &(viscous[viscousSlot].size);
*index = 0;
@@ -288,7 +283,7 @@ static void makeFrame(uint8_t *frame, uint16_t elStart, uint16_t len, uint32_t h
if((alias < 8) && (DigiConfig.viscous & (1 << alias)))
{
viscous[viscousSlot].hash = hash;
- viscous[viscousSlot].timeLimit = ticks + (VISCOUS_HOLD_TIME / SYSTICK_INTERVAL);
+ viscous[viscousSlot].timeLimit = SysTickGet() + (VISCOUS_HOLD_TIME / SYSTICK_INTERVAL);
TermSendToAll(MODE_MONITOR, (uint8_t*)"Saving frame for viscous-delay digipeating\r\n", 0);
}
else
@@ -339,7 +334,7 @@ void DigiDigipeat(uint8_t *frame, uint16_t len)
{
if(deDupe[i].hash == hash)
{
- if(ticks < (deDupe[i].timeLimit))
+ if(SysTickGet() < (deDupe[i].timeLimit))
return; //filter out duplicate frame
}
}
@@ -466,7 +461,7 @@ void DigiStoreDeDupe(uint8_t *buf, uint16_t size)
deDupeCount %= DEDUPE_SIZE;
deDupe[deDupeCount].hash = hash;
- deDupe[deDupeCount].timeLimit = ticks + (DigiConfig.dupeTime * 10 / SYSTICK_INTERVAL);
+ deDupe[deDupeCount].timeLimit = SysTickGet() + (DigiConfig.dupeTime * 10 / SYSTICK_INTERVAL);
deDupeCount++;
}
diff --git a/Src/drivers/systick.c b/Src/drivers/systick.c
index 82d5208..64f1b55 100644
--- a/Src/drivers/systick.c
+++ b/Src/drivers/systick.c
@@ -30,3 +30,15 @@ void SysTickInit(void)
{
SysTick_Config(SystemCoreClock / SYSTICK_FREQUENCY); //SysTick every 10 ms
}
+
+uint32_t SysTickGet(void)
+{
+ return ticks;
+}
+
+void Delay(uint32_t ms)
+{
+ uint32_t target = SysTickGet() + ms / SYSTICK_INTERVAL;
+ while(target > SysTickGet())
+ ;
+}
diff --git a/Src/drivers/uart.c b/Src/drivers/uart.c
index 3b458eb..968f29e 100644
--- a/Src/drivers/uart.c
+++ b/Src/drivers/uart.c
@@ -21,49 +21,10 @@ along with VP-Digi. If not, see .
#include "ax25.h"
#include "common.h"
#include
-
#include "digipeater.h"
Uart Uart1, Uart2, UartUsb;
-//uint8_t Uart_txKiss(uint8_t *buf, uint16_t len)
-//{
-// if(len < 10) //frame is too small
-// {
-// return 1;
-// }
-//
-// uint16_t framebegin = 0;
-// uint8_t framestatus = 0; //0 - frame not started, 1 - frame start found, 2 - in a frame, 3 - frame end found
-//
-// for(uint16_t i = 0; i < len; i++)
-// {
-// if(*(buf + i) == 0xc0) //found KISS frame delimiter
-// {
-// if((i > 2) && (framestatus == 2)) //we are already in frame, this is the ending marker
-// {
-// framestatus = 3;
-// ax25.frameXmit[ax25.xmitIdx++] = 0xFF; //write frame separator
-// Digi_storeDeDupeFromXmitBuf(framebegin); //store duplicate protection hash
-// if((FRAMEBUFLEN - ax25.xmitIdx) < (len - i + 2)) //there might be next frame in input buffer, but if there is no space for it, drop it
-// break;
-// }
-// }
-// else if((*(buf + i) == 0x00) && (*(buf + i - 1) == 0xC0) && ((framestatus == 0) || (framestatus == 3))) //found frame delimiter, modem number (0x00) and we are not in a frame yet or preceding frame has been processed
-// {
-// framestatus = 1; //copy next frame
-// framebegin = ax25.xmitIdx;
-// }
-// else if((framestatus == 1) || (framestatus == 2)) //we are in a frame
-// {
-// ax25.frameXmit[ax25.xmitIdx++] = *(buf + i); //copy data
-// framestatus = 2;
-// }
-// }
-//
-// return 0;
-//}
-
static void handleInterrupt(Uart *port)
{
if(port->port->SR & USART_SR_RXNE) //byte received
@@ -72,13 +33,10 @@ static void handleInterrupt(Uart *port)
port->rxBuffer[port->rxBufferHead++] = port->port->DR; //store it
port->rxBufferHead %= UART_BUFFER_SIZE;
-// if(port->port == USART1) //handle special functions and characters
-// term_handleSpecial(TERM_UART1);
-// else if(port->port == USART2)
-// term_handleSpecial(TERM_UART2);
+ TermHandleSpecial(port);
if(port->mode == MODE_KISS)
- port->kissTimer = ticks + (5000 / SYSTICK_INTERVAL); //set timeout to 5s in KISS mode
+ 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
{
@@ -111,7 +69,7 @@ static void handleInterrupt(Uart *port)
}
}
- if((port->kissTimer > 0) && (ticks >= port->kissTimer)) //KISS timer timeout
+ if((port->kissTimer > 0) && (SysTickGet() >= port->kissTimer)) //KISS timer timeout
{
port->kissTimer = 0;
port->rxBufferHead = 0;
@@ -203,6 +161,7 @@ void UartInit(Uart *port, USART_TypeDef *uart, uint32_t baud)
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));
}
@@ -278,7 +237,7 @@ void UartClearRx(Uart *port)
void UartHandleKissTimeout(Uart *port)
{
- if((port->kissTimer > 0) && (ticks >= port->kissTimer)) //KISS timer timeout
+ if((port->kissTimer > 0) && (SysTickGet() >= port->kissTimer)) //KISS timer timeout
{
port->kissTimer = 0;
port->rxBufferHead = 0;
diff --git a/Src/main.c b/Src/main.c
index 305d7ef..53c891c 100644
--- a/Src/main.c
+++ b/Src/main.c
@@ -94,7 +94,7 @@ static void handleFrame(void)
uint8_t modemBitmap = Ax25GetReceivedFrameBitmap(); //store states
Ax25ClearReceivedFrameBitmap();
- uint8_t *buf = NULL;
+ uint8_t *buf;
uint16_t size = 0;
uint16_t signalLevel = 0;
@@ -113,7 +113,7 @@ static void handleFrame(void)
//for pure square wave it should be equal to the amplitude (around 4095)
//real data contains lots of imperfections (especially mark/space amplitude imbalance) and this value is far smaller than 2900 for standard frames
//division by 9 was selected by trial and error to provide a value of 100(%) when the input signal had peak-peak voltage of 3.3V
- //this probably should be done in a different way, like some peak amplitude tracing
+ //TODO: this probably should be done in a different way, like some peak amplitude tracing
signalLevel /= 9;
if(signalLevel > 100)
@@ -141,9 +141,11 @@ static void handleFrame(void)
TermSendToAll(MODE_MONITOR, (uint8_t*)"D", 1);
break;
case EMPHASIS_NONE:
- default:
TermSendToAll(MODE_MONITOR, (uint8_t*)"F", 1);
break;
+ default:
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"*", 1);
+ break;
}
}
else
@@ -161,8 +163,6 @@ static void handleFrame(void)
DigiDigipeat(buf, size);
-
- free(buf);
}
}
@@ -200,9 +200,7 @@ int main(void)
GPIOA->CRH |= GPIO_CRH_MODE12_1;
GPIOA->CRH &= ~GPIO_CRH_CNF12;
GPIOA->BSRR = GPIO_BSRR_BR12;
- uint32_t t = ticks + (100 / SYSTICK_INTERVAL);
- while(t > ticks)
- ;
+ Delay(100);
GPIOA->CRH &= ~GPIO_CRH_MODE12;
GPIOA->CRH |= GPIO_CRH_CNF12_0;
@@ -269,39 +267,16 @@ int main(void)
Ax25TransmitCheck(); //check for pending transmission request
-// if(USBint) //USB "interrupt"
-// {
-// USBint = 0; //clear
-//
-// if(USBmode == MODE_KISS) //is USB in KISS mode?
-// usbKissTimer = ticks + 500; //set timeout to 5s
-//
-// term_handleSpecial(TERM_USB); //handle special characters (e.g. backspace)
-// if((usbcdcdata[0] == 0xc0) && /*(usbcdcdata[1] == 0x00) &&*/ (usbcdcdata[usbcdcidx - 1] == 0xc0)) //probably a KISS frame
-// {
-// USBrcvd = DATA_KISS;
-// usbKissTimer = 0;
-// }
-//
-// if(((usbcdcdata[usbcdcidx - 1] == '\r') || (usbcdcdata[usbcdcidx - 1] == '\n'))) //proabably a command
-// {
-// USBrcvd = DATA_TERM;
-// usbKissTimer = 0;
-// }
-// }
-//
-// if((usbKissTimer > 0) && (ticks >= usbKissTimer)) //USB KISS timer timeout
-// {
-// usbcdcidx = 0;
-// memset(usbcdcdata, 0, UARTBUFLEN);
-// usbKissTimer = 0;
-// }
-
if(UartUsb.rxType != DATA_NOTHING)
{
- TermParse(&UartUsb);
- UartClearRx(&UartUsb);
+ TermHandleSpecial(&UartUsb);
+ if(UartUsb.rxType != DATA_USB)
+ {
+ TermParse(&UartUsb);
+ UartClearRx(&UartUsb);
+ }
+ UartUsb.rxType = DATA_NOTHING;
}
if(Uart1.rxType != DATA_NOTHING)
{
@@ -318,7 +293,7 @@ int main(void)
BeaconCheck(); //check beacons
- if(ticks > 0xFFFFF000)
+ if(SysTickGet() > 0xFFFFF000)
NVIC_SystemReset();
}
/* USER CODE END 3 */
diff --git a/Src/terminal.c b/Src/terminal.c
index 2b931db..5a99b73 100644
--- a/Src/terminal.c
+++ b/Src/terminal.c
@@ -22,91 +22,40 @@ along with VP-DigiConfig. If not, see .
#include "config.h"
#include "drivers/modem.h"
#include "ax25.h"
+#include "drivers/systick.h"
+void TermHandleSpecial(Uart *u)
+{
+ if(u->mode == MODE_KISS) //don't do anything in KISS mode
+ {
+ u->lastRxBufferHead = 0;
+ return;
+ }
+ if(u->lastRxBufferHead >= u->rxBufferHead) //UART RX buffer index was probably cleared
+ u->lastRxBufferHead = 0;
-//uint16_t spLastIdx[3] = {0, 0, 0}; //index buffer was "special" terminal cases
+ if(u->rxBuffer[u->rxBufferHead - 1] == '\b') //user entered backspace
+ {
+ if(u->rxBufferHead > 1) //there was some data in buffer
+ {
+ u->rxBufferHead -= 2; //remove backspace and preceding character
+ UartSendString(u, "\b \b", 3); //backspace (one character left), remove backspaced character (send space) and backspace again
+ if(u->lastRxBufferHead > 0)
+ u->lastRxBufferHead--; //1 character was removed
+ }
+ else //no preceding character
+ u->rxBufferHead = 0;
+ }
+ uint16_t t = u->rxBufferHead; //store last index
+ if(u->lastRxBufferHead < t) //local echo handling
+ {
+ UartSendString(u, &u->rxBuffer[u->lastRxBufferHead], t - u->lastRxBufferHead); //echo characters entered by user
+ if((u->rxBuffer[t - 1] == '\r') || (u->rxBuffer[t - 1] == '\n'))
+ UartSendString(u, "\r\n", 2);
+ u->lastRxBufferHead = t;
+ }
-/**
- * @brief Handle "special" terminal cases like backspace or local echo
- * @param[in] src Source: TERM_USB, TERM_UART1, TERM_UART2
- * @attention Must be called for every received data
- */
-//void term_handleSpecial(Terminal_stream src)
-//{
-// if(src == TERM_USB)
-// {
-// if(USBmode == MODE_KISS) //don't do anything in KISS mode
-// {
-// spLastIdx[0] = 0;
-// return;
-// }
-// if(spLastIdx[0] >= usbcdcidx) //USB RX buffer index was probably cleared
-// spLastIdx[0] = 0;
-//
-// if(usbcdcdata[usbcdcidx - 1] == '\b') //user entered backspace
-// {
-// if(usbcdcidx > 1) //there was some data in buffer
-// {
-// usbcdcidx -= 2; //remove backspace and preceding character
-// CDC_Transmit_FS((uint8_t*)"\b \b", 3); //backspace (one character left), remove backspaced character (send space) and backspace again
-// if(spLastIdx[0] > 0)
-// spLastIdx[0]--; //1 character was removed
-// }
-// else //there was only a backspace
-// usbcdcidx = 0;
-// }
-// uint16_t t = usbcdcidx; //store last index
-// if(spLastIdx[0] < t) //local echo handling
-// {
-// CDC_Transmit_FS(&usbcdcdata[spLastIdx[0]], t - spLastIdx[0]); //echo characters entered by user
-// if((usbcdcdata[t - 1] == '\r') || (usbcdcdata[t - 1] == '\n'))
-// CDC_Transmit_FS((uint8_t*)"\r\n", 2);
-// spLastIdx[0] = t;
-// }
-// }
-// else if((src == TERM_UART1) || (src == TERM_UART2))
-// {
-// Uart *u = &uart1;
-// uint8_t nr = 1;
-// if(src == TERM_UART2)
-// {
-// u = &uart2;
-// nr = 2;
-// }
-//
-//
-// if(u->mode == MODE_KISS) //don't do anything in KISS mode
-// {
-// spLastIdx[nr] = 0;
-// return;
-// }
-// if(spLastIdx[nr] >= u->bufrxidx) //UART RX buffer index was probably cleared
-// spLastIdx[nr] = 0;
-//
-// if(u->bufrx[u->bufrxidx - 1] == '\b') //user entered backspace
-// {
-// if(u->bufrxidx > 1) //there was some data in buffer
-// {
-// u->bufrxidx -= 2; //remove backspace and preceding character
-// uart_sendString(u, (uint8_t*)"\b \b", 3); //backspace (one character left), remove backspaced character (send space) and backspace again
-// if(spLastIdx[nr] > 0)
-// spLastIdx[nr]--; //1 character was removed
-// }
-// else //there was only a backspace
-// u->bufrxidx = 0;
-// }
-// uint16_t t = u->bufrxidx; //store last index
-// if(spLastIdx[nr] < t) //local echo handling
-// {
-// uart_sendString(u, &u->bufrx[spLastIdx[nr]], t - spLastIdx[nr]); //echo characters entered by user
-// if((u->bufrx[t - 1] == '\r') || (u->bufrx[t - 1] == '\n'))
-// uart_sendString(u, (uint8_t*)"\r\n", 2);
-// spLastIdx[nr] = t;
-// }
-// uart_transmitStart(u);
-// }
-//
-//}
+}
static void sendKiss(Uart *port, uint8_t *buf, uint16_t len)
@@ -165,6 +114,7 @@ static const char monitorHelp[] = "\r\nCommans available in monitor mode:\r\n"
"kiss - switches to KISS mode\r\n"
"config - switches to config mode\r\n"
"reboot - reboots the device\r\n"
+ "time - show time since boot\r\n"
"version - shows full firmware version info\r\n\r\n\r\n";
static const char configHelp[] = "\r\nCommands available in config mode:\r\n"
@@ -174,6 +124,7 @@ static const char configHelp[] = "\r\nCommands available in config mode:\r\n"
"eraseall - erases all configurations and reboots the device\r\n"
"help - shows this help page\r\n"
"reboot - reboots the device\r\n"
+ "time - show time since boot\r\n"
"version - shows full firmware version info\r\n\r\n"
"call - sets callsign with optional SSID\r\n"
"dest - sets destination address\r\n"
@@ -381,6 +332,12 @@ static void printConfig(Uart *src)
UartSendString(src, "Off\r\n", 0);
}
+static void sendTime(Uart *src)
+{
+ UartSendString(src, "Time since boot: ", 0);
+ UartSendNumber(src, SysTickGet() * SYSTICK_INTERVAL / 60000); //convert from ms to minutes
+ UartSendString(src, " minutes\r\n", 0);
+}
void TermParse(Uart *src)
{
@@ -414,7 +371,7 @@ void TermParse(Uart *src)
}
else if(!strncmp(cmd, "monitor", 7))
{
- UartSendString(src, (uint8_t*)"USB switched to monitor mode\r\n", 0);
+ UartSendString(src, (uint8_t*)"Switched to monitor mode\r\n", 0);
src->mode = MODE_MONITOR;
return;
}
@@ -423,7 +380,7 @@ void TermParse(Uart *src)
*/
else if((src->mode == MODE_KISS) && (src->rxType == DATA_KISS))
{
- //Uart_txKiss(cmd, len); //if received KISS data, transmit KISS frame
+ Ax25TxKiss(src->rxBuffer, src->rxBufferHead);
return;
}
/*
@@ -434,15 +391,22 @@ void TermParse(Uart *src)
if(!strncmp(cmd, "help", 4))
{
UartSendString(src, (char *)monitorHelp, 0);
+ return;
}
else if(!strncmp(cmd, "version", 7))
{
UartSendString(src, (char *)versionString, 0);
+ return;
}
else if(!strncmp(cmd, "reboot", 6))
{
NVIC_SystemReset();
}
+ else if(!strncmp(cmd, "time", 4))
+ {
+ sendTime(src);
+ return;
+ }
else if(!strncmp(cmd, "beacon ", 7))
{
if((cmd[7] >= '0') && (cmd[7] <= '7'))
@@ -509,10 +473,17 @@ void TermParse(Uart *src)
if(!strncmp(cmd, "help", 4))
{
UartSendString(src, (uint8_t*)configHelp, 0);
+ return;
}
else if(!strncmp(cmd, "version", 7))
{
UartSendString(src, (uint8_t*)versionString, 0);
+ return;
+ }
+ else if(!strncmp(cmd, "time", 4))
+ {
+ sendTime(src);
+ return;
}
else if(!strncmp(cmd, "reboot", 6))
{
@@ -531,6 +502,7 @@ void TermParse(Uart *src)
else if(!strncmp(cmd, "print", 5))
{
printConfig(src);
+ return;
}
else if(!strncmp(cmd, "list", 4)) //list calls in call filter table
{
@@ -542,56 +514,60 @@ void TermParse(Uart *src)
if(DigiConfig.callFilter[i][0] != 0)
{
uint8_t cl[10] = {0};
- uint8_t clidx = 0;
- for(uint8_t h = 0; h < 6; h++)
+ uint8_t clIdx = 0;
+ for(uint8_t j = 0; j < 6; j++)
{
- if(DigiConfig.callFilter[i][h] == 0xFF) //wildcard
+ if(DigiConfig.callFilter[i][j] == 0xFF) //wildcard
{
- uint8_t g = h;
- uint8_t j = 0;
- while(g < 6)
+ bool partialWildcard = false;
+ for(uint8_t k = j; k < 6; k++) //check if there are all characters wildcarded
{
- if(DigiConfig.callFilter[i][g] != 0xFF)
- j = 1;
- g++;
+ if(DigiConfig.callFilter[i][k] != 0xFF)
+ {
+ partialWildcard = true;
+ break;
+ }
}
- if(j == 0)
+ if(partialWildcard == false) //all characters wildcarded
{
- cl[clidx++] = '*';
+ cl[clIdx++] = '*';
break;
- } else
+ }
+ else
{
- cl[clidx++] = '?';
+ cl[clIdx++] = '?';
}
}
else
{
- if(DigiConfig.callFilter[i][h] != ' ')
- cl[clidx++] = DigiConfig.callFilter[i][h];
+ if(DigiConfig.callFilter[i][j] != ' ')
+ cl[clIdx++] = DigiConfig.callFilter[i][j];
}
}
- if(DigiConfig.callFilter[i][6] == 0xFF)
+ if(DigiConfig.callFilter[i][6] == 0xFF) //wildcard on SSID
{
- cl[clidx++] = '-';
- cl[clidx++] = '*';
+ cl[clIdx++] = '-';
+ cl[clIdx++] = '*';
}
else if(DigiConfig.callFilter[i][6] != 0)
{
- cl[clidx++] = '-';
+ cl[clIdx++] = '-';
if(DigiConfig.callFilter[i][6] > 9)
{
- cl[clidx++] = (DigiConfig.callFilter[i][6] / 10) + 48;
- cl[clidx++] = (DigiConfig.callFilter[i][6] % 10) + 48;
+ cl[clIdx++] = (DigiConfig.callFilter[i][6] / 10) + '0';
+ cl[clIdx++] = (DigiConfig.callFilter[i][6] % 10) + '0';
}
- else cl[clidx++] = DigiConfig.callFilter[i][6] + 48;
+ else
+ cl[clIdx++] = DigiConfig.callFilter[i][6] + '0';
}
UartSendString(src, cl, 0);
}
else
UartSendString(src, "empty", 0);
+
UartSendString(src, "\r\n", 0);
- return;
}
+ return;
}
/*
* Settings insertion handling
@@ -604,11 +580,6 @@ void TermParse(Uart *src)
UartSendString(src, "Incorrect callsign!\r\n", 0);
return;
}
- else
- {
- UartSendString(src, "OK\r\n", 0);
- }
- return;
}
else if(!strncmp(cmd, "dest", 4))
{
@@ -617,10 +588,6 @@ void TermParse(Uart *src)
UartSendString(src, "Incorrect address!\r\n", 0);
return;
}
- else
- {
- UartSendString(src, "OK\r\n", 0);
- }
}
else if(!strncmp(cmd, "txdelay", 7))
{
@@ -633,7 +600,6 @@ void TermParse(Uart *src)
else
{
Ax25Config.txDelayLength = (uint16_t)t;
- UartSendString(src, "OK\r\n", 0);
}
}
else if(!strncmp(cmd, "txtail", 6))
@@ -647,10 +613,8 @@ void TermParse(Uart *src)
else
{
Ax25Config.txTailLength = (uint16_t)t;
- UartSendString(src, "OK\r\n", 0);
}
}
-
else if(!strncmp(cmd, "quiet", 5))
{
int64_t t = StrToInt(&cmd[6], len - 6);
@@ -778,8 +742,6 @@ void TermParse(Uart *src)
{
err = true;
}
-
- UartSendString(src, "OK\r\n", 0);
}
else if(!strncmp(cmd, "digi", 4))
{
@@ -824,7 +786,6 @@ void TermParse(Uart *src)
UartSendString(src, "Incorrect alias!\r\n", 0);
return;
}
- UartSendString(src, "OK\r\n", 0);
}
else if((!strncmp(&cmd[7], "max ", 4) || !strncmp(&cmd[7], "rep ", 4)) && (alno < 4))
{
@@ -949,7 +910,7 @@ void TermParse(Uart *src)
uint8_t tmp[7] = {0};
uint16_t tmpIdx = 0;
- for(uint16_t i = 0; i < len; i++)
+ for(uint16_t i = 0; i < (len - shift); i++)
{
if(cmd[shift + i] == '-') //SSID separator
{
@@ -1042,7 +1003,10 @@ void TermParse(Uart *src)
err = true;
}
else
+ {
UartSendString(src, "Unknown command. For command list type \"help\"\r\n", 0);
+ return;
+ }
if(err)
diff --git a/Src/usbd_cdc_if.c b/Src/usbd_cdc_if.c
index 3cc6912..0bb8c0e 100644
--- a/Src/usbd_cdc_if.c
+++ b/Src/usbd_cdc_if.c
@@ -25,6 +25,7 @@
/* USER CODE BEGIN INCLUDE */
#include "drivers/uart.h"
#include "drivers/systick.h"
+#include "terminal.h"
/* USER CODE END INCLUDE */
/* Private typedef -----------------------------------------------------------*/
@@ -276,6 +277,7 @@ static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
UartUsb.rxBufferHead %= UART_BUFFER_SIZE;
}
+ UartUsb.rxType = DATA_USB;
handleUsbInterrupt(&UartUsb);
return (USBD_OK);
@@ -320,13 +322,8 @@ uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
static void handleUsbInterrupt(Uart *port)
{
-// if(port->port == USART1) //handle special functions and characters
-// term_handleSpecial(TERM_UART1);
-// else if(port->port == USART2)
-// term_handleSpecial(TERM_UART2);
-
if(port->mode == MODE_KISS)
- port->kissTimer = ticks + (5000 / SYSTICK_INTERVAL); //set timeout to 5s in KISS mode
+ port->kissTimer = SysTickGet() + (5000 / SYSTICK_INTERVAL); //set timeout to 5s in KISS mode
if(port->rxBufferHead != 0)
{
diff --git a/vp-digi Debug.cfg b/vp-digi Debug.cfg
new file mode 100644
index 0000000..e285a09
--- /dev/null
+++ b/vp-digi Debug.cfg
@@ -0,0 +1,35 @@
+# This is an NUCLEO-F103RB board with a single STM32F103RBTx chip
+#
+# Generated by System Workbench for STM32
+# Take care that such file, as generated, may be overridden without any early notice. Please have a look to debug launch configuration setup(s)
+
+source [find interface/stlink.cfg]
+
+set WORKAREASIZE 0x5000
+
+transport select "hla_swd"
+
+set CHIPNAME STM32F103RBTx
+set BOARDNAME NUCLEO-F103RB
+
+# CHIPNAMES state
+set CHIPNAME_CPU0_ACTIVATED 1
+
+# Enable debug when in low power modes
+set ENABLE_LOW_POWER 1
+
+# Stop Watchdog counters when halt
+set STOP_WATCHDOG 1
+
+# STlink Debug clock frequency
+set CLOCK_FREQ 4000
+
+# use software system reset
+reset_config none
+set CONNECT_UNDER_RESET 0
+
+# BCTM CPU variables
+
+
+
+source [find target/stm32f1x.cfg]
diff --git a/vp-digi Release.cfg b/vp-digi Release.cfg
new file mode 100644
index 0000000..e285a09
--- /dev/null
+++ b/vp-digi Release.cfg
@@ -0,0 +1,35 @@
+# This is an NUCLEO-F103RB board with a single STM32F103RBTx chip
+#
+# Generated by System Workbench for STM32
+# Take care that such file, as generated, may be overridden without any early notice. Please have a look to debug launch configuration setup(s)
+
+source [find interface/stlink.cfg]
+
+set WORKAREASIZE 0x5000
+
+transport select "hla_swd"
+
+set CHIPNAME STM32F103RBTx
+set BOARDNAME NUCLEO-F103RB
+
+# CHIPNAMES state
+set CHIPNAME_CPU0_ACTIVATED 1
+
+# Enable debug when in low power modes
+set ENABLE_LOW_POWER 1
+
+# Stop Watchdog counters when halt
+set STOP_WATCHDOG 1
+
+# STlink Debug clock frequency
+set CLOCK_FREQ 4000
+
+# use software system reset
+reset_config none
+set CONNECT_UNDER_RESET 0
+
+# BCTM CPU variables
+
+
+
+source [find target/stm32f1x.cfg]