diff --git a/Inc/ax25.h b/Inc/ax25.h
index 62cb223..bb2a910 100644
--- a/Inc/ax25.h
+++ b/Inc/ax25.h
@@ -18,46 +18,57 @@ along with VP-Digi. If not, see .
#ifndef AX25_H_
#define AX25_H_
-#define FRAMELEN (150) //single frame max length
-#define FRAMEBUFLEN (600) //circural frame buffer (multiple frames) length
-
+#include
+#include
-#include
-typedef enum
+enum Ax25RxStage
{
- RX_STAGE_IDLE,
+ RX_STAGE_IDLE = 0,
RX_STAGE_FLAG,
RX_STAGE_FRAME,
-} RxStage;
+};
-typedef struct
+struct Ax25ProtoConfig
{
uint16_t txDelayLength; //TXDelay length in ms
uint16_t txTailLength; //TXTail length in ms
uint16_t quietTime; //Quiet time in ms
uint8_t allowNonAprs; //allow non-APRS packets
+};
-} Ax25_config;
-
-Ax25_config ax25Cfg;
+extern struct Ax25ProtoConfig Ax25Config;
+/**
+ * @brief Write frame to transmit buffer
+ * @param *data Data to transmit
+ * @param size Data size
+ * @return Pointer to internal frame handle or NULL on failure
+ * @attention This function will block if transmission is already in progress
+ */
+void *Ax25WriteTxFrame(uint8_t *data, uint16_t size);
-typedef struct
-{
- uint8_t frameBuf[FRAMEBUFLEN]; //cirucal buffer for received frames, frames are separated with 0xFF
- uint16_t frameBufWr; //cirucal RX buffer write index
- uint16_t frameBufRd; //circural TX buffer read index
- uint8_t frameXmit[FRAMEBUFLEN]; //TX frame buffer
- uint16_t xmitIdx; //TX frame buffer index
- uint16_t sLvl; //RMS of the frame
- uint8_t frameReceived; //frame received flag, must be polled in main loop for >0. Bit 0 for frame received on decoder 1, bit 1 for decoder 2
+/**
+ * @brief Get bitmap of "frame received" flags for each decoder. A non-zero value means that a frame was received
+ * @return Bitmap of decoder that received the frame
+ */
+uint8_t Ax25GetReceivedFrameBitmap(void);
-} Ax25;
+/**
+ * @brief Clear bitmap of "frame received" flags
+ */
+void Ax25ClearReceivedFrameBitmap(void);
-Ax25 ax25;
+/**
+ * @brief Get next received frame (if available)
+ * @param **dst Destination buffer that this function allocates and fills
+ * @param *size Actual frame size
+ * @param *signalLevel Frame signal level (RMS)
+ * @return True if frame was read, false if no more frames to read
+ */
+bool Ax25ReadNextRxFrame(uint8_t **dst, uint16_t *size, uint16_t *signalLevel);
/**
* @brief Get current RX stage
@@ -65,7 +76,7 @@ Ax25 ax25;
* @return RX_STATE_IDLE, RX_STATE_FLAG or RX_STATE_FRAME
* @warning Only for internal use
*/
-RxStage Ax25_getRxStage(uint8_t modemNo);
+enum Ax25RxStage Ax25GetRxStage(uint8_t modemNo);
/**
* @brief Parse incoming bit (not symbol!)
@@ -74,29 +85,29 @@ RxStage Ax25_getRxStage(uint8_t modemNo);
* @param[in] *dem Modem state pointer
* @warning Only for internal use
*/
-void Ax25_bitParse(uint8_t bit, uint8_t modemNo);
+void Ax25BitParse(uint8_t bit, uint8_t modemNo);
/**
* @brief Get next bit to be transmitted
* @return Bit to be transmitted
* @warning Only for internal use
*/
-uint8_t Ax25_getTxBit(void);
+uint8_t Ax25GetTxBit(void);
/**
* @brief Initialize transmission and start when possible
*/
-void Ax25_transmitBuffer(void);
+void Ax25TransmitBuffer(void);
/**
* @brief Start transmitting when possible
* @attention Must be continuously polled in main loop
*/
-void Ax25_transmitCheck(void);
+void Ax25TransmitCheck(void);
/**
* @brief Initialize AX25 module
*/
-void Ax25_init(void);
+void Ax25Init(void);
#endif /* AX25_H_ */
diff --git a/Inc/beacon.h b/Inc/beacon.h
index 9106104..57b019f 100644
--- a/Inc/beacon.h
+++ b/Inc/beacon.h
@@ -21,35 +21,35 @@ along with VP-Digi. If not, see .
#include
+#define BEACON_MAX_PAYLOAD_SIZE 100
-
-typedef struct
+struct Beacon
{
uint8_t enable; //enable beacon
uint32_t interval; //interval in seconds
uint32_t delay; //delay in seconds
- uint8_t data[101]; //information field
+ uint8_t data[BEACON_MAX_PAYLOAD_SIZE + 1]; //information field
uint8_t path[15]; //path, 2 parts max, e.g. WIDE11SP22, can be at byte 0, 7 and 14
uint32_t next; //next beacon timestamp
-} Beacon;
+};
-Beacon beacon[8];
+extern struct Beacon beacon[8];
/**
* @brief Send specified beacon
- * @param[in] no Beacon number (0-7)
+ * @param number Beacon number (0-7)
*/
-void Beacon_send(uint8_t no);
+void BeaconSend(uint8_t number);
/**
- * @brief Check if any beacon should be transmitted and transmit if neccessary
+ * @brief Check if any beacon should be transmitted and transmit if necessary
*/
-void Beacon_check(void);
+void BeaconCheck(void);
/**
* @brief Initialize beacon module
*/
-void Beacon_init(void);
+void BeaconInit(void);
#endif /* BEACON_H_ */
diff --git a/Inc/common.h b/Inc/common.h
index dec1af8..fb2262c 100644
--- a/Inc/common.h
+++ b/Inc/common.h
@@ -18,20 +18,25 @@ along with VP-Digi. If not, see .
#define COMMON_H_
#include
+#include "drivers/uart.h"
+#define IS_UPPERCASE_ALPHANUMERIC(x) ((((x) >= '0') && ((x) <= '9')) || (((x) >= 'A') && ((x) <= 'Z')))
+#define IS_NUMBER(x) (((x) >= '0') && ((x) <= '9'))
#define CRC32_INIT 0xFFFFFFFF
-uint8_t call[6]; //device callsign
-uint8_t callSsid; //device ssid
+struct _GeneralConfig
+{
+ uint8_t call[6]; //device callsign
+ uint8_t callSsid; //device ssid
+ uint8_t dest[7]; //destination address for own beacons. Should be APNV01-0 for VP-Digi, but can be changed. SSID MUST remain 0.
+ uint8_t kissMonitor;
+};
-uint8_t dest[7]; //destination address for own beacons. Should be APNV01-0 for VP-Digi, but can be changed. SSID MUST remain 0.
+extern struct _GeneralConfig GeneralConfig;
-const uint8_t *versionString; //version string
+extern const char versionString[]; //version string
-uint8_t autoReset;
-uint32_t autoResetTimer;
-uint8_t kissMonitor;
/**
* @brief Generate random number from min to max
@@ -39,7 +44,7 @@ uint8_t kissMonitor;
* @param[in] max Higher boundary
* @return Generated number
*/
-int16_t rando(int16_t min, int16_t max);
+int16_t Random(int16_t min, int16_t max);
/**
* @brief Convert string to int
@@ -47,15 +52,23 @@ int16_t rando(int16_t min, int16_t max);
* @param[in] len String length or 0 to detect by strlen()
* @return Converted int
*/
-int64_t strToInt(uint8_t *str, uint8_t len);
+int64_t StrToInt(const char *str, uint16_t len);
+
+///**
+// * @brief Convert AX25 frame to TNC2 (readable) format
+// * @param *from Input AX25 frame
+// * @param len Input frame length
+// * @param *to Destination buffer, will be NULL terminated
+// * @param limit Destination buffer size limit
+// */
+//void ConvertToTNC2(uint8_t *from, uint16_t fromlen, uint8_t *to, uint16_t limit);
/**
- * @brief Convert AX25 frame to TNC2 (readable) format
- * @param[in] *from Input AX25 frame
- * @param[in] len Input frame length
- * @param[out] *to Destination buffer, will be NULL terminated
+ * @brief Convert AX25 frame to TNC2 (readable) format and send it through available ports
+ * @param *from Input AX25 frame
+ * @param len Input frame length
*/
-void common_toTNC2(uint8_t *from, uint16_t fromlen, uint8_t *to);
+void SendTNC2(uint8_t *from, uint16_t len);
/**
* @brief Calculate CRC32
@@ -64,13 +77,34 @@ void common_toTNC2(uint8_t *from, uint16_t fromlen, uint8_t *to);
* @param[in] n Input data length
* @return Calculated CRC32
*/
-uint32_t crc32(uint32_t crc0, uint8_t *s, uint64_t n);
+uint32_t Crc32(uint32_t crc0, uint8_t *s, uint64_t n);
+
+/**
+ * @brief Check if callsign is correct and convert it to AX.25 format
+ * @param *in Input ASCII callsign
+ * @param size Input size, not bigger than 6
+ * @param *out Output buffer, exactly 6 bytes
+ * @return True if callsign is valid
+ */
+bool ParseCallsign(const char *in, uint16_t size, uint8_t *out);
+
+/**
+ * @brief Check if callsign with SSID is correct and convert it to AX.25 format
+ * @param *in Input ASCII callsign with SSID
+ * @param size Input size
+ * @param *out Output buffer, exactly 6 bytes
+ * @param *ssid Output SSID, exactly 1 byte
+ * @return True if callsign is valid
+ */
+bool ParseCallsignWithSsid(const char *in, uint16_t size, uint8_t *out, uint8_t *ssid);
/**
- * @brief Send frame to available UARTs and USB in KISS format
- * @param[in] *buf Frame buffer
- * @param[in] len Frame buffer length
+ * @brief Check if SSID is correct and convert it to uint8_t
+ * @param *in Input ASCII SSID
+ * @param size Input size
+ * @param *out Output buffer, exactly 1 byte
+ * @return True if SSID is valid
*/
-void SendKiss(uint8_t *buf, uint16_t len);
+bool ParseSsid(const char *in, uint16_t size, uint8_t *out);
#endif /* COMMON_H_ */
diff --git a/Inc/config.h b/Inc/config.h
index 2c1a4a7..1dcb11c 100644
--- a/Inc/config.h
+++ b/Inc/config.h
@@ -22,88 +22,21 @@ along with VP-Digi. If not, see .
#include
-#define FLAG_CONFIG_WRITTEN 0x6B
-
-#define MEM_CONFIG 0x800F000
-
-//these are relative addresses, absolute address is calculated as relative address + MEM_CONFIG
-//all fields are 16-bit or n*16-bit long, as data in flash is stored in 16-bit words
-#define CONFIG_FLAG 0 //configuration written flag
-#define CONFIG_CALL 2
-#define CONFIG_SSID 8
-#define CONFIG_TXDELAY 10
-#define CONFIG_TXTAIL 12
-#define CONFIG_TXQUIET 14
-#define CONFIG_RS1BAUD 16
-#define CONFIG_RS2BAUD 20
-#define CONFIG_BEACONS 24
-#define CONFIG_BCIV 26 //beacon intervals
-#define CONFIG_BCDL 42 //beacon delays
-#define CONFIG_BC0 58 //beacon information fields, null terminated
-#define CONFIG_BC1 158
-#define CONFIG_BC2 258
-#define CONFIG_BC3 358
-#define CONFIG_BC4 458
-#define CONFIG_BC5 558
-#define CONFIG_BC6 658 //668 ? it should be 658 e.t.c.
-#define CONFIG_BC7 758
-#define CONFIG_BCP0 858 //beacon paths, 14 bytes each
-#define CONFIG_BCP1 872
-#define CONFIG_BCP2 886
-#define CONFIG_BCP3 900
-#define CONFIG_BCP4 914
-#define CONFIG_BCP5 928
-#define CONFIG_BCP6 942
-#define CONFIG_BCP7 956
-#define CONFIG_DIGION 970
-#define CONFIG_DIGIEN 972
-#define CONFIG_DIGIVISC 974 //viscous-delay settings in higher half, direct-only in lower half
-#define CONFIG_DIGIAL0 976
-#define CONFIG_DIGIAL1 982
-#define CONFIG_DIGIAL2 988
-#define CONFIG_DIGIAL3 994
-#define CONFIG_DIGIAL4 1000
-#define CONFIG_DIGIAL5 1008
-#define CONFIG_DIGIAL6 1016
-#define CONFIG_DIGIAL7 1024
-#define CONFIG_DIGIMAX0 1032
-#define CONFIG_DIGIMAX1 1034
-#define CONFIG_DIGIMAX2 1036
-#define CONFIG_DIGIMAX3 1038
-#define CONFIG_DIGIREP0 1040
-#define CONFIG_DIGIREP1 1042
-#define CONFIG_DIGIREP2 1044
-#define CONFIG_DIGIREP3 1046
-#define CONFIG_DIGITRACE 1048
-#define CONFIG_DIGIDEDUPE 1050
-#define CONFIG_DIGICALLFILEN 1052
-#define CONFIG_DIGIFILLIST 1054
-#define CONFIG_DIGIFILTYPE 1194
-#define CONFIG_AUTORST 1196
-#define CONFIG_DIGISSID4 1198
-#define CONFIG_DIGISSID5 1200
-#define CONFIG_DIGISSID6 1202
-#define CONFIG_DIGISSID7 1204
-#define CONFIG_PWM_FLAT 1206
-#define CONFIG_KISSMONITOR 1208
-#define CONFIG_DEST 1210
-#define CONFIG_ALLOWNONAPRS 1216
-#define CONFIG_XXX 1218 //next address (not used)
/**
* @brief Store configuration from RAM to Flash
*/
-void Config_write(void);
+void ConfigWrite(void);
/**
* @brief Erase all configuration
*/
-void Config_erase(void);
+void ConfigErase(void);
/**
* @brief Read configuration from Flash to RAM
* @return 1 if success, 0 if no configuration stored in Flash
*/
-uint8_t Config_read(void);
+uint8_t ConfigRead(void);
#endif /* CONFIG_H_ */
diff --git a/Inc/digipeater.h b/Inc/digipeater.h
index eacc2da..d75da18 100644
--- a/Inc/digipeater.h
+++ b/Inc/digipeater.h
@@ -21,9 +21,7 @@ along with VP-Digi. If not, see .
#include
-
-
-typedef struct
+struct _DigiConfig
{
uint8_t alias[8][6]; //digi alias list
uint8_t ssid[4]; //ssid list for simple aliases
@@ -40,8 +38,7 @@ typedef struct
uint8_t filterPolarity : 1; //filter polarity: 0 - blacklist, 1- whitelist
} Digi;
-Digi digi; //digipeater state
-
+extern struct _DigiConfig DigiConfig; //digipeater state
/**
@@ -50,18 +47,19 @@ Digi digi; //digipeater state
* @param[in] len Frame length
* Decides whether the frame should be digipeated or not, processes it and pushes to TX buffer if needed
*/
-void Digi_digipeat(uint8_t *frame, uint16_t len);
+void DigiDigipeat(uint8_t *frame, uint16_t len);
/**
- * @brief Store duplicate protection hash for the frame already pushed to TX buffer
- * @param[in] idx First frame byte index in TX buffer
+ * @brief Store duplicate protection hash for frame
+ * @param *buf Frame buffer
+ * @param size Frame size
*/
-void Digi_storeDeDupeFromXmitBuf(uint16_t idx);
+void DigiStoreDeDupe(uint8_t *buf, uint16_t size);
/**
- * @brief Refresh viscous-delay buffers and push frames to TX buffer if neccessary
- * @attention Should be called constantly
+ * @brief Refresh viscous-delay buffers and push frames to TX buffer if necessary
+ * @attention Should be called in main loop
*/
-void Digi_viscousRefresh(void);
+void DigiViscousRefresh(void);
#endif /* DIGIPEATER_H_ */
diff --git a/Inc/drivers/afsk.h_bak b/Inc/drivers/afsk.h_bak
deleted file mode 100644
index 1cac2de..0000000
--- a/Inc/drivers/afsk.h_bak
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef DRIVERS_AFSK_H_
-#define DRIVERS_AFSK_H_
-
-//#define ALVLDBG
-
-#include "systick.h"
-#include "stm32f10x.h"
-#include
-#include
-#include
-#include "variables.h"
-#include "common.h"
-#include "ax25.h"
-
-#ifdef ALVLDBG
-#include "drivers/uart.h"
-#endif
-
-#define NN 8 //probkowanie/baudrate
-
-#define PTT_ON GPIOC->BSRR = GPIO_BSRR_BS14
-#define PTT_OFF GPIOC->BSRR = GPIO_BSRR_BR14
-#define DCD_ON (GPIOC->BSRR = GPIO_BSRR_BR13)
-#define DCD_OFF (GPIOC->BSRR = GPIO_BSRR_BS13)
-
-void afsk_decode(uint8_t);
-int32_t afsk_demod(int16_t);
-void DMA1_Channel2_IRQHandler(void) __attribute__ ((interrupt));
-void DMA1_Channel2_IRQHandler(void);
-void TIM2_IRQHandler(void) __attribute__ ((interrupt));
-void TIM2_IRQHandler(void);
-void TIM3_IRQHandler(void) __attribute__ ((interrupt));
-void TIM3_IRQHandler(void);
-void afsk_sendTone(uint8_t);
-void afsk_sendFlag(uint8_t);
-void afsk_transmitTestStart(uint8_t);
-void afsk_transmitTestStop(void);
-void afsk_transmitStart(void);
-void afsk_transmitStop(void);
-void afsk_init(void);
-
-
-#endif
diff --git a/Inc/drivers/modem.h b/Inc/drivers/modem.h
index 5d7ddf6..19bb73a 100644
--- a/Inc/drivers/modem.h
+++ b/Inc/drivers/modem.h
@@ -20,98 +20,105 @@ along with VP-Digi. If not, see .
#include
+//number of parallel demodulators
+//each demodulator must be explicitly configured in code
+#define MODEM_DEMODULATOR_COUNT 2
-typedef enum
+#define MODEM_BAUDRATE 1200.f
+#define MODEM_MARK_FREQUENCY 1200.f
+#define MODEM_SPACE_FREQUENCY 2200.f
+
+enum ModemTxTestMode
{
TEST_DISABLED,
TEST_MARK,
TEST_SPACE,
TEST_ALTERNATING,
-} TxTestMode;
+};
-typedef struct
+struct ModemDemodConfig
{
uint8_t usePWM : 1; //0 - use R2R, 1 - use PWM
uint8_t flatAudioIn : 1; //0 - normal (deemphasized) audio input, 1 - flat audio (unfiltered) input
-} Afsk_config;
+};
-Afsk_config afskCfg;
+extern struct ModemDemodConfig ModemConfig;
-typedef enum
+enum ModemEmphasis
{
PREEMPHASIS,
DEEMPHASIS,
EMPHASIS_NONE
-} Emphasis;
+};
+
/**
- * @brief Get current DCD (channel busy) state
- * @return 0 if channel free, 1 if busy
+ * @brief Get filter type (preemphasis, deemphasis etc.) for given modem
+ * @param modem Modem number
+ * @return Filter type
*/
-uint8_t Afsk_dcdState(void);
+enum ModemEmphasis ModemGetFilterType(uint8_t modem);
/**
- * @brief Check if there is an ongoing TX test
- * @return 0 if not, 1 if any TX test is enabled
+ * @brief Get current DCD state
+ * @return 1 if channel busy, 0 if free
*/
-uint8_t Afsk_isTxTestOngoing(void);
+uint8_t ModemDcdState(void);
/**
- * @brief Clear RMS meter state for specified modem
- * @param[in] modemNo Modem number: 0 or 1
+ * @brief Check if there is a TX test mode enabled
+ * @return 1 if in TX test mode, 0 otherwise
*/
-void Afsk_clearRMS(uint8_t modemNo);
+uint8_t ModemIsTxTestOngoing(void);
/**
- * @brief Clear RMS value from specified modem
- * @param[in] modemNo Modem number: 0 or 1
- * @return RMS
+ * @brief Clear modem RMS counter
+ * @param number Modem number
*/
-uint16_t Afsk_getRMS(uint8_t modemNo);
+void ModemClearRMS(uint8_t number);
/**
- * @brief Current DCD state
- * @return 0 if no DCD (channel free), 1 if DCD
+ * @brief Get RMS value for modem
+ * @param number Modem number
+ * @return RMS value
*/
-uint8_t Afsk_dcdState(void);
+uint16_t ModemGetRMS(uint8_t number);
/**
* @brief Start or restart TX test mode
- * @param[in] type TX test type: TEST_MARK, TEST_SPACE or TEST_ALTERNATING
+ * @param type TX test type: TEST_MARK, TEST_SPACE or TEST_ALTERNATING
*/
-void Afsk_txTestStart(TxTestMode type);
+void ModemTxTestStart(enum ModemTxTestMode type);
/**
* @brief Stop TX test mode
*/
-void Afsk_txTestStop(void);
-
+void ModemTxTestStop(void);
/**
* @brief Configure and start TX
- * @warning Transmission should be started with Ax25_transmitBuffer
+ * @info This function is used internally by protocol module.
+ * @warning Use Ax25TransmitStart() to initialize transmission
*/
-void Afsk_transmitStart(void);
+void ModemTransmitStart(void);
/**
* @brief Stop TX and go back to RX
*/
-void Afsk_transmitStop(void);
+void ModemTransmitStop(void);
/**
- * @brief Initialize AFSK module
+ * @brief Initialize modem module
*/
-void Afsk_init(void);
+void ModemInit(void);
-
-void DMA1_Channel2_IRQHandler(void) __attribute__ ((interrupt));
-void TIM3_IRQHandler(void) __attribute__ ((interrupt));
-void TIM2_IRQHandler(void) __attribute__ ((interrupt));
-
+#if (MODEM_DEMODULATOR_COUNT > 8)
+#error There may be at most 8 parallel demodulators/decoders
+#endif
#endif
diff --git a/Inc/drivers/systick.h b/Inc/drivers/systick.h
index dc0428a..93a5378 100644
--- a/Inc/drivers/systick.h
+++ b/Inc/drivers/systick.h
@@ -19,12 +19,15 @@ along with VP-Digi. If not, see .
#define SYSTICK_H_
#include
-#include "stm32f1xx.h"
+
+
+#define SYSTICK_FREQUENCY 100 //systick frequency in Hz
+#define SYSTICK_INTERVAL (1000 / SYSTICK_FREQUENCY) //systick interval in milliseconds
extern volatile uint32_t ticks;
//void SysTick_Handler(void);
-void SysTick_init(void);
+void SysTickInit(void);
#endif /* SYSTICK_H_ */
diff --git a/Inc/drivers/uart.h b/Inc/drivers/uart.h
index b2bcf49..3d967cb 100644
--- a/Inc/drivers/uart.h
+++ b/Inc/drivers/uart.h
@@ -18,124 +18,102 @@ along with VP-Digi. If not, see .
#ifndef UART_H_
#define UART_H_
-#define UARTBUFLEN 250
-
#include "stm32f1xx.h"
#include
#include "usbd_cdc_if.h"
+#include "ax25.h"
+
+#define UART_BUFFER_SIZE 250
-typedef enum
+enum UartMode
{
MODE_KISS,
MODE_TERM,
MODE_MONITOR,
-} Uart_mode;
+};
-typedef enum
+enum UartDataType
{
+ DATA_NOTHING = 0,
DATA_KISS,
DATA_TERM,
- DATA_NOTHING,
-} Uart_data_type;
+};
typedef struct
{
volatile USART_TypeDef *port; //UART peripheral
uint32_t baudrate; //baudrate 1200-115200
- Uart_data_type rxflag; //rx status
- uint8_t txflag; //tx status (1 when transmitting)
- uint8_t bufrx[UARTBUFLEN]; //buffer for rx data
- uint16_t bufrxidx; //rx data buffer index
- uint8_t buftx[UARTBUFLEN]; //circular tx buffer
- uint16_t buftxrd, buftxwr; //tx buffer indexes
- Uart_mode mode; //uart mode
- uint8_t enabled;
+ enum UartDataType rxType; //rx status
+ uint8_t enabled : 1;
+ uint8_t isUsb : 1;
+ uint8_t rxBuffer[UART_BUFFER_SIZE];
+ uint16_t rxBufferHead;
+ uint8_t txBuffer[UART_BUFFER_SIZE];
+ uint16_t txBufferHead, txBufferTail;
+ uint8_t txBufferFull : 1;
+ enum UartMode mode;
uint32_t kissTimer;
} Uart;
-Uart uart1, uart2;
-
-Uart_mode USBmode;
-Uart_data_type USBrcvd;
-uint8_t USBint; //USB "interrupt" flag
-
-
-/**
- * \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);
-
+extern Uart Uart1, Uart2, UartUsb;
-/**
- * \brief Send single byte using USB
- * \param[in] data Byte
- */
-void uartUSB_sendByte(uint8_t data);
+///**
+// * \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 Start buffer transmission
- * \param[in] *port UART
- */
-void uart_transmitStart(Uart *port);
-
-/**
- * \brief Store byte in TX buffer
- * \param[in] *port UART
- * \param[in] data Data
+ * @brief Send byte
+ * @param[in] *port UART
+ * @param[in] data Data
*/
-void uart_sendByte(Uart *port, uint8_t data);
+void UartSendByte(Uart *port, uint8_t data);
/**
- * \brief Store string in TX buffer
- * \apram[in] *port UART
- * \param[in] *data Buffer
- * \param[in] len Buffer length or 0 for null-terminated string
+ * @brief Send string
+ * @param *port UART
+ * @param *data Buffer
+ * @param len Buffer length or 0 for null-terminated string
*/
-void uart_sendString(Uart *port, uint8_t *data, uint16_t datalen);
+void UartSendString(Uart *port, void *data, uint16_t datalen);
/**
- * \brief Send string using USB
- * \param[in] *data Buffer
- * \param[in] len Buffer length or 0 for null-terminated string
+ * @brief Send signed number
+ * @param *port UART
+ * @param n Number
*/
-void uartUSB_sendString(uint8_t* data, uint16_t len);
+void UartSendNumber(Uart *port, int32_t n);
-/**
- * \brief Store number (in ASCII format) in TX buffer
- * \param[in] *port UART
- * \param[in] n Number
- */
-void uart_sendNumber(Uart *port, int32_t n);
/**
- * \brief Send number (in ASCII format) using USB
- * \param[in] n Number
+ * @brief Initialize UART structures
+ * @param *port UART [prt
+ * @param *uart Physical UART peripheral. NULL if USB in CDC mode
+ * @param baud Baudrate
*/
-void uartUSB_sendNumber(int32_t n);
-
+void UartInit(Uart *port, USART_TypeDef *uart, uint32_t baud);
/**
- * \brief Initialize UART structures
- * \param[in] *port UART
- * \param[in] *uart Physical UART peripheral
- * \param[in] baud Baudrate
+ * @brief Configure and enable/disable UART
+ * @param *port UART port
+ * @param state 0 - disable, 1 - enable
*/
-void uart_init(Uart *port, USART_TypeDef *uart, uint32_t baud);
+void UartConfig(Uart *port, uint8_t state);
/**
- * \brief Configure and enable/disable UART
- * \param[in] *port UART
- * \param[in] state 0 - disable, 1 - enable
+ * @brief Clear RX buffer and flags
+ * @param *port UART port
*/
-void uart_config(Uart *port, uint8_t state);
+void UartClearRx(Uart *port);
/**
- * \brief Clear RX buffer and flags
- * \param[in] *port UART
+ * @brief Handle KISS timeout
+ * @param *port UART pointer
+ * @attention This function must be polled constantly in main loop for USB UART.
*/
-void uart_clearRx(Uart *port);
+void UartHandleKissTimeout(Uart *port);
#endif
diff --git a/Inc/drivers/watchdog.h b/Inc/drivers/watchdog.h
index 4623368..fb4be59 100644
--- a/Inc/drivers/watchdog.h
+++ b/Inc/drivers/watchdog.h
@@ -23,12 +23,12 @@ along with VP-Digi. If not, see .
/**
* @brief Initialize watchdog
*/
-void Wdog_init(void);
+void WdogInit(void);
/**
* @brief Restart watchdog
* @attention Must be called continuously in main loop
*/
-void Wdog_reset(void);
+void WdogReset(void);
#endif /* DRIVERS_WATCHDOG_H_ */
diff --git a/Inc/terminal.h b/Inc/terminal.h
index 95d62af..45623ce 100644
--- a/Inc/terminal.h
+++ b/Inc/terminal.h
@@ -21,71 +21,39 @@ along with VP-Digi. If not, see .
#include "drivers/uart.h"
#include
-
-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 Send data to all available monitor outputs
- * \param[in] *data Data to send
- * \param[in] len Data length or 0 for NULL-terminated data
- */
-void term_sendMonitor(uint8_t *data, uint16_t len);
-
-/**
- * \brief Send number to all available monitor outputs
- * \param[in] data Number to send
- */
-void term_sendMonitorNumber(int32_t data);
-
-/**
-* \brief Send terminal buffer using specified stream
-* \param[in] way Stream: TERM_ANY, TERM_USB, TERM_UART1, TERM_UART2
-*/
-void term_sendBuf(Terminal_stream way);
-
-/**
- * \brief Push byte to terminal buffer
- * \param[in] data Byte to store
- */
-void term_sendByte(uint8_t data);
-
-/**
- * \brief Push string to terminal buffer
- * \param[in] *data String
- * \param[in] len String length or 0 for NULL-terminated string
- */
-void term_sendString(uint8_t *data, uint16_t len);
-
/**
- * \brief Push number (in ASCII form) in terminal buffer
- * \param[in] n Number
+ * @brief Send data to all available ports
+ * @param mode Output mode/data type
+ * @param *data Data buffer
+ * @param size Data size
*/
-void term_sendNumber(int32_t n);
+void TermSendToAll(enum UartMode mode, uint8_t *data, uint16_t size);
+
+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[in] *cmd Data
- * \param[in] len Data length
- * \param[in] src Source: TERM_USB, TERM_UART1, TERM_UART2
- * \param[in] type Data type: DATA_KISS, DATA_TERM
- * \param[in] mode Input mode: MODE_KISS, MODE_TERM, MODE_MONITOR
+ * \param *src UART structure
*/
-void term_parse(uint8_t *cmd, uint16_t len, Terminal_stream src, Uart_data_type type, Uart_mode mode);
+void TermParse(Uart *src);
#endif /* DEBUG_H_ */
diff --git a/Inc/usbd_cdc_if.h b/Inc/usbd_cdc_if.h
index 84ca6fa..9792e9a 100644
--- a/Inc/usbd_cdc_if.h
+++ b/Inc/usbd_cdc_if.h
@@ -91,9 +91,7 @@
extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
-uint8_t usbrcvdflag;
-uint8_t usbcdcdata[UARTBUFLEN];
-uint16_t usbcdcidx;
+
/* USER CODE END EXPORTED_VARIABLES */
/**
diff --git a/Src/ax25.c b/Src/ax25.c
index de8666a..941c907 100644
--- a/Src/ax25.c
+++ b/Src/ax25.c
@@ -20,6 +20,44 @@ along with VP-Digi. If not, see .
#include "drivers/modem.h"
#include "common.h"
#include "drivers/systick.h"
+#include
+
+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_COUNT (10) //max count of frames in buffer
+#define FRAME_BUFFER_SIZE (FRAME_MAX_COUNT * 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
+
+#define MAX_TRANSMIT_RETRY_COUNT 8 //max number of retries if channel is busy
+
+struct FrameHandle
+{
+ uint16_t start;
+ uint16_t size;
+ uint16_t signalLevel;
+};
+
+static uint8_t rxBuffer[FRAME_BUFFER_SIZE]; //circular buffer for received frames
+static uint16_t rxBufferHead = 0; //circular RX buffer write index
+static struct FrameHandle rxFrame[FRAME_MAX_COUNT];
+static uint8_t rxFrameHead = 0;
+static uint8_t rxFrameTail = 0;
+static bool rxFrameBufferFull = false;
+
+static uint8_t txBuffer[FRAME_BUFFER_SIZE]; //circular TX frame buffer
+static uint16_t txBufferHead = 0; //circular TX buffer write index
+static uint16_t txBufferTail = 0;
+static struct FrameHandle txFrame[FRAME_MAX_COUNT];
+static uint8_t txFrameHead = 0;
+static uint8_t txFrameTail = 0;
+static bool txFrameBufferFull = false;
+
+static uint8_t frameReceived; //a bitmap of receivers that received the frame
+
enum TxStage
{
@@ -39,89 +77,148 @@ enum TxInitStage
TX_INIT_TRANSMITTING
};
-struct TxState
+static uint8_t txByte = 0; //current TX byte
+static uint16_t txByteIdx = 0; //current TX byte index
+static int8_t txBitIdx = 0; //current bit index in txByte
+static uint16_t txDelayElapsed = 0; //counter of TXDelay bytes already sent
+static uint8_t txFlagsElapsed = 0; //counter of flag bytes already sent
+static uint8_t txCrcByteIdx = 0; //currently transmitted byte of CRC
+static uint8_t txBitstuff = 0; //bit-stuffing counter
+static uint16_t txTailElapsed; //counter of TXTail bytes already sent
+static uint16_t txCrc = 0xFFFF; //current CRC
+static uint32_t txQuiet = 0; //quit time + current tick value
+static uint8_t txRetries = 0; //number of TX retries
+static enum TxInitStage txInitStage; //current TX initialization stage
+static enum TxStage txStage; //current TX stage
+
+struct RxState
{
- uint8_t txByte; //current TX byte
- int8_t txBitIdx; //current bit index in txByte
- uint16_t txDelayElapsed; //counter of TXDelay bytes already sent
- uint8_t flagsElapsed; //counter of flag bytes already sent
- uint16_t xmitIdx; //current TX byte index in TX buffer
- uint8_t crcIdx; //currently transmitted byte of CRC
- uint8_t bitstuff; //bit-stuffing counter
- uint16_t txTailElapsed; //counter of TXTail bytes already sent
- uint16_t txDelay; //number of TXDelay bytes to send
- uint16_t txTail; //number of TXTail bytes to send
uint16_t crc; //current CRC
- uint32_t txQuiet; //quit time + current tick value
- uint8_t txRetries; //number of TX retries
- enum TxInitStage tx; //current TX initialization stage
- enum TxStage txStage; //current TX stage
-};
-
-volatile struct TxState txState;
-
-
-typedef struct
-{
- uint16_t crc; //current CRC
- uint8_t frame[FRAMELEN]; //raw frame buffer
+ uint8_t frame[FRAME_MAX_SIZE]; //raw frame buffer
uint16_t frameIdx; //index for raw frame buffer
- uint8_t recByte; //byte being currently received
- uint8_t rBitIdx; //bit index for recByte
+ uint8_t receivedByte; //byte being currently received
+ uint8_t receivedBitIdx; //bit index for recByte
uint8_t rawData; //raw data being currently received
- RxStage rx; //current RX stage
+ enum Ax25RxStage rx; //current RX stage
uint8_t frameReceived; //frame received flag
-} RxState;
-
-volatile RxState rxState1, rxState2;
+};
-uint16_t lastCrc = 0; //CRC of the last received frame. If not 0, a frame was successfully received
-uint16_t rxMultiplexDelay = 0; //simple delay for decoder multiplexer to avoid receiving the same frame twice
+static volatile struct RxState rxState[MODEM_DEMODULATOR_COUNT];
-RxStage Ax25_getRxStage(uint8_t modemNo)
-{
- if(modemNo == 0)
- return rxState1.rx;
-
- return rxState2.rx;
-}
+static uint16_t lastCrc = 0; //CRC of the last received frame. If not 0, a frame was successfully received
+static uint16_t rxMultiplexDelay = 0; //simple delay for decoder multiplexer to avoid receiving the same frame twice
+static uint16_t txDelay; //number of TXDelay bytes to send
+static uint16_t txTail; //number of TXTail bytes to send
+#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))
/**
* @brief Recalculate CRC for one bit
- * @param[in] bit Input bit
+ * @param bit Input bit
* @param *crc CRC pointer
*/
-static void ax25_calcCRC(uint8_t bit, uint16_t *crc) {
- static uint16_t xor_result;
+static void calculateCRC(uint8_t bit, uint16_t *crc)
+{
+ uint16_t xor_result;
xor_result = *crc ^ bit;
*crc >>= 1;
if (xor_result & 0x0001)
{
*crc ^= 0x8408;
}
- return;
}
-void Ax25_bitParse(uint8_t bit, uint8_t modemNo)
+uint8_t Ax25GetReceivedFrameBitmap(void)
{
- if(lastCrc > 0) //there was a frame received
+ return frameReceived;
+}
+
+void Ax25ClearReceivedFrameBitmap(void)
+{
+ frameReceived = 0;
+}
+
+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++)
+ {
+ txBuffer[txBufferHead++] = data[i];
+ txBufferHead %= FRAME_BUFFER_SIZE;
+ }
+ void *ret = &txFrame[txFrameHead];
+ txFrameHead++;
+ txFrameHead %= FRAME_MAX_COUNT;
+ if(txFrameHead == txFrameTail)
+ txFrameBufferFull = true;
+ return ret;
+}
+
+
+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;
+ }
+
+ for(uint16_t i = 0; i < rxFrame[rxFrameTail].size; i++)
+ {
+ (*dst)[i] = rxBuffer[(rxFrame[rxFrameTail].start + i) % FRAME_BUFFER_SIZE];
+ }
+
+ *signalLevel = rxFrame[rxFrameTail].signalLevel;
+ *size = rxFrame[rxFrameTail].size;
+
+ rxFrameBufferFull = false;
+ rxFrameTail++;
+ rxFrameTail %= FRAME_MAX_COUNT;
+ return true;
+}
+
+enum Ax25RxStage Ax25GetRxStage(uint8_t modem)
+{
+ return rxState[modem].rx;
+}
+
+
+void Ax25BitParse(uint8_t bit, uint8_t modem)
+{
+ if(lastCrc != 0) //there was a frame received
{
rxMultiplexDelay++;
- if(rxMultiplexDelay > 4) //hold it for a while and wait for the other decoder to receive the frame
+ if(rxMultiplexDelay > (4 * MODEM_DEMODULATOR_COUNT)) //hold it for a while and wait for other decoders to receive the frame
{
lastCrc = 0;
rxMultiplexDelay = 0;
- ax25.frameReceived = (rxState1.frameReceived > 0) | ((rxState2.frameReceived > 0) << 1);
+ for(uint8_t i = 0; i < MODEM_DEMODULATOR_COUNT; i++)
+ {
+ frameReceived |= ((rxState[i].frameReceived > 0) << i);
+ rxState[i].frameReceived = 0;
+ }
}
}
- RxState *rx = (RxState*)&rxState1;
- if(modemNo == 1)
- rx = (RxState*)&rxState2;
+ struct RxState *rx = (struct RxState*)&(rxState[modem]);
rx->rawData <<= 1; //store incoming bit
rx->rawData |= (bit > 0);
@@ -129,7 +226,7 @@ void Ax25_bitParse(uint8_t bit, uint8_t modemNo)
if(rx->rawData == 0x7E) //HDLC flag received
{
- if(rx->rx == RX_STAGE_FRAME) //we are in frame, so this is the end of the frame
+ if(rx->rx == RX_STAGE_FRAME) //if we are in frame, this is the end of the frame
{
if((rx->frameIdx > 15)) //correct frame must be at least 16 bytes long
{
@@ -142,69 +239,55 @@ void Ax25_bitParse(uint8_t bit, uint8_t modemNo)
//if non-APRS frames are not allowed, check if this frame has control=0x03 and PID=0xF0
- if(!ax25Cfg.allowNonAprs && ((rx->frame[i + 1] != 0x03) || (rx->frame[i + 2] != 0xf0)))
+ if(Ax25Config.allowNonAprs || (((rx->frame[i + 1] == 0x03) && (rx->frame[i + 2] == 0xf0))))
{
- rx->recByte = 0;
- rx->rBitIdx = 0;
- rx->frameIdx = 0;
- rx->crc = 0xFFFF;
-
- return;
+ if((rx->frame[rx->frameIdx - 2] == ((rx->crc & 0xFF) ^ 0xFF)) && (rx->frame[rx->frameIdx - 1] == (((rx->crc >> 8) & 0xFF) ^ 0xFF))) //check CRC
+ {
+ rx->frameReceived = 1;
+ rx->frameIdx -= 2; //remove CRC
+ if(rx->crc != lastCrc) //the other decoder has not received this frame yet, so store it in main frame buffer
+ {
+ lastCrc = rx->crc; //store CRC of this frame
+
+ if(!rxFrameBufferFull) //if enough space, store the frame
+ {
+ rxFrame[rxFrameHead].start = rxBufferHead;
+ rxFrame[rxFrameHead].signalLevel = ModemGetRMS(modem);
+ rxFrame[rxFrameHead++].size = rx->frameIdx;
+ rxFrameHead %= FRAME_MAX_COUNT;
+ if(rxFrameHead == txFrameHead)
+ rxFrameBufferFull = true;
+
+ for(uint16_t i = 0; i < rx->frameIdx; i++)
+ {
+ rxBuffer[rxBufferHead++] = rx->frame[i];
+ rxBufferHead %= FRAME_BUFFER_SIZE;
+ }
+
+ }
+ }
+ }
}
- if ((rx->frame[rx->frameIdx - 2] == ((rx->crc & 0xFF) ^ 0xFF)) && (rx->frame[rx->frameIdx - 1] == (((rx->crc >> 8) & 0xFF) ^ 0xFF))) //check CRC
- {
- rx->frameReceived = 1;
- if(rx->crc != lastCrc) //the other decoder has not received this frame yet, so store it in main frame buffer
- {
- lastCrc = rx->crc; //store CRC of this frame
- ax25.sLvl = Afsk_getRMS(modemNo); //get RMS amplitude of the received frame
- uint16_t freebuf = 0;
- if(ax25.frameBufWr > ax25.frameBufRd) //check if there is enough free space in buffer
- freebuf = FRAMEBUFLEN - ax25.frameBufWr + ax25.frameBufRd - 3;
- else
- freebuf = ax25.frameBufRd - ax25.frameBufWr - 3;
-
- if((rx->frameIdx - 2) <= freebuf) //if enough space, store the frame
- {
- for(uint16_t i = 0; i < rx->frameIdx - 2; i++)
- {
- ax25.frameBuf[ax25.frameBufWr++] = rx->frame[i];
- ax25.frameBufWr %= (FRAMEBUFLEN);
- }
- ax25.frameBuf[ax25.frameBufWr++] = 0xFF; //add frame separator
- ax25.frameBufWr %= FRAMEBUFLEN;
- }
- }
- } else
- {
- Afsk_clearRMS(modemNo);
- }
-
}
-
- rx->recByte = 0;
- rx->rBitIdx = 0;
- rx->frameIdx = 0;
- rx->crc = 0xFFFF;
}
rx->rx = RX_STAGE_FLAG;
- rx->recByte = 0;
- rx->rBitIdx = 0;
+ ModemClearRMS(modem);
+ rx->receivedByte = 0;
+ rx->receivedBitIdx = 0;
rx->frameIdx = 0;
rx->crc = 0xFFFF;
- Afsk_clearRMS(modemNo);
return;
}
if((rx->rawData & 0x7F) == 0x7F) //received 7 consecutive ones, this is an error (sometimes called "escape byte")
{
- Afsk_clearRMS(modemNo);
- rx->rx = RX_STAGE_IDLE;
- rx->recByte = 0;
- rx->rBitIdx = 0;
+ rx->rx = RX_STAGE_FLAG;
+ ModemClearRMS(modem);
+ rx->receivedByte = 0;
+ rx->receivedBitIdx = 0;
rx->frameIdx = 0;
rx->crc = 0xFFFF;
return;
@@ -216,232 +299,220 @@ void Ax25_bitParse(uint8_t bit, uint8_t modemNo)
return;
- if((rx->rawData & 0x3F) == 0x3E) //dismiss bit 0 added by bitstuffing
+ if((rx->rawData & 0x3F) == 0x3E) //dismiss bit 0 added by bit stuffing
return;
if(rx->rawData & 0x01) //received bit 1
- rx->recByte |= 0x80; //store it
+ rx->receivedByte |= 0x80; //store it
- if(++rx->rBitIdx >= 8) //received full byte
+ if(++rx->receivedBitIdx >= 8) //received full byte
{
- if(rx->frameIdx > FRAMELEN) //frame is too long
+ if(rx->frameIdx > FRAME_MAX_SIZE) //frame is too long
{
rx->rx = RX_STAGE_IDLE;
- rx->recByte = 0;
- rx->rBitIdx = 0;
+ ModemClearRMS(modem);
+ rx->receivedByte = 0;
+ rx->receivedBitIdx = 0;
rx->frameIdx = 0;
rx->crc = 0xFFFF;
- Afsk_clearRMS(modemNo);
return;
}
if(rx->frameIdx >= 2) //more than 2 bytes received, calculate CRC
{
for(uint8_t i = 0; i < 8; i++)
{
- ax25_calcCRC((rx->frame[rx->frameIdx - 2] >> i) & 0x01, &(rx->crc));
+ calculateCRC((rx->frame[rx->frameIdx - 2] >> i) & 1, &(rx->crc));
}
}
rx->rx = RX_STAGE_FRAME;
- rx->frame[rx->frameIdx++] = rx->recByte; //store received byte
- rx->recByte = 0;
- rx->rBitIdx = 0;
+ rx->frame[rx->frameIdx++] = rx->receivedByte; //store received byte
+ rx->receivedByte = 0;
+ rx->receivedBitIdx = 0;
}
else
- rx->recByte >>= 1;
+ rx->receivedByte >>= 1;
}
-uint8_t Ax25_getTxBit(void)
+uint8_t Ax25GetTxBit(void)
{
- if(txState.txBitIdx == 8)
+ if(txBitIdx == 8)
{
- txState.txBitIdx = 0;
- if(txState.txStage == TX_STAGE_PREAMBLE) //transmitting preamble (TXDelay)
+ txBitIdx = 0;
+ if(txStage == TX_STAGE_PREAMBLE) //transmitting preamble (TXDelay)
{
- if(txState.txDelayElapsed < txState.txDelay) //still transmitting
+ if(txDelayElapsed < txDelay) //still transmitting
{
- txState.txByte = 0x7E;
- txState.txDelayElapsed++;
+ txByte = 0x7E;
+ txDelayElapsed++;
}
else //now transmit initial flags
{
- txState.txDelayElapsed = 0;
- txState.txStage = TX_STAGE_HEADER_FLAGS;
+ txDelayElapsed = 0;
+ txStage = TX_STAGE_HEADER_FLAGS;
}
}
- if(txState.txStage == TX_STAGE_HEADER_FLAGS) //transmitting initial flags
+ if(txStage == TX_STAGE_HEADER_FLAGS) //transmitting initial flags
{
- if(txState.flagsElapsed < 4) //say we want to transmit 4 flags
+ if(txFlagsElapsed < STATIC_HEADER_FLAG_COUNT)
{
- txState.txByte = 0x7E;
- txState.flagsElapsed++;
+ txByte = 0x7E;
+ txFlagsElapsed++;
}
else
{
- txState.flagsElapsed = 0;
- txState.txStage = TX_STAGE_DATA; //transmit data
+ txFlagsElapsed = 0;
+ txStage = TX_STAGE_DATA; //transmit data
}
}
- if(txState.txStage == TX_STAGE_DATA) //transmitting normal data
+ if(txStage == TX_STAGE_DATA) //transmitting normal data
{
- if((ax25.xmitIdx > 10) && (txState.xmitIdx < ax25.xmitIdx)) //send buffer
+transmitNormalData:
+ if((txFrameHead != txFrameTail) || txFrameBufferFull)
{
- if(ax25.frameXmit[txState.xmitIdx] == 0xFF) //frame separator found
+ if(txByteIdx < txFrame[txFrameTail].size) //send buffer
{
- txState.txStage = TX_STAGE_CRC; //transmit CRC
- txState.xmitIdx++;
+ txByte = txBuffer[(txFrame[txFrameTail].start + txByteIdx) % FRAME_BUFFER_SIZE];
+ txByteIdx++;
}
- else //normal bytes
+ else //end of buffer, send CRC
{
- txState.txByte = ax25.frameXmit[txState.xmitIdx];
- txState.xmitIdx++;
+ txStage = TX_STAGE_CRC; //transmit CRC
+ txCrcByteIdx = 0;
}
- } else //end of buffer
+ }
+ else //no more frames
{
- ax25.xmitIdx = 0;
- txState.xmitIdx = 0;
- txState.txStage = TX_STAGE_TAIL;
+ txByteIdx = 0;
+ txBitIdx = 0;
+ txStage = TX_STAGE_TAIL;
}
}
- if(txState.txStage == TX_STAGE_CRC) //transmitting CRC
+ if(txStage == TX_STAGE_CRC) //transmitting CRC
{
-
- if(txState.crcIdx < 2)
+ if(txCrcByteIdx <= 1)
{
- txState.txByte = (txState.crc >> (txState.crcIdx * 8)) ^ 0xFF;
- txState.crcIdx++;
+ txByte = (txCrc & 0xFF) ^ 0xFF;
+ txCrc >>= 8;
+ txCrcByteIdx++;
}
else
{
- txState.crc = 0xFFFF;
- txState.txStage = TX_STAGE_FOOTER_FLAGS; //now transmit flags
- txState.crcIdx = 0;
+ txCrc = 0xFFFF;
+ txStage = TX_STAGE_FOOTER_FLAGS; //now transmit flags
+ txFlagsElapsed = 0;
}
+
}
- if(txState.txStage == TX_STAGE_FOOTER_FLAGS)
+ if(txStage == TX_STAGE_FOOTER_FLAGS)
{
- if(txState.flagsElapsed < 8) //say we want to transmit 8 flags
+ if(txFlagsElapsed < STATIC_FOOTER_FLAG_COUNT)
{
- txState.txByte = 0x7E;
- txState.flagsElapsed++;
- } else
+ txByte = 0x7E;
+ txFlagsElapsed++;
+ }
+ else
{
- txState.flagsElapsed = 0;
- txState.txStage = TX_STAGE_DATA; //return to normal data transmission stage. There might be a next frame to transmit
- if((ax25.xmitIdx > 10) && (txState.xmitIdx < ax25.xmitIdx)) //send buffer
- {
- if(ax25.frameXmit[txState.xmitIdx] == 0xFF) //frame separator found
- {
- txState.txStage = TX_STAGE_CRC; //transmit CRC
- txState.xmitIdx++;
- }
- else //normal bytes
- {
- txState.txByte = ax25.frameXmit[txState.xmitIdx];
- txState.xmitIdx++;
- }
- } else //end of buffer
- {
- ax25.xmitIdx = 0;
- txState.xmitIdx = 0;
- txState.txStage = TX_STAGE_TAIL;
- }
+ txFlagsElapsed = 0;
+ txStage = TX_STAGE_DATA; //return to normal data transmission stage. There might be a next frame to transmit
+ txFrameBufferFull = false;
+ txFrameTail++;
+ txFrameTail %= FRAME_MAX_COUNT;
+ goto transmitNormalData;
}
}
- if(txState.txStage == TX_STAGE_TAIL) //transmitting tail
+ if(txStage == TX_STAGE_TAIL) //transmitting tail
{
- ax25.xmitIdx = 0;
- if(txState.txTailElapsed < txState.txTail)
+ if(txTailElapsed < txTail)
{
- txState.txByte = 0x7E;
- txState.txTailElapsed++;
+ txByte = 0x7E;
+ txTailElapsed++;
}
else //tail transmitted, stop transmission
{
- txState.txTailElapsed = 0;
- txState.txStage = TX_STAGE_IDLE;
- txState.crc = 0xFFFF;
- txState.bitstuff = 0;
- txState.txByte = 0;
- txState.tx = TX_INIT_OFF;
- Afsk_transmitStop();
+ txTailElapsed = 0;
+ txStage = TX_STAGE_IDLE;
+ txCrc = 0xFFFF;
+ txBitstuff = 0;
+ txByte = 0;
+ txInitStage = TX_INIT_OFF;
+ txBufferTail = txBufferHead;
+ ModemTransmitStop();
+ return 0;
}
-
-
}
}
uint8_t txBit = 0;
- if((txState.txStage == TX_STAGE_DATA) || (txState.txStage == TX_STAGE_CRC)) //transmitting normal data or CRC
+ if((txStage == TX_STAGE_DATA) || (txStage == TX_STAGE_CRC)) //transmitting normal data or CRC
{
- if(txState.bitstuff == 5) //5 consecutive ones transmitted
+ if(txBitstuff == 5) //5 consecutive ones transmitted
{
txBit = 0; //transmit bit-stuffed 0
- txState.bitstuff = 0;
+ txBitstuff = 0;
}
else
{
- if(txState.txByte & 1) //1 being transmitted
+ if(txByte & 1) //1 being transmitted
{
- txState.bitstuff++; //increment bit stuffing counter
+ txBitstuff++; //increment bit stuffing counter
txBit = 1;
- } else
+ }
+ else
{
txBit = 0;
- txState.bitstuff = 0; //0 being transmitted, reset bit stuffing counter
+ txBitstuff = 0; //0 being transmitted, reset bit stuffing counter
}
- if(txState.txStage == TX_STAGE_DATA) //calculate CRC only for normal data
- ax25_calcCRC(txState.txByte & 1, (uint16_t*)&(txState.crc));
- txState.txByte >>= 1;
- txState.txBitIdx++;
+ if(txStage == TX_STAGE_DATA) //calculate CRC only for normal data
+ calculateCRC(txByte & 1, &txCrc);
+
+ txByte >>= 1;
+ txBitIdx++;
}
}
else //transmitting preamble or flags, don't calculate CRC, don't use bit stuffing
{
- txBit = txState.txByte & 1;
- txState.txByte >>= 1;
- txState.txBitIdx++;
+ txBit = txByte & 1;
+ txByte >>= 1;
+ txBitIdx++;
}
return txBit;
-
}
/**
* @brief Initialize transmission and start when possible
*/
-void Ax25_transmitBuffer(void)
+void Ax25TransmitBuffer(void)
{
- if(txState.tx == TX_INIT_WAITING)
+ if(txInitStage == TX_INIT_WAITING)
return;
- if(txState.tx == TX_INIT_TRANSMITTING)
+ if(txInitStage == TX_INIT_TRANSMITTING)
return;
- if(ax25.xmitIdx > 10)
+ if((txFrameHead != txFrameTail) || txFrameBufferFull)
{
- txState.txQuiet = (ticks + (ax25Cfg.quietTime / 10) + rando(0, 20)); //calculate required delay
- txState.tx = TX_INIT_WAITING;
+ txQuiet = (ticks + (Ax25Config.quietTime / SYSTICK_INTERVAL) + Random(0, 200 / SYSTICK_INTERVAL)); //calculate required delay
+ txInitStage = TX_INIT_WAITING;
}
- else ax25.xmitIdx = 0;
}
-
-
/**
* @brief Start transmission immediately
* @warning Transmission should be initialized using Ax25_transmitBuffer
*/
-static void ax25_transmitStart(void)
+static void transmitStart(void)
{
- txState.crc = 0xFFFF; //initial CRC value
- txState.txStage = TX_STAGE_PREAMBLE;
- txState.txByte = 0;
- txState.txBitIdx = 0;
- Afsk_transmitStart();
+ txCrc = 0xFFFF; //initial CRC value
+ txStage = TX_STAGE_PREAMBLE;
+ txByte = 0;
+ txBitIdx = 0;
+ txFlagsElapsed = 0;
+ ModemTransmitStart();
}
@@ -449,58 +520,49 @@ static void ax25_transmitStart(void)
* @brief Start transmitting when possible
* @attention Must be continuously polled in main loop
*/
-void Ax25_transmitCheck(void)
+void Ax25TransmitCheck(void)
{
- if(txState.tx == TX_INIT_OFF) //TX not initialized at all, nothing to transmit
+ if(txInitStage == TX_INIT_OFF) //TX not initialized at all, nothing to transmit
return;
- if(txState.tx == TX_INIT_TRANSMITTING) //already transmitting
+ if(txInitStage == TX_INIT_TRANSMITTING) //already transmitting
return;
- if(ax25.xmitIdx < 10)
- {
- ax25.xmitIdx = 0;
- return;
- }
-
- if(Afsk_isTxTestOngoing()) //TX test is enabled, wait for now
+ if(ModemIsTxTestOngoing()) //TX test is enabled, wait for now
return;
- if(txState.txQuiet < ticks) //quit time has elapsed
+ if(txQuiet < ticks) //quit time has elapsed
{
- if(!Afsk_dcdState()) //channel is free
+ if(!ModemDcdState()) //channel is free
{
- txState.tx = TX_INIT_TRANSMITTING; //transmit right now
- txState.txRetries = 0;
- ax25_transmitStart();
+ txInitStage = TX_INIT_TRANSMITTING; //transmit right now
+ txRetries = 0;
+ transmitStart();
}
else //channel is busy
{
- if(txState.txRetries == 8) //8th retry occurred, transmit immediately
+ if(txRetries == MAX_TRANSMIT_RETRY_COUNT) //timeout
{
- txState.tx = TX_INIT_TRANSMITTING; //transmit right now
- txState.txRetries = 0;
- ax25_transmitStart();
+ txInitStage = TX_INIT_TRANSMITTING; //transmit right now
+ txRetries = 0;
+ transmitStart();
}
else //still trying
{
- txState.txQuiet = ticks + rando(10, 50); //try again after some random time
- txState.txRetries++;
+ txQuiet = ticks + Random(100 / SYSTICK_INTERVAL, 500 / SYSTICK_INTERVAL); //try again after some random time
+ txRetries++;
}
}
}
}
-void Ax25_init(void)
+void Ax25Init(void)
{
- txState.crc = 0xFFFF;
- ax25.frameBufWr = 0;
- ax25.frameBufRd = 0;
- ax25.xmitIdx = 0;
- ax25.frameReceived = 0;
+ txCrc = 0xFFFF;
- rxState1.crc = 0xFFFF;
- rxState2.crc = 0xFFFF;
+ memset((void*)rxState, 0, sizeof(rxState));
+ for(uint8_t i = 0; i < (sizeof(rxState) / sizeof(rxState[0])); i++)
+ rxState[i].crc = 0xFFFF;
- txState.txDelay = ((float)ax25Cfg.txDelayLength / 6.66667f); //change milliseconds to byte count
- txState.txTail = ((float)ax25Cfg.txTailLength / 6.66667f);
+ txDelay = ((float)Ax25Config.txDelayLength / (8.f * 1000.f / (float)MODEM_BAUDRATE)); //change milliseconds to byte count
+ txTail = ((float)Ax25Config.txTailLength / (8.f * 1000.f / (float)MODEM_BAUDRATE));
}
diff --git a/Src/beacon.c b/Src/beacon.c
index 4587243..02ccf80 100644
--- a/Src/beacon.c
+++ b/Src/beacon.c
@@ -23,40 +23,40 @@ along with VP-Digi. If not, see .
#include "terminal.h"
#include "drivers/systick.h"
-uint32_t beaconDelay[8] = {0};
-
+struct Beacon beacon[8];
+static uint32_t beaconDelay[8] = {0};
+static uint8_t buf[150]; //frame buffer
/**
* @brief Send specified beacon
* @param[in] no Beacon number (0-7)
*/
-void Beacon_send(uint8_t no)
+void BeaconSend(uint8_t number)
{
- if(beacon[no].enable == 0)
+ if(beacon[number].enable == 0)
return; //beacon disabled
- uint8_t buf[150] = {0}; //frame buffer
uint16_t idx = 0;
- for(uint8_t i = 0; i < 7; i++) //add destination address
- buf[idx++] = dest[i];
+ for(uint8_t i = 0; i < sizeof(GeneralConfig.dest); i++) //add destination address
+ buf[idx++] = GeneralConfig.dest[i];
- for(uint8_t i = 0; i < 6; i++) //add source address
- buf[idx++] = call[i];
+ for(uint8_t i = 0; i < sizeof(GeneralConfig.call); i++) //add source address
+ buf[idx++] = GeneralConfig.call[i];
- buf[idx++] = ((callSsid << 1) + 0b01100000); //add source ssid
+ buf[idx++] = ((GeneralConfig.callSsid << 1) + 0b01100000); //add source ssid
- if(beacon[no].path[0] > 0) //this beacon has some path set
+ if(beacon[number].path[0] > 0) //this beacon has some path set
{
for(uint8_t i = 0; i < 14; i++) //loop through path
{
- if((beacon[no].path[i] > 0) || (i == 6) || (i == 13)) //normal data, not a NULL symbol
+ if((beacon[number].path[i] > 0) || (i == 6) || (i == 13)) //normal data, not a NULL symbol
{
- buf[idx] = (beacon[no].path[i] << 1); //copy path
+ buf[idx] = beacon[number].path[i]; //copy path
if((i == 6) || (i == 13)) //it was and ssid
{
- buf[idx] += 0b01100000; //add appripriate bits for ssid
+ buf[idx] = ((buf[idx] << 1) + 0b01100000); //add appropriate bits for ssid
}
idx++;
}
@@ -67,47 +67,35 @@ void Beacon_send(uint8_t no)
buf[idx - 1] |= 1; //add c-bit on the last element
buf[idx++] = 0x03; //control
buf[idx++] = 0xF0; //pid
- for(uint8_t i = 0; i < strlen((char*)beacon[no].data); i++)
+ for(uint8_t i = 0; i < strlen((char*)beacon[number].data); i++)
{
- buf[idx++] = beacon[no].data[i]; //copy beacon comment
+ buf[idx++] = beacon[number].data[i]; //copy beacon comment
}
- if((FRAMEBUFLEN - ax25.xmitIdx) > (idx + 2)) //check for free space in TX buffer
+ void *handle = NULL;
+ if(NULL != (handle = Ax25WriteTxFrame(buf, idx))) //try to write frame to TX buffer
{
- uint16_t frameStart = ax25.xmitIdx; //store index
-
- for(uint8_t i = 0; i < idx; i++)
- {
- ax25.frameXmit[ax25.xmitIdx++] = buf[i]; //copy frame to main TX buffer
- }
-
- if(kissMonitor) //monitoring mode, send own frames to KISS ports
+ if(GeneralConfig.kissMonitor) //monitoring mode, send own frames to KISS ports
{
- SendKiss(ax25.frameXmit, ax25.xmitIdx);
+ TermSendToAll(MODE_KISS, buf, idx);
}
- ax25.frameXmit[ax25.xmitIdx++] = 0xFF; //frame separator
- Digi_storeDeDupeFromXmitBuf(frameStart); //store frame hash in duplicate protection buffer (to prevent from digipeating own packets)
-
- uint8_t bufto[200];
- common_toTNC2((uint8_t *)&ax25.frameXmit[frameStart], ax25.xmitIdx - frameStart - 1, bufto);
+ DigiStoreDeDupe(buf, idx); //store frame hash in duplicate protection buffer (to prevent from digipeating own packets)
- term_sendMonitor((uint8_t*)"(AX.25) Transmitting beacon ", 0);
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"(AX.25) Transmitting beacon ", 0);
- term_sendMonitorNumber(no);
- term_sendMonitor((uint8_t*)": ", 0);
- term_sendMonitor(bufto, 0);
- term_sendMonitor((uint8_t*)"\r\n", 0);
+ TermSendNumberToAll(MODE_MONITOR, number);
+ TermSendToAll(MODE_MONITOR, (uint8_t*)": ", 0);
+ SendTNC2(buf, idx);
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"\r\n", 0);
}
-
-
}
/**
- * @brief Check if any beacon should be transmitted and transmit if neccessary
+ * @brief Check if any beacon should be transmitted and transmit if necessary
*/
-void Beacon_check(void)
+void BeaconCheck(void)
{
for(uint8_t i = 0; i < 8; i++)
{
@@ -120,7 +108,7 @@ void Beacon_check(void)
return;
beacon[i].next = ticks + beacon[i].interval; //save next beacon timestamp
beaconDelay[i] = 0;
- Beacon_send(i);
+ BeaconSend(i);
}
}
}
@@ -129,11 +117,11 @@ void Beacon_check(void)
/**
* @brief Initialize beacon module
*/
-void Beacon_init(void)
+void BeaconInit(void)
{
for(uint8_t i = 0; i < 8; i++)
{
- beaconDelay[i] = (beacon[i].delay * 100) + ticks + 3000; //set delay for beacons and add constant 30 seconds of delay
+ beaconDelay[i] = (beacon[i].delay * SYSTICK_FREQUENCY) + ticks + (30000 / SYSTICK_INTERVAL); //set delay for beacons and add constant 30 seconds of delay
beacon[i].next = 0;
}
}
diff --git a/Src/common.c b/Src/common.c
index cd12458..c7d075b 100644
--- a/Src/common.c
+++ b/Src/common.c
@@ -22,152 +22,148 @@ along with VP-Digi. If not, see .
#include "drivers/uart.h"
#include "usbd_cdc_if.h"
-uint8_t call[6] = {'N' << 1, '0' << 1, 'C' << 1, 'A' << 1, 'L' << 1, 'L' << 1};
-uint8_t callSsid = 0;
-
-uint8_t dest[7] = {130, 160, 156, 172, 96, 98, 96}; //destination address: APNV01-0 by default. SSID MUST remain 0.
-
-const uint8_t *versionString = (const uint8_t*)"VP-Digi v. 1.2.6\r\nThe open-source standalone APRS digipeater controller and KISS TNC\r\n";
+struct _GeneralConfig GeneralConfig =
+{
+ .call = {'N' << 1, '0' << 1, 'C' << 1, 'A' << 1, 'L' << 1, 'L' << 1},
+ .callSsid = 0,
+ .dest = {130, 160, 156, 172, 96, 98, 96}, //destination address: APNV01-0 by default. SSID MUST remain 0.
+ .kissMonitor = 0,
+};
-uint8_t autoReset = 0;
-uint32_t autoResetTimer = 0;
-uint8_t kissMonitor = 0;
+const char versionString[] = "VP-Digi v. 1.3.0\r\nThe open-source standalone APRS digipeater controller and KISS TNC\r\n";
+static uint64_t pow10i(uint16_t exp)
+{
+ if(exp == 0)
+ return 1;
+ uint64_t n = 1;
+ while(exp--)
+ n *= 10;
+ return n;
+}
-int64_t strToInt(uint8_t *str, uint8_t len)
+int64_t StrToInt(const char *str, uint16_t len)
{
if(len == 0)
+ len = strlen(str);
+
+ int64_t tmp = 0;
+ for(int32_t i = (len - 1); i >= 0; i--)
{
- while(1)
+ if((i == 0) && (str[0] == '-'))
{
- if(((str[len] > 47) && (str[len] < 58)))
- len++;
- else
- break;
- if(len >= 100)
- return 0;
+ return -tmp;
}
- }
- int64_t tmp = 0;
- for(int16_t i = (len - 1); i >= 0; i--)
- {
- if((i == 0) && (str[i] == '-'))
- tmp = -tmp;
+ else if(IS_NUMBER(str[i]))
+ tmp += ((str[i] - '0') * pow10i(len - 1 - i));
else
- tmp += ((str[i] - 48) * pow(10, len - 1 - i));
+ return 0;
}
return tmp;
}
-int16_t rando(int16_t min, int16_t max)
+int16_t Random(int16_t min, int16_t max)
{
int16_t tmp;
- if (max>=min)
- max-= min;
+ if (max >= min)
+ max -= min;
else
{
- tmp= min - max;
- min= max;
- max= tmp;
+ tmp = min - max;
+ min = max;
+ max = tmp;
}
return max ? (rand() % max + min) : min;
}
-
-
-void common_toTNC2(uint8_t *from, uint16_t len, uint8_t *to)
+static void sendTNC2ToUart(Uart *uart, uint8_t *from, uint16_t len)
{
-
for(uint8_t i = 0; i < 6; i++) //source call
{
- if((*(from + 7 + i) >> 1) != ' ') //skip spaces
+ if((from[7 + i] >> 1) != ' ') //skip spaces
{
- *(to++) = *(from + 7 + i) >> 1;
+ UartSendByte(uart, from[7 + i] >> 1);
}
}
- uint8_t ssid = ((*(from + 13) >> 1) & 0b00001111); //store ssid
+ uint8_t ssid = ((from[13] >> 1) & 0b00001111); //store ssid
if(ssid > 0) //SSID >0
{
- *(to++) = '-'; //add -
- if(ssid > 9)
- *(to++) = '1'; //ssid >9, so will be -1x
- *(to++) = (ssid % 10) + 48;
+ UartSendByte(uart, '-'); //add -
+ UartSendNumber(uart, ssid);
}
- *(to++) = '>'; //first separator
-
+ UartSendByte(uart, '>'); //first separator
for(uint8_t i = 0; i < 6; i++) //destination call
{
- if((*(from + i) >> 1) != ' ') //skip spaces
+ if((from[i] >> 1) != ' ') //skip spaces
{
- *(to++) = *(from + i) >> 1;
+ UartSendByte(uart, from[i] >> 1);
}
}
- ssid = ((*(from + 6) >> 1) & 0b00001111); //store ssid
+ ssid = ((from[6] >> 1) & 0b00001111); //store ssid
if(ssid > 0) //SSID >0
{
- *(to++) = '-'; //add -
- if(ssid > 9)
- *(to++) = '1'; //ssid >9, so will be -1x
- *(to++) = (ssid % 10) + 48;
+ UartSendByte(uart, '-'); //add -
+ UartSendNumber(uart, ssid);
}
uint16_t nextPathEl = 14; //next path element index
- if(!(*(from + 13) & 1)) //no c-bit in source address, there is a digi path
+ if(!(from[13] & 1)) //no c-bit in source address, there is a digi path
{
-
- do //analize all path elements
+ do //analyze all path elements
{
- *(to++) = ','; //path separator
+ UartSendByte(uart, ','); //path separator
for(uint8_t i = 0; i < 6; i++) //copy element
{
- if((*(from + nextPathEl + i) >> 1) != ' ') //skip spaces
+ if((from[nextPathEl + i] >> 1) != ' ') //skip spaces
{
- *(to++) = *(from + nextPathEl + i) >> 1;
+ UartSendByte(uart, from[nextPathEl + i] >> 1);
}
}
- ssid = ((*(from + nextPathEl + 6) >> 1) & 0b00001111); //store ssid
+ ssid = ((from[nextPathEl + 6] >> 1) & 0b00001111); //store ssid
if(ssid > 0) //SSID >0
{
- *(to++) = '-'; //add -
- if(ssid > 9)
- *(to++) = '1'; //ssid >9, so will be -1x
- *(to++) = (ssid % 10) + 48;
+ UartSendByte(uart, '-'); //add -
+ UartSendNumber(uart, ssid);
}
- if((*(from + nextPathEl + 6) & 128)) //h-bit in ssid
- *(to++) = '*'; //add *
+ if((from[nextPathEl + 6] & 0x80)) //h-bit in ssid
+ UartSendByte(uart, '*'); //add *
nextPathEl += 7; //next path element
if(nextPathEl > 56) //too many path elements
break;
}
- while((*(from + nextPathEl - 1) & 1) == 0); //loop until the c-bit is found
+ while((from[nextPathEl - 1] & 1) == 0); //loop until the c-bit is found
}
-
- *(to++) = ':'; //separator
+ UartSendByte(uart, ':'); //separator
nextPathEl += 2; //skip Control and PID
- for(; nextPathEl < len; nextPathEl++) //copy information field
- {
- *(to++) = *(from + nextPathEl);
- }
-
+ UartSendString(uart, &(from[nextPathEl]), len - nextPathEl); //send information field
- *(to++) = 0; //terminate with NULL
+ UartSendByte(uart, 0); //terminate with NULL
+}
+void SendTNC2(uint8_t *from, uint16_t len)
+{
+ if(UartUsb.mode == MODE_MONITOR)
+ sendTNC2ToUart(&UartUsb, from, len);
+ if(Uart1.mode == MODE_MONITOR)
+ sendTNC2ToUart(&Uart1, from, len);
+ if(Uart2.mode == MODE_MONITOR)
+ sendTNC2ToUart(&Uart2, from, len);
}
-uint32_t crc32(uint32_t crc0, uint8_t *s, uint64_t n)
+uint32_t Crc32(uint32_t crc0, uint8_t *s, uint64_t n)
{
uint32_t crc = ~crc0;
@@ -185,38 +181,67 @@ uint32_t crc32(uint32_t crc0, uint8_t *s, uint64_t n)
return ~crc;
}
-void SendKiss(uint8_t *buf, uint16_t len)
+bool ParseCallsign(const char *in, uint16_t size, uint8_t *out)
{
- Uart *u = &uart1;
+ if(size > 6)
+ return false;
- for(uint8_t i = 0; i < 2; i++)
+ uint8_t tmp[6];
+
+ uint8_t i = 0;
+ for(; i < size; i++)
+ {
+ if(!IS_UPPERCASE_ALPHANUMERIC(in[i]))
+ return false;
+
+ tmp[i] = in[i] << 1;
+ }
+
+ for(uint8_t k = 0; k < i; k++)
+ out[k] = tmp[k];
+
+ for(; i < 6; i++)
+ out[i] = ' ' << 1;
+
+
+ return true;
+}
+
+bool ParseCallsignWithSsid(const char *in, uint16_t size, uint8_t *out, uint8_t *ssid)
+{
+ uint16_t ssidPosition = size;
+ for(uint16_t i = 0; i < size; i++)
{
- if(u->mode == MODE_KISS) //check if KISS mode
+ if(in[i] == '-')
{
- uart_sendByte(u, 0xc0); //send data in kiss format
- uart_sendByte(u, 0x00);
- for(uint16_t j = 0; j < len; j++)
- {
- uart_sendByte(u, buf[j]);
- }
- uart_sendByte(u, 0xc0);
- uart_transmitStart(u);
+ ssidPosition = i;
+ break;
}
- u = &uart2;
}
+ ssidPosition++;
+ if(!ParseCallsign(in, ssidPosition - 1, out))
+ return false;
- if(USBmode == MODE_KISS) //check if USB in KISS mode
+ if(ssidPosition == size)
{
- uint8_t t[2] = {0xc0, 0};
-
- CDC_Transmit_FS(&t[0], 1);
- CDC_Transmit_FS(&t[1], 1);
+ *ssid = 0;
+ return true;
+ }
- for(uint16_t i = 0; i < len; i++)
- {
- CDC_Transmit_FS(&buf[i], 1);
+ if(!ParseSsid(&in[ssidPosition], size - ssidPosition, ssid))
+ return false;
+ return true;
+}
- }
- CDC_Transmit_FS(&t[0], 1);
+bool ParseSsid(const char *in, uint16_t size, uint8_t *out)
+{
+ int64_t ssid = StrToInt(in, size);
+ if((ssid >= 0) && (ssid <= 15))
+ {
+ *out = (uint8_t)ssid;
+ return true;
}
+ return false;
}
+
+
diff --git a/Src/config.c b/Src/config.c
index 7369740..c190440 100644
--- a/Src/config.c
+++ b/Src/config.c
@@ -1,5 +1,5 @@
/*
-This file is part of VP-Digi.
+This file is part of VP-DigiConfig.
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
@@ -12,7 +12,7 @@ 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 .
+along with VP-DigiConfig. If not, see .
*/
#include "config.h"
@@ -26,26 +26,94 @@ along with VP-Digi. If not, see .
#include "stm32f1xx.h"
#include "drivers/modem.h"
+#define CONFIG_ADDRESS 0x800F000
+#define CONFIG_PAGE_COUNT 2
+#define CONFIG_PAGE_SIZE 1024 //1024 words (2048 bytes)
+
+#define CONFIG_FLAG_WRITTEN 0x6B
+
+
+//these are relative addresses, absolute address is calculated as relative address + MEM_CONFIG
+//all fields are 16-bit or n*16-bit long, as data in flash is stored in 16-bit words
+#define CONFIG_FLAG 0 //configuration written flag
+#define CONFIG_CALL 2
+#define CONFIG_SSID 8
+#define CONFIG_TXDELAY 10
+#define CONFIG_TXTAIL 12
+#define CONFIG_TXQUIET 14
+#define CONFIG_RS1BAUD 16
+#define CONFIG_RS2BAUD 20
+#define CONFIG_BEACONS 24
+#define CONFIG_BCIV 26 //beacon intervals
+#define CONFIG_BCDL 42 //beacon delays
+#define CONFIG_BC0 58 //beacon information fields, null terminated
+#define CONFIG_BC1 158
+#define CONFIG_BC2 258
+#define CONFIG_BC3 358
+#define CONFIG_BC4 458
+#define CONFIG_BC5 558
+#define CONFIG_BC6 658
+#define CONFIG_BC7 758
+#define CONFIG_BCP0 858 //beacon paths, 14 bytes each
+#define CONFIG_BCP1 872
+#define CONFIG_BCP2 886
+#define CONFIG_BCP3 900
+#define CONFIG_BCP4 914
+#define CONFIG_BCP5 928
+#define CONFIG_BCP6 942
+#define CONFIG_BCP7 956
+#define CONFIG_DIGION 970
+#define CONFIG_DIGIEN 972
+#define CONFIG_DIGIVISC 974 //viscous-delay settings in higher half, direct-only in lower half
+#define CONFIG_DIGIAL0 976
+#define CONFIG_DIGIAL1 982
+#define CONFIG_DIGIAL2 988
+#define CONFIG_DIGIAL3 994
+#define CONFIG_DIGIAL4 1000
+#define CONFIG_DIGIAL5 1008
+#define CONFIG_DIGIAL6 1016
+#define CONFIG_DIGIAL7 1024
+#define CONFIG_DIGIMAX0 1032
+#define CONFIG_DIGIMAX1 1034
+#define CONFIG_DIGIMAX2 1036
+#define CONFIG_DIGIMAX3 1038
+#define CONFIG_DIGIREP0 1040
+#define CONFIG_DIGIREP1 1042
+#define CONFIG_DIGIREP2 1044
+#define CONFIG_DIGIREP3 1046
+#define CONFIG_DIGITRACE 1048
+#define CONFIG_DIGIDEDUPE 1050
+#define CONFIG_DIGICALLFILEN 1052
+#define CONFIG_DIGIFILLIST 1054
+#define CONFIG_DIGIFILTYPE 1194
+#define CONFIG_DIGISSID4 1196
+#define CONFIG_DIGISSID5 1198
+#define CONFIG_DIGISSID6 1200
+#define CONFIG_DIGISSID7 1202
+#define CONFIG_PWM_FLAT 1204
+#define CONFIG_KISSMONITOR 1206
+#define CONFIG_DEST 1208
+#define CONFIG_ALLOWNONAPRS 1214
+#define CONFIG_XXX 1216 //next address (not used)
+
+
/**
* @brief Write word to configuration part in flash
* @param[in] address Relative address
* @param[in] data Data to write
* @warning Flash must be unlocked first
*/
-static void flash_write(uint32_t address, uint16_t data)
+static void write(uint32_t address, uint16_t data)
{
FLASH->CR |= FLASH_CR_PG; //programming mode
- *(volatile uint16_t*)((address + MEM_CONFIG)) = data; //store data
+ *((volatile uint16_t*)(address + CONFIG_ADDRESS)) = data; //store data
- while (FLASH->SR & FLASH_SR_BSY);; //wait for ceompletion
+ while (FLASH->SR & FLASH_SR_BSY);; //wait for completion
if(!(FLASH->SR & FLASH_SR_EOP)) //an error occurred
- {
FLASH->CR &= ~FLASH_CR_PG;
- return;
- } else FLASH->SR |= FLASH_SR_EOP;
-
- //FLASH->CR &= ~FLASH_CR_PG;
+ else
+ FLASH->SR |= FLASH_SR_EOP;
}
/**
@@ -55,16 +123,16 @@ static void flash_write(uint32_t address, uint16_t data)
* @param[in] len Data length
* @warning Flash must be unlocked first
*/
-static void flash_writeString(uint32_t address, uint8_t *data, uint16_t len)
+static void writeString(uint32_t address, uint8_t *data, uint16_t len)
{
uint16_t i = 0;
- for(; i < (len >> 1); i++)
+ for(; i < (len / 2); i++)
{
- flash_write(address + (i << 1), *(data + (i << 1)) | (*(data + 1 + (i << 1)) << 8)); //program memory
+ write(address + (i << 1), *(data + (i << 1)) | (*(data + 1 + (i << 1)) << 8)); //program memory
}
if((len % 2) > 0)
{
- flash_write(address + (i << 1), *(data + (i << 1))); //store last byte if number of bytes is odd
+ write(address + (i << 1), *(data + (i << 1))); //store last byte if number of bytes is odd
}
}
@@ -73,9 +141,9 @@ static void flash_writeString(uint32_t address, uint8_t *data, uint16_t len)
* @param[in] address Relative address
* @return Data (word)
*/
-static uint16_t flash_read(uint32_t address)
+static uint16_t read(uint32_t address)
{
- return *(volatile uint16_t*)((address + MEM_CONFIG));
+ return *(volatile uint16_t*)((address + CONFIG_ADDRESS));
}
/**
@@ -84,37 +152,40 @@ static uint16_t flash_read(uint32_t address)
* @param[out] *data Data
* @param[in] len Byte count
*/
-static void flash_readString(uint32_t address, uint8_t *data, uint16_t len)
+static void readString(uint32_t address, uint8_t *data, uint16_t len)
{
uint16_t i = 0;
for(; i < (len >> 1); i++)
{
- *(data + (i << 1)) = (uint8_t)flash_read(address + (i << 1));
- *(data + 1 + (i << 1)) = (uint8_t)flash_read(address + 1 + (i << 1));
+ *(data + (i << 1)) = (uint8_t)read(address + (i << 1));
+ *(data + 1 + (i << 1)) = (uint8_t)read(address + 1 + (i << 1));
}
if((len % 2) > 0)
{
- *(data + (i << 1)) = (uint8_t)flash_read(address + (i << 1));
+ *(data + (i << 1)) = (uint8_t)read(address + (i << 1));
}
}
-void Config_erase(void)
+void ConfigErase(void)
{
FLASH->KEYR = 0x45670123; //unlock memory
FLASH->KEYR = 0xCDEF89AB;
- while (FLASH->SR & FLASH_SR_BSY);;
+ while (FLASH->SR & FLASH_SR_BSY)
+ ;
FLASH->CR |= FLASH_CR_PER; //erase mode
- for(uint8_t i = 0; i < 2; i++)
+ for(uint8_t i = 0; i < CONFIG_PAGE_COUNT; i++)
{
- FLASH->AR = (MEM_CONFIG) + (1024 * i);
+ FLASH->AR = CONFIG_ADDRESS + (CONFIG_PAGE_SIZE * i);
FLASH->CR |= FLASH_CR_STRT; //start erase
- while (FLASH->SR & FLASH_SR_BSY);;
+ while (FLASH->SR & FLASH_SR_BSY)
+ ;
if(!(FLASH->SR & FLASH_SR_EOP))
{
FLASH->CR &= ~FLASH_CR_PER;
-
return;
- } else FLASH->SR |= FLASH_SR_EOP;
+ }
+ else
+ FLASH->SR |= FLASH_SR_EOP;
}
FLASH->CR &= ~FLASH_CR_PER;
}
@@ -122,106 +193,103 @@ void Config_erase(void)
/**
* @brief Store configuration from RAM to Flash
*/
-void Config_write(void)
+void ConfigWrite(void)
{
- Config_erase();
+ ConfigErase();
- flash_writeString(CONFIG_CALL, call, 6);
- flash_write(CONFIG_SSID, callSsid);
- flash_writeString(CONFIG_DEST, dest, 6);
- flash_write(CONFIG_TXDELAY, ax25Cfg.txDelayLength);
- flash_write(CONFIG_TXTAIL, ax25Cfg.txTailLength);
- flash_write(CONFIG_TXQUIET, ax25Cfg.quietTime);
- flash_writeString(CONFIG_RS1BAUD, (uint8_t*)&uart1.baudrate, 3);
- flash_writeString(CONFIG_RS2BAUD, (uint8_t*)&uart2.baudrate, 3);
+ writeString(CONFIG_CALL, GeneralConfig.call, sizeof(GeneralConfig.call));
+ write(CONFIG_SSID, GeneralConfig.callSsid);
+ writeString(CONFIG_DEST, GeneralConfig.dest, sizeof(GeneralConfig.dest));
+ write(CONFIG_TXDELAY, Ax25Config.txDelayLength);
+ write(CONFIG_TXTAIL, Ax25Config.txTailLength);
+ write(CONFIG_TXQUIET, Ax25Config.quietTime);
+ writeString(CONFIG_RS1BAUD, (uint8_t*)&Uart1.baudrate, 4);
+ writeString(CONFIG_RS2BAUD, (uint8_t*)&Uart2.baudrate, 4);
- flash_write(CONFIG_BEACONS, (beacon[0].enable > 0) | ((beacon[1].enable > 0) << 1) | ((beacon[2].enable > 0) << 2) | ((beacon[3].enable > 0) << 3) | ((beacon[4].enable > 0) << 4) | ((beacon[5].enable > 0) << 5) | ((beacon[6].enable > 0) << 6) | ((beacon[7].enable > 0) << 7));
+ write(CONFIG_BEACONS, (beacon[0].enable > 0) | ((beacon[1].enable > 0) << 1) | ((beacon[2].enable > 0) << 2) | ((beacon[3].enable > 0) << 3) | ((beacon[4].enable > 0) << 4) | ((beacon[5].enable > 0) << 5) | ((beacon[6].enable > 0) << 6) | ((beacon[7].enable > 0) << 7));
for(uint8_t s = 0; s < 8; s++)
{
- flash_write(CONFIG_BCIV + (2 * s), beacon[s].interval / 6000);
+ write(CONFIG_BCIV + (2 * s), beacon[s].interval / 6000);
}
for(uint8_t s = 0; s < 8; s++)
{
- flash_write(CONFIG_BCDL + (2 * s), beacon[s].delay / 60);
+ write(CONFIG_BCDL + (2 * s), beacon[s].delay / 60);
}
- flash_writeString(CONFIG_BC0, beacon[0].data, 100);
- flash_writeString(CONFIG_BC1, beacon[1].data, 100);
- flash_writeString(CONFIG_BC2, beacon[2].data, 100);
- flash_writeString(CONFIG_BC3, beacon[3].data, 100);
- flash_writeString(CONFIG_BC4, beacon[4].data, 100);
- flash_writeString(CONFIG_BC5, beacon[5].data, 100);
- flash_writeString(CONFIG_BC6, beacon[6].data, 100);
- flash_writeString(CONFIG_BC7, beacon[7].data, 100);
- flash_writeString(CONFIG_BCP0, beacon[0].path, 14);
- flash_writeString(CONFIG_BCP1, beacon[1].path, 14);
- flash_writeString(CONFIG_BCP2, beacon[2].path, 14);
- flash_writeString(CONFIG_BCP3, beacon[3].path, 14);
- flash_writeString(CONFIG_BCP4, beacon[4].path, 14);
- flash_writeString(CONFIG_BCP5, beacon[5].path, 14);
- flash_writeString(CONFIG_BCP6, beacon[6].path, 14);
- flash_writeString(CONFIG_BCP7, beacon[7].path, 14);
- flash_write(CONFIG_DIGION, digi.enable);
- flash_write(CONFIG_DIGIEN, digi.enableAlias);
- flash_write(CONFIG_DIGIVISC, ((uint16_t)digi.viscous << 8) | (uint16_t)digi.directOnly);
- flash_writeString(CONFIG_DIGIAL0, digi.alias[0], 5);
- flash_writeString(CONFIG_DIGIAL1, digi.alias[1], 5);
- flash_writeString(CONFIG_DIGIAL2, digi.alias[2], 5);
- flash_writeString(CONFIG_DIGIAL3, digi.alias[3], 5);
- flash_writeString(CONFIG_DIGIAL4, digi.alias[4], 6);
- flash_writeString(CONFIG_DIGIAL5, digi.alias[5], 6);
- flash_writeString(CONFIG_DIGIAL6, digi.alias[6], 6);
- flash_writeString(CONFIG_DIGIAL7, digi.alias[7], 6);
- flash_write(CONFIG_DIGISSID4, digi.ssid[0]);
- flash_write(CONFIG_DIGISSID5, digi.ssid[1]);
- flash_write(CONFIG_DIGISSID6, digi.ssid[2]);
- flash_write(CONFIG_DIGISSID7, digi.ssid[3]);
- flash_write(CONFIG_DIGIMAX0, digi.max[0]);
- flash_write(CONFIG_DIGIMAX1, digi.max[1]);
- flash_write(CONFIG_DIGIMAX2, digi.max[2]);
- flash_write(CONFIG_DIGIMAX3, digi.max[3]);
- flash_write(CONFIG_DIGIREP0, digi.rep[0]);
- flash_write(CONFIG_DIGIREP1, digi.rep[1]);
- flash_write(CONFIG_DIGIREP2, digi.rep[2]);
- flash_write(CONFIG_DIGIREP3, digi.rep[3]);
- flash_write(CONFIG_DIGITRACE, digi.traced);
- flash_write(CONFIG_DIGIDEDUPE, digi.dupeTime);
- flash_write(CONFIG_DIGICALLFILEN, digi.callFilterEnable);
- flash_write(CONFIG_DIGIFILTYPE, digi.filterPolarity);
- flash_writeString(CONFIG_DIGIFILLIST, digi.callFilter[0], 140);
- flash_write(CONFIG_AUTORST, autoReset);
- flash_write(CONFIG_PWM_FLAT, afskCfg.usePWM | (afskCfg.flatAudioIn << 1));
- flash_write(CONFIG_KISSMONITOR, kissMonitor);
- flash_write(CONFIG_ALLOWNONAPRS, ax25Cfg.allowNonAprs);
+ writeString(CONFIG_BC0, beacon[0].data, 100);
+ writeString(CONFIG_BC1, beacon[1].data, 100);
+ writeString(CONFIG_BC2, beacon[2].data, 100);
+ writeString(CONFIG_BC3, beacon[3].data, 100);
+ writeString(CONFIG_BC4, beacon[4].data, 100);
+ writeString(CONFIG_BC5, beacon[5].data, 100);
+ writeString(CONFIG_BC6, beacon[6].data, 100);
+ writeString(CONFIG_BC7, beacon[7].data, 100);
+ writeString(CONFIG_BCP0, beacon[0].path, 14);
+ writeString(CONFIG_BCP1, beacon[1].path, 14);
+ writeString(CONFIG_BCP2, beacon[2].path, 14);
+ writeString(CONFIG_BCP3, beacon[3].path, 14);
+ writeString(CONFIG_BCP4, beacon[4].path, 14);
+ writeString(CONFIG_BCP5, beacon[5].path, 14);
+ writeString(CONFIG_BCP6, beacon[6].path, 14);
+ writeString(CONFIG_BCP7, beacon[7].path, 14);
+ write(CONFIG_DIGION, DigiConfig.enable);
+ write(CONFIG_DIGIEN, DigiConfig.enableAlias);
+ write(CONFIG_DIGIVISC, ((uint16_t)DigiConfig.viscous << 8) | (uint16_t)DigiConfig.directOnly);
+ writeString(CONFIG_DIGIAL0, DigiConfig.alias[0], 5);
+ writeString(CONFIG_DIGIAL1, DigiConfig.alias[1], 5);
+ writeString(CONFIG_DIGIAL2, DigiConfig.alias[2], 5);
+ writeString(CONFIG_DIGIAL3, DigiConfig.alias[3], 5);
+ writeString(CONFIG_DIGIAL4, DigiConfig.alias[4], 6);
+ writeString(CONFIG_DIGIAL5, DigiConfig.alias[5], 6);
+ writeString(CONFIG_DIGIAL6, DigiConfig.alias[6], 6);
+ writeString(CONFIG_DIGIAL7, DigiConfig.alias[7], 6);
+ write(CONFIG_DIGISSID4, DigiConfig.ssid[0]);
+ write(CONFIG_DIGISSID5, DigiConfig.ssid[1]);
+ write(CONFIG_DIGISSID6, DigiConfig.ssid[2]);
+ write(CONFIG_DIGISSID7, DigiConfig.ssid[3]);
+ write(CONFIG_DIGIMAX0, DigiConfig.max[0]);
+ write(CONFIG_DIGIMAX1, DigiConfig.max[1]);
+ write(CONFIG_DIGIMAX2, DigiConfig.max[2]);
+ write(CONFIG_DIGIMAX3, DigiConfig.max[3]);
+ write(CONFIG_DIGIREP0, DigiConfig.rep[0]);
+ write(CONFIG_DIGIREP1, DigiConfig.rep[1]);
+ write(CONFIG_DIGIREP2, DigiConfig.rep[2]);
+ write(CONFIG_DIGIREP3, DigiConfig.rep[3]);
+ write(CONFIG_DIGITRACE, DigiConfig.traced);
+ write(CONFIG_DIGIDEDUPE, DigiConfig.dupeTime);
+ write(CONFIG_DIGICALLFILEN, DigiConfig.callFilterEnable);
+ write(CONFIG_DIGIFILTYPE, DigiConfig.filterPolarity);
+ writeString(CONFIG_DIGIFILLIST, DigiConfig.callFilter[0], sizeof(DigiConfig.callFilter));
+ write(CONFIG_PWM_FLAT, ModemConfig.usePWM | (ModemConfig.flatAudioIn << 1));
+ write(CONFIG_KISSMONITOR, GeneralConfig.kissMonitor);
+ write(CONFIG_ALLOWNONAPRS, Ax25Config.allowNonAprs);
- flash_write(CONFIG_FLAG, FLAG_CONFIG_WRITTEN);
+ write(CONFIG_FLAG, CONFIG_FLAG_WRITTEN);
FLASH->CR &= ~FLASH_CR_PG;
FLASH->CR |= FLASH_CR_LOCK;
}
-uint8_t Config_read(void)
+uint8_t ConfigRead(void)
{
- if(flash_read(CONFIG_FLAG) != FLAG_CONFIG_WRITTEN) //no configuration stored
+ if(read(CONFIG_FLAG) != CONFIG_FLAG_WRITTEN) //no configuration stored
{
return 0;
}
- flash_readString(CONFIG_CALL, call, 6);
- callSsid = (uint8_t)flash_read(CONFIG_SSID);
+ readString(CONFIG_CALL, GeneralConfig.call, sizeof(GeneralConfig.call));
+ GeneralConfig.callSsid = (uint8_t)read(CONFIG_SSID);
uint8_t temp[6];
- flash_readString(CONFIG_DEST, temp, 6);
+ readString(CONFIG_DEST, temp, sizeof(temp));
if((temp[0] >= ('A' << 1)) && (temp[0] <= ('Z' << 1)) && ((temp[0] & 1) == 0)) //check if stored destination address is correct (we just assume it by reading the first byte)
{
- memcpy(dest, temp, sizeof(uint8_t) * 6);
+ memcpy(GeneralConfig.dest, temp, sizeof(temp));
}
- ax25Cfg.txDelayLength = flash_read(CONFIG_TXDELAY);
- ax25Cfg.txTailLength = flash_read(CONFIG_TXTAIL);
- ax25Cfg.quietTime = flash_read(CONFIG_TXQUIET);
- uart1.baudrate = 0;
- uart2.baudrate = 0;
- flash_readString(CONFIG_RS1BAUD, (uint8_t*)&uart1.baudrate, 3);
- flash_readString(CONFIG_RS2BAUD, (uint8_t*)&uart2.baudrate, 3);
- uint8_t bce = (uint8_t)flash_read(CONFIG_BEACONS);
+ Ax25Config.txDelayLength = read(CONFIG_TXDELAY);
+ Ax25Config.txTailLength = read(CONFIG_TXTAIL);
+ Ax25Config.quietTime = read(CONFIG_TXQUIET);
+ readString(CONFIG_RS1BAUD, (uint8_t*)&Uart1.baudrate, 4);
+ readString(CONFIG_RS2BAUD, (uint8_t*)&Uart2.baudrate, 4);
+ uint8_t bce = (uint8_t)read(CONFIG_BEACONS);
beacon[0].enable = (bce & 1) > 0;
beacon[1].enable = (bce & 2) > 0;
beacon[2].enable = (bce & 4) > 0;
@@ -230,59 +298,58 @@ uint8_t Config_read(void)
beacon[5].enable = (bce & 32) > 0;
beacon[6].enable = (bce & 64) > 0;
beacon[7].enable = (bce & 128) > 0;
- for(uint8_t s = 0; s < 8; s++)
+ for(uint8_t s = 0; s < (sizeof(beacon) / sizeof(*beacon)); s++)
{
- beacon[s].interval = flash_read(CONFIG_BCIV + (2 * s)) * 6000;
+ beacon[s].interval = read(CONFIG_BCIV + (2 * s)) * 6000;
}
- for(uint8_t s = 0; s < 8; s++)
+ for(uint8_t s = 0; s < (sizeof(beacon) / sizeof(*beacon)); s++)
{
- beacon[s].delay = flash_read(CONFIG_BCDL + (2 * s)) * 60;
+ beacon[s].delay = read(CONFIG_BCDL + (2 * s)) * 60;
}
- for(uint8_t g = 0; g < 8; g++)
+ for(uint8_t g = 0; g < (sizeof(beacon) / sizeof(*beacon)); g++)
{
- flash_readString(CONFIG_BC0 + (g * 100), beacon[g].data, 100);
+ readString(CONFIG_BC0 + (g * 100), beacon[g].data, 100);
}
- for(uint8_t g = 0; g < 8; g++)
+ for(uint8_t g = 0; g < (sizeof(beacon) / sizeof(*beacon)); g++)
{
- flash_readString(CONFIG_BCP0 + (g * 14), beacon[g].path, 14);
+ readString(CONFIG_BCP0 + (g * 14), beacon[g].path, 14);
}
- digi.enable = (uint8_t)flash_read(CONFIG_DIGION);
- digi.enableAlias = (uint8_t)flash_read(CONFIG_DIGIEN);
- uint16_t t = flash_read(CONFIG_DIGIVISC);
- digi.viscous = (t & 0xFF00) >> 8;
- digi.directOnly = t & 0xFF;
- flash_readString(CONFIG_DIGIAL0, digi.alias[0], 5);
- flash_readString(CONFIG_DIGIAL1, digi.alias[1], 5);
- flash_readString(CONFIG_DIGIAL2, digi.alias[2], 5);
- flash_readString(CONFIG_DIGIAL3, digi.alias[3], 5);
- flash_readString(CONFIG_DIGIAL4, digi.alias[4], 6);
- flash_readString(CONFIG_DIGIAL5, digi.alias[5], 6);
- flash_readString(CONFIG_DIGIAL6, digi.alias[6], 6);
- flash_readString(CONFIG_DIGIAL7, digi.alias[7], 6);
- digi.ssid[0] = (uint8_t)flash_read(CONFIG_DIGISSID4);
- digi.ssid[1] = (uint8_t)flash_read(CONFIG_DIGISSID5);
- digi.ssid[2] = (uint8_t)flash_read(CONFIG_DIGISSID6);
- digi.ssid[3] = (uint8_t)flash_read(CONFIG_DIGISSID7);
- digi.max[0] = (uint8_t)flash_read(CONFIG_DIGIMAX0);
- digi.max[1] = (uint8_t)flash_read(CONFIG_DIGIMAX1);
- digi.max[2] = (uint8_t)flash_read(CONFIG_DIGIMAX2);
- digi.max[3] = (uint8_t)flash_read(CONFIG_DIGIMAX3);
- digi.rep[0] = (uint8_t)flash_read(CONFIG_DIGIREP0);
- digi.rep[1] = (uint8_t)flash_read(CONFIG_DIGIREP1);
- digi.rep[2] = (uint8_t)flash_read(CONFIG_DIGIREP2);
- digi.rep[3] = (uint8_t)flash_read(CONFIG_DIGIREP3);
- digi.traced = (uint8_t)flash_read(CONFIG_DIGITRACE);
- digi.dupeTime = (uint8_t)flash_read(CONFIG_DIGIDEDUPE);
- digi.callFilterEnable = (uint8_t)flash_read(CONFIG_DIGICALLFILEN);
- digi.filterPolarity = (uint8_t)flash_read(CONFIG_DIGIFILTYPE);
- flash_readString(CONFIG_DIGIFILLIST, digi.callFilter[0], 140);
- autoReset = (uint8_t)flash_read(CONFIG_AUTORST);
- t = (uint8_t)flash_read(CONFIG_PWM_FLAT);
- afskCfg.usePWM = t & 1;
- afskCfg.flatAudioIn = (t & 2) > 0;
- kissMonitor = (flash_read(CONFIG_KISSMONITOR) == 1);
- ax25Cfg.allowNonAprs = (flash_read(CONFIG_ALLOWNONAPRS) == 1);
+ DigiConfig.enable = (uint8_t)read(CONFIG_DIGION);
+ DigiConfig.enableAlias = (uint8_t)read(CONFIG_DIGIEN);
+ uint16_t t = read(CONFIG_DIGIVISC);
+ DigiConfig.viscous = (t & 0xFF00) >> 8;
+ DigiConfig.directOnly = t & 0xFF;
+ readString(CONFIG_DIGIAL0, DigiConfig.alias[0], 5);
+ readString(CONFIG_DIGIAL1, DigiConfig.alias[1], 5);
+ readString(CONFIG_DIGIAL2, DigiConfig.alias[2], 5);
+ readString(CONFIG_DIGIAL3, DigiConfig.alias[3], 5);
+ readString(CONFIG_DIGIAL4, DigiConfig.alias[4], 6);
+ readString(CONFIG_DIGIAL5, DigiConfig.alias[5], 6);
+ readString(CONFIG_DIGIAL6, DigiConfig.alias[6], 6);
+ readString(CONFIG_DIGIAL7, DigiConfig.alias[7], 6);
+ DigiConfig.ssid[0] = (uint8_t)read(CONFIG_DIGISSID4);
+ DigiConfig.ssid[1] = (uint8_t)read(CONFIG_DIGISSID5);
+ DigiConfig.ssid[2] = (uint8_t)read(CONFIG_DIGISSID6);
+ DigiConfig.ssid[3] = (uint8_t)read(CONFIG_DIGISSID7);
+ DigiConfig.max[0] = (uint8_t)read(CONFIG_DIGIMAX0);
+ DigiConfig.max[1] = (uint8_t)read(CONFIG_DIGIMAX1);
+ DigiConfig.max[2] = (uint8_t)read(CONFIG_DIGIMAX2);
+ DigiConfig.max[3] = (uint8_t)read(CONFIG_DIGIMAX3);
+ DigiConfig.rep[0] = (uint8_t)read(CONFIG_DIGIREP0);
+ DigiConfig.rep[1] = (uint8_t)read(CONFIG_DIGIREP1);
+ DigiConfig.rep[2] = (uint8_t)read(CONFIG_DIGIREP2);
+ DigiConfig.rep[3] = (uint8_t)read(CONFIG_DIGIREP3);
+ DigiConfig.traced = (uint8_t)read(CONFIG_DIGITRACE);
+ DigiConfig.dupeTime = (uint8_t)read(CONFIG_DIGIDEDUPE);
+ DigiConfig.callFilterEnable = (uint8_t)read(CONFIG_DIGICALLFILEN);
+ DigiConfig.filterPolarity = (uint8_t)read(CONFIG_DIGIFILTYPE);
+ readString(CONFIG_DIGIFILLIST, DigiConfig.callFilter[0], 140);
+ t = (uint8_t)read(CONFIG_PWM_FLAT);
+ ModemConfig.usePWM = t & 1;
+ ModemConfig.flatAudioIn = (t & 2) > 0;
+ GeneralConfig.kissMonitor = (read(CONFIG_KISSMONITOR) == 1);
+ Ax25Config.allowNonAprs = (read(CONFIG_ALLOWNONAPRS) == 1);
return 1;
}
diff --git a/Src/digipeater.c b/Src/digipeater.c
index 55552e2..15f9ee5 100644
--- a/Src/digipeater.c
+++ b/Src/digipeater.c
@@ -1,5 +1,5 @@
/*
-This file is part of VP-Digi.
+This file is part of VP-DigiConfig.
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
@@ -12,7 +12,7 @@ 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 .
+along with VP-DigiConfig. If not, see .
*/
#include "digipeater.h"
@@ -24,31 +24,51 @@ along with VP-Digi. If not, see .
#include
#include "drivers/systick.h"
-#define VISCOUS_DATA_LEN (6) //max frames in viscous-delay buffer
-uint8_t viscousBuf[VISCOUS_DATA_LEN][FRAMELEN]; //viscous-delay frames buffer
-uint32_t viscousData[VISCOUS_DATA_LEN][2]; //viscous-delay hash and timestamp buffer
-#define VISCOUS_HOLD_TIME 500 //viscous-delay hold time in 10 ms units
+struct _DigiConfig DigiConfig;
+#define VISCOUS_MAX_FRAME_COUNT 20 //max frames in viscous-delay buffer
+#define VISCOUS_MAX_FRAME_SIZE 150
-#define DEDUPE_LEN (40) //duplicate protection buffer size (number of hashes)
-uint32_t deDupeBuf[DEDUPE_LEN][2]; //duplicate protection hash buffer
-uint8_t deDupeIndex = 0; //duplicate protection buffer index
+struct ViscousData
+{
+ uint32_t hash;
+ uint32_t timeLimit;
+ uint8_t *frame;
+ uint16_t size;
+};
+static struct ViscousData viscous[VISCOUS_MAX_FRAME_COUNT];
+#define VISCOUS_HOLD_TIME 5000 //viscous-delay hold time in ms
+
+struct DeDupeData
+{
+ uint32_t hash;
+ uint32_t timeLimit;
+};
+
+#define DEDUPE_SIZE (40) //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
+static uint8_t buf[DIGI_BUFFER_SIZE];
+
/**
- * @brief Check if frame with specified hash is alread in viscous-delay buffer and delete it if so
+ * @brief Check if frame with specified hash is already in viscous-delay buffer and delete it if so
* @param[in] hash Frame hash
* @return 0 if not in buffer, 1 if in buffer
*/
-static uint8_t digi_viscousCheckAndRemove(uint32_t hash)
+static uint8_t viscousCheckAndRemove(uint32_t hash)
{
- for(uint8_t i = 0; i < VISCOUS_DATA_LEN; i++)
+ for(uint8_t i = 0; i < VISCOUS_MAX_FRAME_COUNT; i++)
{
- if(viscousData[i][0] == hash) //matching hash
+ if(viscous[i].hash == hash) //matching hash
{
- viscousData[i][0] = 0; //clear slot
- viscousData[i][1] = 0;
- term_sendMonitor((uint8_t*)"Digipeated frame received, dropping old frame from viscous-delay buffer\r\n", 0);
+ 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);
return 1;
}
}
@@ -57,102 +77,89 @@ static uint8_t digi_viscousCheckAndRemove(uint32_t hash)
-void Digi_viscousRefresh(void)
+void DigiViscousRefresh(void)
{
- if(digi.viscous == 0) //viscous-digipeating disabled on every alias
+ if(DigiConfig.viscous == 0) //viscous digipeating disabled on every alias
{
return;
}
- for(uint8_t i = 0; i < VISCOUS_DATA_LEN; i++)
+ for(uint8_t i = 0; i < VISCOUS_MAX_FRAME_COUNT; i++)
{
- if((viscousData[i][0] > 0) && ((ticks - viscousData[i][1]) > VISCOUS_HOLD_TIME)) //it's time to transmit this frame
+ if((viscous[i].timeLimit > 0) && (ticks >= viscous[i].timeLimit)) //it's time to transmit this frame
{
- uint8_t len = strlen((char*)viscousBuf[i]);
- if((len + 2) > (FRAMEBUFLEN - ax25.xmitIdx)) //frame won't fit in tx buffer
- {
- return;
- }
-
- uint16_t begin = ax25.xmitIdx;
-
- for(uint8_t j = 0; j < len; j++) //copy frame to tx buffer
+ void *handle = NULL;
+ if(NULL != (handle = Ax25WriteTxFrame(viscous[i].frame, viscous[i].size)))
{
- ax25.frameXmit[ax25.xmitIdx] = viscousBuf[i][j];
- ax25.xmitIdx++;
+ if(GeneralConfig.kissMonitor) //monitoring mode, send own frames to KISS ports
+ {
+ TermSendToAll(MODE_KISS, viscous[i].frame, viscous[i].size);
+ }
+
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"(AX.25) Transmitting viscous-delayed frame: ", 0);
+ SendTNC2(viscous[i].frame, viscous[i].size);
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"\r\n", 0);
}
- ax25.frameXmit[ax25.xmitIdx] = 0xFF;
- ax25.xmitIdx++;
- if(kissMonitor) //monitoring mode, send own frames to KISS ports
- {
- SendKiss(ax25.frameXmit, ax25.xmitIdx - 1);
- }
-
- uint8_t buf[200];
- common_toTNC2((uint8_t*)&ax25.frameXmit[begin], ax25.xmitIdx - begin - 1, buf);
-
- term_sendMonitor((uint8_t*)"(AX.25) Transmitting viscous-delayed frame: ", 0);
- term_sendMonitor(buf, 0);
- term_sendMonitor((uint8_t*)"\r\n", 0);
-
- viscousData[i][0] = 0;
- viscousData[i][1] = 0;
+ viscous[i].hash = 0; //clear slot
+ viscous[i].timeLimit = 0;
+ free(viscous[i].frame);
+ viscous[i].size = 0;
}
}
}
/**
* @brief Compare callsign with specified call in call filter table - helper function.
- * @param[in] *call Callsign
- * @param[in] no Callsign filter table index
- * @return 0 if matched with call filter, 1 if not
+ * @param *call Callsign
+ * @param index Callsign filter table index
+ * @return 1 if matched, 0 otherwise
*/
-static uint8_t compareFilterCall(uint8_t *call, uint8_t no)
+static uint8_t compareFilterCall(uint8_t *call, uint8_t index)
{
uint8_t err = 0;
for(uint8_t i = 0; i < 6; i++)
{
- if((digi.callFilter[no][i] < 0xff) && ((call[i] >> 1) != digi.callFilter[no][i]))
+ if((DigiConfig.callFilter[index][i] < 0xff) && ((call[i] >> 1) != DigiConfig.callFilter[index][i]))
err = 1;
}
- if((digi.callFilter[no][6] < 0xff) && ((call[6] - 96) != digi.callFilter[no][6])) //special case for ssid
+ if((DigiConfig.callFilter[index][6] < 0xff) && ((call[6] - 96) != DigiConfig.callFilter[index][6])) //special case for ssid
err = 1;
- return err;
+
+ return (err == 0);
}
/**
* @brief Check frame with call filter
* @param[in] *call Callsign in incoming frame
* @param[in] alias Digi alias index currently used
- * @return 0 if accepted, 1 if rejected
+ * @return 1 if accepted, 0 if rejected
*/
static uint8_t filterFrameCheck(uint8_t *call, uint8_t alias)
{
-
//filter by call
- if((digi.callFilterEnable >> alias) & 1) //check if enabled
+ if((DigiConfig.callFilterEnable >> alias) & 1) //check if enabled
{
- for(uint8_t i = 0; i < 20; i++)
+ for(uint8_t i = 0; i < (sizeof(DigiConfig.callFilter) / sizeof(DigiConfig.callFilter[0])); i++)
{
- if(!compareFilterCall(call, i)) //if callsigns match...
+ if(compareFilterCall(call, i)) //if callsigns match...
{
- if((digi.filterPolarity) == 0)
- return 1; //...and blacklist is enabled, drop the frame
+ if(DigiConfig.filterPolarity == 0)
+ return 0; //...and blacklist is enabled, drop the frame
else
- return 0; //...and whitelist is enabled, accept the frame
+ return 1; //...and whitelist is enabled, accept the frame
}
}
//if callsign is not on the list...
- if((digi.filterPolarity) == 0)
- return 0; //...and blacklist is enabled, accept the frame
+ if((DigiConfig.filterPolarity) == 0)
+ return 1; //...and blacklist is enabled, accept the frame
else
- return 1; //...and whitelist is enabled, drop the frame
+ return 0; //...and whitelist is enabled, drop the frame
}
//filter by call disabled
- return 0;
+ return 1;
}
@@ -168,38 +175,43 @@ static uint8_t filterFrameCheck(uint8_t *call, uint8_t alias)
*/
static void makeFrame(uint8_t *frame, uint16_t elStart, uint16_t len, uint32_t hash, uint8_t alias, uint8_t simple, uint8_t n)
{
- uint8_t *buf;
- uint16_t bufidx = 0;
+ uint16_t _index = 0; //underlying index for buffer if not in viscous-delay mode
+ uint8_t *buffer; //buffer to store frame being prepared
+ uint16_t *index = &_index; //index in buffer
uint8_t viscousSlot = 0; //viscous delay frame slot we will use
- if((alias < 8) && (digi.viscous & (1 << (alias))))
+ if((alias < 8) && (DigiConfig.viscous & (1 << (alias)))) //viscous delay mode
{
- for(uint8_t i = 0; i < VISCOUS_DATA_LEN; i++)
+ for(uint8_t i = 0; i < VISCOUS_MAX_FRAME_COUNT; i++)
{
- if(viscousData[i][0] == 0) //look for the first available slot
+ if(viscous[i].timeLimit == 0) //look for the first available slot
{
viscousSlot = i;
break;
}
}
- if((len + 7) > FRAMELEN) //if frame length (+ 7 bytes for inserted call) is bigger than buffer size
+ if((len + 7) > VISCOUS_MAX_FRAME_SIZE) //if frame length (+ 7 bytes for inserted call) is bigger than buffer size
return; //drop
- buf = viscousBuf[viscousSlot];
+ viscous[viscousSlot].frame = malloc(len + 7);
+ if(NULL == viscous[viscousSlot].frame)
+ return;
+ buffer = viscous[viscousSlot].frame;
+ index = &(viscous[viscousSlot].size);
+ *index = 0;
}
else //normal mode
{
- buf = malloc(FRAMELEN);
- if(buf == NULL)
+ if(sizeof(buf) < (len + 7))
return;
+ buffer = buf;
}
-
if(alias < 8)
{
- if(filterFrameCheck(&frame[7], alias)) //push source callsign though the filter
+ if(!filterFrameCheck(&frame[7], alias)) //push source callsign through the filter
return;
}
uint8_t ssid = (frame[elStart + 6] >> 1) - 48; //store SSID (N)
@@ -207,7 +219,7 @@ static void makeFrame(uint8_t *frame, uint16_t elStart, uint16_t len, uint32_t h
if(alias < 8)
{
- if((digi.viscous & (1 << (alias))) || (digi.directOnly & (1 << alias))) //viscous-delay or direct-only enabled
+ if((DigiConfig.viscous & (1 << (alias))) || (DigiConfig.directOnly & (1 << alias))) //viscous-delay or direct-only enabled
{
if(elStart != 14)
return; //this is not the very first path element, frame not received directly
@@ -218,143 +230,117 @@ static void makeFrame(uint8_t *frame, uint16_t elStart, uint16_t len, uint32_t h
if(simple) //if this is a simple alias, our own call or we treat n-N as a simple alias
{
- while(bufidx < (len)) //copy whole frame
+ while(*index < len) //copy whole frame
{
- buf[bufidx] = frame[bufidx];
- bufidx++;
- if(bufidx >= FRAMELEN)
- {
- if(buf != NULL)
- free(buf);
- return;
- }
+ buffer[*index] = frame[*index];
+ (*index)++;
}
- if((alias == 8) || ((digi.traced & (1 << alias)) == 0)) //own call or untraced
+
+ if((alias == 8) || ((DigiConfig.traced & (1 << alias)) == 0)) //own call or untraced
{
- buf[elStart + 6] += 128; //add h-bit
+ buffer[elStart + 6] += 128; //add h-bit
}
else //not our call, but treat it as a simple alias
{
- for(uint8_t i = 0; i < 6; i++) //replace with own call
- buf[elStart + i] = call[i];
+ for(uint8_t i = 0; i < sizeof(GeneralConfig.call); i++) //replace with own call
+ buffer[elStart + i] = GeneralConfig.call[i];
- buf[elStart + 6] &= 1; //clear everything but path end bit
- buf[elStart + 6] |= ((callSsid << 1) + 0b11100000); //inset ssid and h-bit
+ buffer[elStart + 6] &= 1; //clear everything but path end bit
+ buffer[elStart + 6] |= ((GeneralConfig.callSsid << 1) + 0b11100000); //insert ssid and h-bit
}
}
else //standard n-N alias
{
- while(bufidx < elStart) //copy all data before current path element
+ while(*index < elStart) //copy all data before current path element
{
- buf[bufidx] = frame[bufidx];
- bufidx++;
- if(bufidx >= FRAMELEN)
- {
- if(buf != NULL)
- free(buf);
- return;
- }
+ buffer[*index] = frame[*index];
+ (*index)++;
}
uint16_t shift = 0;
- if((digi.traced & (1 << alias)) || ((ssid == n) && (elStart == 14))) //if this is a traced alias OR it's not, but this is the very first hop for this packet, insert own call
+ //insert own callsign to path if:
+ //1. this is a traced alias OR
+ //2. this is an untraced alias, but it is the very first hop (heard directly)
+ if((DigiConfig.traced & (1 << alias)) || ((ssid == n) && (elStart == 14)))
{
- for(uint8_t i = 0; i < 6; i++) //insert own call
- buf[bufidx++] = call[i];
+ for(uint8_t i = 0; i < sizeof(GeneralConfig.call); i++) //insert own call
+ buffer[(*index)++] = GeneralConfig.call[i];
- buf[bufidx++] = ((callSsid << 1) + 0b11100000); //insert ssid and h-bit
+ buffer[(*index)++] = ((GeneralConfig.callSsid << 1) + 0b11100000); //insert ssid and h-bit
shift = 7; //additional shift when own call is inserted
}
- while(bufidx < (len + shift)) //copy rest of the frame
+ while(*index < (len + shift)) //copy rest of the frame
{
- buf[bufidx] = frame[bufidx - shift];
- bufidx++;
- if(bufidx >= FRAMELEN)
- {
- if(buf != NULL)
- free(buf);
- return;
- }
+ buffer[*index] = frame[*index - shift];
+ (*index)++;
}
- buf[elStart + shift + 6] -= 2; //decrement SSID in alias (2 beacuse ssid is shifted left by 1)
- if((buf[elStart + shift + 6] & 0b11110) == 0) //if SSID is 0
+ buffer[elStart + shift + 6] -= 2; //decrement SSID in alias (2 because ssid is shifted left by 1)
+ if((buffer[elStart + shift + 6] & 0b11110) == 0) //if SSID is 0
{
- buf[elStart + shift + 6] += 128; //add h-bit
+ buffer[elStart + shift + 6] += 0x80; //add h-bit
}
}
- if((alias < 8) && (digi.viscous & (1 << alias)))
+ if((alias < 8) && (DigiConfig.viscous & (1 << alias)))
{
- buf[bufidx++] = 0x00;
- viscousData[viscousSlot][0] = hash;
- viscousData[viscousSlot][1] = ticks;
- term_sendMonitor((uint8_t*)"Saving frame for viscous-delay digipeating\r\n", 0);
+ viscous[viscousSlot].hash = hash;
+ viscous[viscousSlot].timeLimit = ticks + (VISCOUS_HOLD_TIME / SYSTICK_INTERVAL);
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"Saving frame for viscous-delay digipeating\r\n", 0);
}
else
{
- if((FRAMEBUFLEN - ax25.xmitIdx) > (bufidx + 2))
+ void *handle = NULL;
+ if(NULL != (handle = Ax25WriteTxFrame(buffer, *index)))
{
- deDupeIndex %= DEDUPE_LEN;
+ DigiStoreDeDupe(buffer, *index);
- deDupeBuf[deDupeIndex][0] = hash; //store duplicate protection hash
- deDupeBuf[deDupeIndex][1] = ticks; //store timestamp
-
- deDupeIndex++;
-
- uint16_t begin = ax25.xmitIdx; //store frame beginning in tx buffer
-
- for(uint16_t i = 0; i < bufidx; i++) //copy frame to tx buffer
- {
- ax25.frameXmit[ax25.xmitIdx++] = buf[i];
- }
- ax25.frameXmit[ax25.xmitIdx++] = 0xFF;
-
- if(kissMonitor) //monitoring mode, send own frames to KISS ports
- {
- SendKiss(ax25.frameXmit, ax25.xmitIdx - 1);
- }
+ if(GeneralConfig.kissMonitor) //monitoring mode, send own frames to KISS ports
+ {
+ TermSendToAll(MODE_KISS, buffer, *index);
+ }
- common_toTNC2((uint8_t *)&ax25.frameXmit[begin], ax25.xmitIdx - begin - 1, buf);
- term_sendMonitor((uint8_t*)"(AX.25) Digipeating frame: ", 0);
- term_sendMonitor(buf, 0);
- term_sendMonitor((uint8_t*)"\r\n", 0);
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"(AX.25) Digipeating frame: ", 0);
+ SendTNC2(buffer, *index);
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"\r\n", 0);
}
- free(buf);
}
}
-void Digi_digipeat(uint8_t *frame, uint16_t len)
+void DigiDigipeat(uint8_t *frame, uint16_t len)
{
+ if(!DigiConfig.enable)
+ return;
- uint16_t t = 13; //path length for now
+ uint16_t t = 13; //start from first byte that can contain path end bit
while((frame[t] & 1) == 0) //look for path end
{
+ if((t + 7) >= len)
+ return;
t += 7;
- if(t > 150) return;
}
//calculate frame "hash"
- uint32_t hash = crc32(CRC32_INIT, frame, 14); //use destination and source adddress, skip path
- hash = crc32(hash, &frame[t + 1], len - t - 1); //continue through all remaining data
+ uint32_t hash = Crc32(CRC32_INIT, frame, 14); //use destination and source address, skip path
+ hash = Crc32(hash, &frame[t + 1], len - t); //continue through all remaining data
- if(digi.viscous) //viscous-delay enabled on any slot
+ if(DigiConfig.viscous) //viscous-delay enabled on any slot
{
- if(digi_viscousCheckAndRemove(hash)) //check if this frame was received twice
+ if(viscousCheckAndRemove(hash)) //check if this frame was received twice
return; //if so, drop it
}
- for(uint8_t i = 0; i < DEDUPE_LEN; i++) //check if frame is already in duplicate filtering buffer
+ for(uint8_t i = 0; i < DEDUPE_SIZE; i++) //check if frame is already in duplicate filtering buffer
{
- if(deDupeBuf[i][0] == hash)
+ if(deDupe[i].hash == hash)
{
- if((ticks - deDupeBuf[i][1]) <= (digi.dupeTime * 100))
- return; //filter duplicate frame
+ if(ticks < (deDupe[i].timeLimit))
+ return; //filter out duplicate frame
}
}
@@ -365,7 +351,7 @@ void Digi_digipeat(uint8_t *frame, uint16_t len)
}
- while((frame[t] & 128) == 0) //look for h-bit
+ while((frame[t] & 0x80) == 0) //look for h-bit
{
if(t == 13)
{
@@ -375,17 +361,19 @@ void Digi_digipeat(uint8_t *frame, uint16_t len)
}
t++; //now t is the index for the first byte in path element we want to process
-
uint8_t ssid = ((frame[t + 6] >> 1) - 0b00110000); //current path element SSID
uint8_t err = 0;
- for(uint8_t i = 0; i < 6; i++) //compare with our call
+ for(uint8_t i = 0; i < sizeof(GeneralConfig.call); i++) //compare with our call
{
- if(frame[t + i] != call[i])
+ if(frame[t + i] != GeneralConfig.call[i])
+ {
err = 1;
+ break;
+ }
}
- if(ssid != callSsid) //compare SSID also
+ if(ssid != GeneralConfig.callSsid) //compare SSID also
err = 1;
if(err == 0) //our callsign is in the path
@@ -394,19 +382,18 @@ void Digi_digipeat(uint8_t *frame, uint16_t len)
return;
}
-
-
for(uint8_t i = 0; i < 4; i++) //check for simple alias match
{
err = 0;
- for(uint8_t j = 0; j < 6; j++)
+ for(uint8_t j = 0; j < sizeof(DigiConfig.alias[0]); j++)
{
- if(frame[t + j] != digi.alias[i + 4][j])
+ if(frame[t + j] != DigiConfig.alias[i + 4][j])
{
err = 1;
+ break;
}
}
- if(ssid != digi.ssid[i])
+ if(ssid != DigiConfig.ssid[i])
err = 1;
if(err == 0) //no error
@@ -422,11 +409,12 @@ void Digi_digipeat(uint8_t *frame, uint16_t len)
{
err = 0;
uint8_t j = 0;
- for(; j < strlen((const char *)digi.alias[i]); j++)
+ for(; j < strlen((const char *)DigiConfig.alias[i]); j++)
{
- if(frame[t + j] != digi.alias[i][j]) //check for matching alias
+ if(frame[t + j] != DigiConfig.alias[i][j]) //check for matching alias
{
err = 1; //alias not matching
+ break;
}
}
@@ -435,7 +423,7 @@ void Digi_digipeat(uint8_t *frame, uint16_t len)
uint8_t n = ((frame[t + j] >> 1) - 48); //get n from alias (e.g. WIDEn-N) - N is in ssid variable
//every path must meet several requirements
- //say we have WIDEn-N path
+ //say we have a WIDEn-N path. Then:
//N <= n
//0 < n < 8
//0 < N < 8
@@ -443,14 +431,14 @@ void Digi_digipeat(uint8_t *frame, uint16_t len)
return;
//check if n and N <= digi max
- if((n <= digi.max[i]) && (ssid <= digi.max[i]))
+ if((n <= DigiConfig.max[i]) && (ssid <= DigiConfig.max[i]))
{
- if(digi.enableAlias & (1 << i))
+ if(DigiConfig.enableAlias & (1 << i))
makeFrame(frame, t, len, hash, i, 0, n); //process as a standard n-N frame
}
- else if((digi.rep[i] > 0) && (n >= digi.rep[i])) //else check if n and N >= digi replace
+ else if((DigiConfig.rep[i] > 0) && (n >= DigiConfig.rep[i])) //else check if n and N >= digi replace
{
- if(digi.enableAlias & (1 << i))
+ if(DigiConfig.enableAlias & (1 << i))
makeFrame(frame, t, len, hash, i, 1, n);
}
}
@@ -461,28 +449,24 @@ void Digi_digipeat(uint8_t *frame, uint16_t len)
-void Digi_storeDeDupeFromXmitBuf(uint16_t idx)
+void DigiStoreDeDupe(uint8_t *buf, uint16_t size)
{
- uint32_t hash = crc32(CRC32_INIT, &ax25.frameXmit[idx], 14); //calculate for destination and source address
-
+ uint32_t hash = Crc32(CRC32_INIT, buf, 14); //calculate for destination and source address
uint16_t i = 13;
- while((ax25.frameXmit[i] & 1) == 0) //look for path end bit (skip path)
+ while((buf[i] & 1) == 0) //look for path end bit (skip path)
{
i++;
}
i++;
- while(ax25.frameXmit[i] != 0xFF)
- {
- hash = crc32(hash, &ax25.frameXmit[i++], 1);
- }
+ hash = Crc32(hash, &buf[i], size - i);
- deDupeIndex %= DEDUPE_LEN;
+ deDupeCount %= DEDUPE_SIZE;
- deDupeBuf[deDupeIndex][0] = hash;
- deDupeBuf[deDupeIndex][1] = ticks;
+ deDupe[deDupeCount].hash = hash;
+ deDupe[deDupeCount].timeLimit = ticks + (DigiConfig.dupeTime * 10 / SYSTICK_INTERVAL);
- deDupeIndex++;
+ deDupeCount++;
}
diff --git a/Src/drivers/modem.c b/Src/drivers/modem.c
index e1f53c4..ba419af 100644
--- a/Src/drivers/modem.c
+++ b/Src/drivers/modem.c
@@ -41,65 +41,36 @@ along with VP-Digi. If not, see .
#define DCD_INC 7
#define DCD_PLLTUNE 0
-#define NN 8 //samples per symbol
-#define DACSINELEN 32 //DAC sine table size
+#define N 8 //samples per symbol
+#define DAC_SINE_SIZE 32 //DAC sine table size
#define PLLINC 536870912 //PLL tick increment value
#define PLLLOCKED 0.74 //PLL adjustment value when locked
#define PLLNOTLOCKED 0.50 //PLL adjustment value when not locked
-
#define PTT_ON GPIOB->BSRR = GPIO_BSRR_BS7
#define PTT_OFF GPIOB->BSRR = GPIO_BSRR_BR7
#define DCD_ON (GPIOC->BSRR = GPIO_BSRR_BR13)
#define DCD_OFF (GPIOC->BSRR = GPIO_BSRR_BS13)
+struct ModemDemodConfig ModemConfig;
-struct ModState
-{
- TxTestMode txTestState; //current TX test mode
- uint16_t dacSine[DACSINELEN]; //sine samples for DAC
- uint8_t dacSineIdx; //current sine sample index
- uint16_t samples_oversampling[4]; //very raw received samples, filled directly by DMA
- uint8_t currentSymbol; //current symbol for NRZI encoding
- uint16_t txDelay; //TXDelay length in number of bytes
- uint16_t txTail; //TXTail length in number of bytes
- uint8_t markFreq; //mark frequency (inter-sample interval)
- uint8_t spaceFreq; //space frequency (inter-sample interval)
- uint16_t baudRate; //baudrate
- int32_t coeffHiI[NN], coeffLoI[NN], coeffHiQ[NN], coeffLoQ[NN]; //correlator IQ coefficients
-};
-
-volatile struct ModState modState;
-
-
-typedef struct
-{
- Emphasis emphasis; //preemphasis/deemphasis
- uint8_t rawSymbols; //raw, unsynchronized symbols
- uint8_t syncSymbols; //synchronized symbols
- int16_t rawSample[8]; //input (raw) samples
- int32_t rxSample[16]; //rx samples after pre/deemphasis filter
- uint8_t rxSampleIdx; //index for the array above
- int64_t lpfSample[16]; //rx samples after final filtering
- uint8_t dcd : 1; //DCD state
- uint64_t RMSenergy; //frame energy counter (sum of samples squared)
- uint32_t RMSsampleCount; //number of samples for RMS
- int32_t pll; //bit recovery PLL counter
- int32_t lastPll; //last bit recovery PLL counter value
- int32_t dcdPll; //DCD PLL main counter
- uint8_t dcdLastSymbol; //last symbol for DCD
- uint8_t dcdCounter; //DCD "pulse" counter (incremented when RX signal is correct)
-} Demod;
-
-volatile Demod demod1;
-volatile Demod demod2;
+static enum ModemTxTestMode txTestState; //current TX test mode
+static uint16_t dacSine[DAC_SINE_SIZE]; //sine samples for DAC
+static uint8_t dacSineIdx; //current sine sample index
+static uint16_t samples[4]; //very raw received samples, filled directly by DMA
+static uint8_t currentSymbol; //current symbol for NRZI encoding
+static uint8_t markFreq; //mark frequency (inter-sample interval)
+static uint8_t spaceFreq; //space frequency (inter-sample interval)
+static uint16_t baudRate; //baudrate
+static int32_t coeffHiI[N], coeffLoI[N], coeffHiQ[N], coeffLoQ[N]; //correlator IQ coefficients
+static uint8_t dcd = 0; //multiplexed DCD state from both demodulators
-uint8_t dcd = 0; //multiplexed DCD state from both demodulators
/**
* @brief BPF filter with 2200 Hz tone 6 dB preemphasis (it actually attenuates 1200 Hz tone by 6 dB)
*/
-const int16_t bpf1200[8] = {
+static const int16_t bpfCoeffs[8] =
+{
728,
-13418,
-554,
@@ -113,7 +84,8 @@ const int16_t bpf1200[8] = {
/**
* @brief BPF filter with 2200 Hz tone 6 dB deemphasis
*/
-const int16_t bpf1200inv[8] = {
+static const int16_t invBpfCoeffs[8] =
+{
-10513,
-10854,
9589,
@@ -124,11 +96,15 @@ const int16_t bpf1200inv[8] = {
-879
};
+#define BPF_TAPS (sizeof(bpfCoeffs) / sizeof(*bpfCoeffs) > sizeof(invBpfCoeffs) / sizeof(*invBpfCoeffs) ? \
+ sizeof(bpfCoeffs) / sizeof(*bpfCoeffs) : sizeof(invBpfCoeffs) / sizeof(*invBpfCoeffs))
+
/**
* @brief Output LPF filter to remove data faster than 1200 baud
* It actually is a 600 Hz filter: symbols can change at 1200 Hz, but it takes 2 "ticks" to return to the same symbol - that's why it's 600 Hz
*/
-const int16_t lpf1200[15] = {
+static const int16_t lpfCoeffs[15] =
+{
-6128,
-5974,
-2503,
@@ -146,54 +122,70 @@ const int16_t lpf1200[15] = {
-6128
};
+#define LPF_TAPS (sizeof(lpfCoeffs) / sizeof(*lpfCoeffs))
+
+
+struct DemodState
+{
+ enum ModemEmphasis emphasis; //preemphasis/deemphasis
+ uint8_t rawSymbols; //raw, unsynchronized symbols
+ uint8_t syncSymbols; //synchronized symbols
+ int16_t rawSample[BPF_TAPS]; //input (raw) samples
+ int32_t rxSample[BPF_TAPS]; //rx samples after pre/deemphasis filter
+ uint8_t rxSampleIdx; //index for the array above
+ int64_t lpfSample[LPF_TAPS]; //rx samples after final filtering
+ uint8_t dcd : 1; //DCD state
+ uint64_t RMSenergy; //frame energy counter (sum of samples squared)
+ uint32_t RMSsampleCount; //number of samples for RMS
+ int32_t pll; //bit recovery PLL counter
+ int32_t lastPll; //last bit recovery PLL counter value
+ int32_t dcdPll; //DCD PLL main counter
+ uint8_t dcdLastSymbol; //last symbol for DCD
+ uint8_t dcdCounter; //DCD "pulse" counter (incremented when RX signal is correct)
+};
+static volatile struct DemodState demodState[MODEM_DEMODULATOR_COUNT];
-static void afsk_decode(uint8_t symbol, Demod *dem);
-static int32_t afsk_demod(int16_t sample, Demod *dem);
-static void afsk_ptt(uint8_t state);
+static void decode(uint8_t symbol, uint8_t demod);
+static int32_t demodulate(int16_t sample, struct DemodState *dem);
+static void setPtt(uint8_t state);
-uint8_t Afsk_dcdState(void)
+uint8_t ModemDcdState(void)
{
return dcd;
}
-uint8_t Afsk_isTxTestOngoing(void)
+uint8_t ModemIsTxTestOngoing(void)
{
- if(modState.txTestState != TEST_DISABLED)
+ if(txTestState != TEST_DISABLED)
return 1;
return 0;
}
-void Afsk_clearRMS(uint8_t modemNo)
+void ModemClearRMS(uint8_t modem)
{
- if(modemNo == 0)
- {
- demod1.RMSenergy = 0;
- demod1.RMSsampleCount = 0;
- }
- else
- {
- demod2.RMSenergy = 0;
- demod2.RMSsampleCount = 0;
- }
+
+ demodState[modem].RMSenergy = 0;
+ demodState[modem].RMSsampleCount = 0;
+
}
-uint16_t Afsk_getRMS(uint8_t modemNo)
+uint16_t ModemGetRMS(uint8_t modem)
{
- if(modemNo == 0)
- {
- return sqrtf((float)demod1.RMSenergy / (float)demod1.RMSsampleCount);
- }
- return sqrtf((float)demod2.RMSenergy / (float)demod2.RMSsampleCount);
+ return sqrtf((float)demodState[modem].RMSenergy / (float)demodState[modem].RMSsampleCount);
}
+enum ModemEmphasis ModemGetFilterType(uint8_t modem)
+{
+ return demodState[modem].emphasis;
+}
/**
* @brief Set DCD LED
* @param[in] state 0 - OFF, 1 - ON
*/
-static void afsk_dcd(uint8_t state)
+static void setDcd(uint8_t state)
{
if(state)
{
@@ -219,33 +211,33 @@ void DMA1_Channel2_IRQHandler(void)
{
DMA1->IFCR |= DMA_IFCR_CTCIF2;
- int32_t sample = ((modState.samples_oversampling[0] + modState.samples_oversampling[1] + modState.samples_oversampling[2] + modState.samples_oversampling[3]) >> 1) - 4095; //calculate input sample (decimation)
- uint8_t symbol = 0; //output symbol
+ int32_t sample = ((samples[0] + samples[1] + samples[2] + samples[3]) >> 1) - 4095; //calculate input sample (decimation)
- //use 2 demodulators
- symbol = (afsk_demod(sample, (Demod*)&demod1) > 0); //demodulate sample
- afsk_decode(symbol, (Demod*)&demod1); //recover bits, decode NRZI and call higher level function
+ uint8_t partialDcd = 0;
- symbol = (afsk_demod(sample, (Demod*)&demod2) > 0);
- afsk_decode(symbol, (Demod*)&demod2);
+ for(uint8_t i = 0; i < MODEM_DEMODULATOR_COUNT; i++)
+ {
+ uint8_t symbol = (demodulate(sample, (struct DemodState*)&demodState[i]) > 0); //demodulate sample
+ decode(symbol, i); //recover bits, decode NRZI and call higher level function
+ if(demodState[i].dcd)
+ partialDcd |= 1;
+ }
- if(demod1.dcd || demod2.dcd) //DCD on any of the demodulators
+ if(partialDcd) //DCD on any of the demodulators
{
dcd = 1;
- afsk_dcd(1);
+ setDcd(1);
}
- else if((demod1.dcd == 0) && (demod2.dcd == 0)) //no DCD on both demodulators
+ else //no DCD on both demodulators
{
dcd = 0;
- afsk_dcd(0);
+ setDcd(0);
}
}
}
-
-
/**
* @brief ISR for pushing DAC samples
*/
@@ -254,19 +246,18 @@ void TIM1_UP_IRQHandler(void)
{
TIM1->SR &= ~TIM_SR_UIF;
- modState.dacSineIdx++;
- modState.dacSineIdx &= (DACSINELEN - 1);
-
- if(afskCfg.usePWM)
+ if(ModemConfig.usePWM)
{
- TIM4->CCR1 = modState.dacSine[modState.dacSineIdx];
+ TIM4->CCR1 = dacSine[dacSineIdx];
}
else
{
- GPIOB->ODR &= ~61440; //zero 4 oldest bits
- GPIOB->ODR |= (modState.dacSine[modState.dacSineIdx] << 12); //write sample to 4 oldest bits
-
+ GPIOB->ODR &= ~0xF000; //zero 4 oldest bits
+ GPIOB->ODR |= (dacSine[dacSineIdx] << 12); //write sample to 4 oldest bits
}
+
+ dacSineIdx++;
+ dacSineIdx &= (DAC_SINE_SIZE - 1);
}
@@ -278,34 +269,25 @@ void TIM3_IRQHandler(void)
{
TIM3->SR &= ~TIM_SR_UIF;
- if(modState.txTestState == TEST_DISABLED) //transmitting normal data
+ if(txTestState == TEST_DISABLED) //transmitting normal data
{
- if(Ax25_getTxBit() == 0) //get next bit and check if it's 0
+ if(Ax25GetTxBit() == 0) //get next bit and check if it's 0
{
- modState.currentSymbol = modState.currentSymbol ? 0 : 1; //change symbol - NRZI encoding
+ currentSymbol ^= 1; //change symbol - NRZI encoding
}
//if 1, no symbol change
}
else //transmit test mode
{
- modState.currentSymbol = modState.currentSymbol ? 0 : 1; //change symbol
+ currentSymbol ^= 1; //change symbol
}
- if(modState.currentSymbol) //current symbol is space
- {
+ TIM1->CNT = 0;
- TIM1->CNT = 0;
- TIM1->ARR = modState.spaceFreq;
- }
+ if(currentSymbol) //current symbol is space
+ TIM1->ARR = spaceFreq;
else //mark
- {
-
- TIM1->CNT = 0;
- TIM1->ARR = modState.markFreq;
-
- }
-
-
+ TIM1->ARR = markFreq;
}
@@ -316,30 +298,27 @@ void TIM3_IRQHandler(void)
* @param[in] *dem Demodulator state
* @return Current tone (0 or 1)
*/
-static int32_t afsk_demod(int16_t sample, Demod *dem)
+static int32_t demodulate(int16_t sample, struct DemodState *dem)
{
dem->RMSenergy += ((sample >> 1) * (sample >> 1)); //square the sample and add it to the sum
dem->RMSsampleCount++; //increment number of samples
-
-
if(dem->emphasis != EMPHASIS_NONE) //preemphasis/deemphasis is used
{
int32_t out = 0; //filtered output
- for(uint8_t i = 7; i > 0; i--)
+ for(uint8_t i = BPF_TAPS - 1; i > 0; i--)
dem->rawSample[i] = dem->rawSample[i - 1]; //shift old samples
dem->rawSample[0] = sample; //store new sample
- for(uint8_t i = 0; i < 8; i++)
+ for(uint8_t i = 0; i < BPF_TAPS; i++)
{
if(dem->emphasis == PREEMPHASIS)
- out += bpf1200[i] * dem->rawSample[i]; //use preemphasis
+ out += bpfCoeffs[i] * dem->rawSample[i]; //use preemphasis
else
- out += bpf1200inv[i] * dem->rawSample[i]; //use deemphasis
+ out += invBpfCoeffs[i] * dem->rawSample[i]; //use deemphasis
}
-
dem->rxSample[dem->rxSampleIdx] = (out >> 15); //store filtered sample
}
else //no pre/deemphasis
@@ -347,21 +326,20 @@ static int32_t afsk_demod(int16_t sample, Demod *dem)
dem->rxSample[dem->rxSampleIdx] = sample; //store incoming sample
}
- int64_t outLoI = 0, outLoQ = 0, outHiI = 0, outHiQ = 0; //output values after correlating
+ dem->rxSampleIdx = (dem->rxSampleIdx + 1) % BPF_TAPS; //increment sample pointer and wrap around if needed
- dem->rxSampleIdx = (dem->rxSampleIdx + 1) % NN; //increment sample pointer and wrap around if needed
+ int64_t outLoI = 0, outLoQ = 0, outHiI = 0, outHiQ = 0; //output values after correlating
- for(uint8_t i = 0; i < NN; i++) {
- int32_t t = dem->rxSample[(dem->rxSampleIdx + i) % NN]; //read sample
- outLoI += t * modState.coeffLoI[i]; //correlate sample
- outLoQ += t * modState.coeffLoQ[i];
- outHiI += t * modState.coeffHiI[i];
- outHiQ += t * modState.coeffHiQ[i];
+ for(uint8_t i = 0; i < N; i++) {
+ int32_t t = dem->rxSample[(dem->rxSampleIdx + i) % BPF_TAPS]; //read sample
+ outLoI += t * coeffLoI[i]; //correlate sample
+ outLoQ += t * coeffLoQ[i];
+ outHiI += t * coeffHiI[i];
+ outHiQ += t * coeffHiQ[i];
}
uint64_t hi = 0, lo = 0;
-
hi = ((outHiI >> 12) * (outHiI >> 12)) + ((outHiQ >> 12) * (outHiQ >> 12)); //calculate output tone levels
lo = ((outLoI >> 12) * (outLoI >> 12)) + ((outLoQ >> 12) * (outLoQ >> 12));
@@ -395,7 +373,6 @@ static int32_t afsk_demod(int16_t sample, Demod *dem)
dem->dcdLastSymbol = dcdSymbol; //store last symbol for symbol change detection
-
if(dem->dcdCounter > DCD_MAXPULSE) //maximum DCD counter value reached
dem->dcdCounter = DCD_MAXPULSE; //avoid "sticky" DCD and counter overflow
@@ -407,13 +384,13 @@ static int32_t afsk_demod(int16_t sample, Demod *dem)
//filter out signal faster than 1200 baud
int64_t out = 0;
- for(uint8_t i = 14; i > 0; i--)
+ for(uint8_t i = LPF_TAPS - 1; i > 0; i--)
dem->lpfSample[i] = dem->lpfSample[i - 1];
dem->lpfSample[0] = (int64_t)hi - (int64_t)lo;
- for(uint8_t i = 0; i < 15; i++)
+ for(uint8_t i = 0; i < LPF_TAPS; i++)
{
- out += lpf1200[i] * dem->lpfSample[i];
+ out += lpfCoeffs[i] * dem->lpfSample[i];
}
return out > 0;
@@ -425,10 +402,11 @@ static int32_t afsk_demod(int16_t sample, Demod *dem)
/**
* @brief Decode received symbol: bit recovery, NRZI decoding and pass the decoded bit to higher level protocol
* @param[in] symbol Received symbol
- * @param *dem Demodulator state
+ * @param demod Demodulator index
*/
-static void afsk_decode(uint8_t symbol, Demod *dem)
+static void decode(uint8_t symbol, uint8_t demod)
{
+ struct DemodState *dem = (struct DemodState*)&demodState[demod];
//This function provides bit/clock recovery and NRZI decoding
//Bit recovery is based on PLL which is described in the function above (DCD PLL)
@@ -441,7 +419,6 @@ static void afsk_decode(uint8_t symbol, Demod *dem)
dem->rawSymbols |= (symbol & 1);
-
if ((dem->pll < 0) && (dem->lastPll > 0)) //PLL counter overflow, sample symbol, decode NRZI and process in higher layer
{
dem->syncSymbols <<= 1; //shift recovered (received, synchronized) bit register
@@ -456,18 +433,18 @@ static void afsk_decode(uint8_t symbol, Demod *dem)
//NRZI decoding
if (((dem->syncSymbols & 0x03) == 0b11) || ((dem->syncSymbols & 0x03) == 0b00)) //two last symbols are the same - no symbol transition - decoded bit 1
{
- Ax25_bitParse(1, (dem == &demod1) ? 0 : 1);
+ Ax25BitParse(1, demod);
}
else //symbol transition - decoded bit 0
{
- Ax25_bitParse(0, (dem == &demod1) ? 0 : 1);
+ Ax25BitParse(0, demod);
}
}
if(((dem->rawSymbols & 0x03) == 0b10) || ((dem->rawSymbols & 0x03) == 0b01)) //if there was a symbol transition, adjust PLL
{
- if (Ax25_getRxStage((dem == &demod1) ? 0 : 1) != RX_STAGE_FRAME) //not in a frame
+ if(Ax25GetRxStage(demod) != RX_STAGE_FRAME) //not in a frame
{
dem->pll = (int)(dem->pll * PLLNOTLOCKED); //adjust PLL faster
}
@@ -480,54 +457,47 @@ static void afsk_decode(uint8_t symbol, Demod *dem)
}
-/**
- * @brief Start or restart TX test mode
- * @param[in] type TX test type: TEST_MARK, TEST_SPACE or TEST_ALTERNATING
- */
-void Afsk_txTestStart(TxTestMode type)
+
+void ModemTxTestStart(enum ModemTxTestMode type)
{
- if(modState.txTestState != TEST_DISABLED) //TX test is already running
- Afsk_txTestStop(); //stop this test
+ if(txTestState != TEST_DISABLED) //TX test is already running
+ ModemTxTestStop(); //stop this test
- afsk_ptt(1); //PTT on
- modState.txTestState = type;
+ setPtt(1); //PTT on
+ txTestState = type;
//DAC timer
TIM1->PSC = 17; //72/18=4 MHz
TIM1->DIER = TIM_DIER_UIE; //enable interrupt
TIM1->CR1 |= TIM_CR1_CEN; //enable timer
-
TIM2->CR1 &= ~TIM_CR1_CEN; //disable RX timer
-
NVIC_DisableIRQ(DMA1_Channel2_IRQn); //disable RX DMA interrupt
NVIC_EnableIRQ(TIM1_UP_IRQn); //enable timer 1 for PWM
if(type == TEST_MARK)
{
- TIM1->ARR = modState.markFreq;
+ TIM1->ARR = markFreq;
} else if(type == TEST_SPACE)
{
- TIM1->ARR = modState.spaceFreq;
+ TIM1->ARR = spaceFreq;
}
else //alternating tones
{
//enable baudrate generator
TIM3->PSC = 71; //72/72=1 MHz
TIM3->DIER = TIM_DIER_UIE; //enable interrupt
- TIM3->ARR = modState.baudRate; //set timer interval
+ TIM3->ARR = baudRate; //set timer interval
TIM3->CR1 = TIM_CR1_CEN; //enable timer
NVIC_EnableIRQ(TIM3_IRQn); //enable interrupt in NVIC
}
}
-/**
- * @brief Stop TX test mode
- */
-void Afsk_txTestStop(void)
+
+void ModemTxTestStop(void)
{
- modState.txTestState = TEST_DISABLED;
+ txTestState = TEST_DISABLED;
TIM3->CR1 &= ~TIM_CR1_CEN; //turn off timers
TIM1->CR1 &= ~TIM_CR1_CEN;
@@ -537,16 +507,13 @@ void Afsk_txTestStop(void)
NVIC_DisableIRQ(TIM1_UP_IRQn);
NVIC_EnableIRQ(DMA1_Channel2_IRQn);
- afsk_ptt(0); //PTT off
+ setPtt(0); //PTT off
}
-/**
- * @brief Configure and start TX
- * @warning Transmission should be started with Ax25_transmitBuffer
- */
-void Afsk_transmitStart(void)
+
+void ModemTransmitStart(void)
{
- afsk_ptt(1); //PTT on
+ setPtt(1); //PTT on
TIM1->PSC = 17;
TIM1->DIER |= TIM_DIER_UIE;
@@ -554,7 +521,7 @@ void Afsk_transmitStart(void)
TIM3->PSC = 71;
TIM3->DIER |= TIM_DIER_UIE;
- TIM3->ARR = modState.baudRate;
+ TIM3->ARR = baudRate;
TIM3->CR1 = TIM_CR1_CEN;
TIM1->CR1 = TIM_CR1_CEN;
@@ -563,14 +530,13 @@ void Afsk_transmitStart(void)
NVIC_DisableIRQ(DMA1_Channel2_IRQn);
NVIC_EnableIRQ(TIM1_UP_IRQn);
NVIC_EnableIRQ(TIM3_IRQn);
-
}
/**
* @brief Stop TX and go back to RX
*/
-void Afsk_transmitStop(void)
+void ModemTransmitStop(void)
{
TIM2->CR1 |= TIM_CR1_CEN;
@@ -581,7 +547,7 @@ void Afsk_transmitStop(void)
NVIC_DisableIRQ(TIM3_IRQn);
NVIC_EnableIRQ(DMA1_Channel2_IRQn);
- afsk_ptt(0);
+ setPtt(0);
TIM4->CCR1 = 44; //set around 50% duty cycle
}
@@ -590,7 +556,7 @@ void Afsk_transmitStop(void)
* @brief Controls PTT output
* @param[in] state 0 - PTT off, 1 - PTT on
*/
-static void afsk_ptt(uint8_t state)
+static void setPtt(uint8_t state)
{
if(state)
PTT_ON;
@@ -603,11 +569,11 @@ static void afsk_ptt(uint8_t state)
/**
* @brief Initialize AFSK module
*/
-void Afsk_init(void)
+void ModemInit(void)
{
/**
- * TIM1 is used for pushing samples to DAC (R2R or PWM)
- * TIM3 is the baudrate generator for TX
+ * TIM1 is used for pushing samples to DAC (R2R or PWM) at 4 MHz
+ * TIM3 is the baudrate generator for TX running at 1 MHz
* TIM4 is the PWM generator with no software interrupt
* TIM2 is the RX sampling timer with no software interrupt, but it directly calls DMA
*/
@@ -622,13 +588,12 @@ void Afsk_init(void)
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
-
GPIOC->CRH |= GPIO_CRH_MODE13_1; //DCD LED on PC13
GPIOC->CRH &= ~GPIO_CRH_MODE13_0;
GPIOC->CRH &= ~GPIO_CRH_CNF13;
- GPIOB->CRH &= ~4294901760; //R2R output on PB12-PB15
- GPIOB->CRH |= 572653568;
+ GPIOB->CRH &= ~0xFFFF0000; //R2R output on PB12-PB15
+ GPIOB->CRH |= 0x22220000;
GPIOA->CRL &= ~GPIO_CRL_CNF0; //ADC input on PA0
GPIOA->CRL &= ~GPIO_CRL_MODE0;
@@ -654,9 +619,11 @@ void Afsk_init(void)
ADC1->CR2 |= ADC_CR2_ADON; //ADC on
ADC1->CR2 |= ADC_CR2_RSTCAL; //calibrate ADC
- while(ADC1->CR2 & ADC_CR2_RSTCAL);
+ while(ADC1->CR2 & ADC_CR2_RSTCAL)
+ ;
ADC1->CR2 |= ADC_CR2_CAL;
- while(ADC1->CR2 & ADC_CR2_CAL);
+ while(ADC1->CR2 & ADC_CR2_CAL)
+ ;
ADC1->CR2 |= ADC_CR2_EXTTRIG;
ADC1->CR2 |= ADC_CR2_SWSTART; //start ADC conversion
@@ -670,7 +637,7 @@ void Afsk_init(void)
DMA1_Channel2->CCR |= DMA_CCR_MINC | DMA_CCR_CIRC| DMA_CCR_TCIE; //circular mode, memory increment and interrupt
DMA1_Channel2->CNDTR = 4; //4 samples
DMA1_Channel2->CPAR = (uint32_t)&(ADC1->DR); //ADC data register address
- DMA1_Channel2->CMAR = (uint32_t)modState.samples_oversampling; //sample buffer address
+ DMA1_Channel2->CMAR = (uint32_t)samples; //sample buffer address
DMA1_Channel2->CCR |= DMA_CCR_EN; //enable DMA
NVIC_EnableIRQ(DMA1_Channel2_IRQn);
@@ -680,42 +647,39 @@ void Afsk_init(void)
TIM2->ARR = 103; //4MHz / 104 =~38400 Hz (4*9600 Hz for 4x oversampling)
TIM2->CR1 |= TIM_CR1_CEN; //enable timer
- modState.markFreq = 103; //set mark frequency
- modState.spaceFreq = 55; //set space frequency
-
- modState.baudRate = 832; //set baudrate
-
-
+ markFreq = 4000000 / (DAC_SINE_SIZE * (uint32_t)MODEM_MARK_FREQUENCY) - 1; //set mark frequency
+ spaceFreq = 4000000 / (DAC_SINE_SIZE * (uint32_t)MODEM_SPACE_FREQUENCY) - 1; //set space frequency
+ baudRate = 1000000 / (uint32_t)MODEM_BAUDRATE - 1; //set baudrate
- for(uint8_t i = 0; i < NN; i++) //calculate correlator coefficients
+ for(uint8_t i = 0; i < N; i++) //calculate correlator coefficients
{
- modState.coeffLoI[i] = 4095.f * cosf(2.f * 3.1416f * (float)i / (float)NN);
- modState.coeffLoQ[i] = 4095.f * sinf(2.f * 3.1416f * (float)i / (float)NN);
- modState.coeffHiI[i] = 4095.f * cosf(2.f * 3.1416f * (float)i / (float)NN * 2200.f / 1200.f);
- modState.coeffHiQ[i] = 4095.f * sinf(2.f * 3.1416f * (float)i / (float)NN * 2200.f / 1200.f);
+ coeffLoI[i] = 4095.f * cosf(2.f * 3.1416f * (float)i / (float)N * MODEM_MARK_FREQUENCY / MODEM_BAUDRATE);
+ coeffLoQ[i] = 4095.f * sinf(2.f * 3.1416f * (float)i / (float)N * MODEM_MARK_FREQUENCY / MODEM_BAUDRATE);
+ coeffHiI[i] = 4095.f * cosf(2.f * 3.1416f * (float)i / (float)N * MODEM_SPACE_FREQUENCY / MODEM_BAUDRATE);
+ coeffHiQ[i] = 4095.f * sinf(2.f * 3.1416f * (float)i / (float)N * MODEM_SPACE_FREQUENCY / MODEM_BAUDRATE);
}
- for(uint8_t i = 0; i < DACSINELEN; i++) //calculate DAC sine samples
+ for(uint8_t i = 0; i < DAC_SINE_SIZE; i++) //calculate DAC sine samples
{
- if(afskCfg.usePWM)
- modState.dacSine[i] = ((sinf(2.f * 3.1416f * (float)i / (float)DACSINELEN) + 1.f) * 45.f);
+ if(ModemConfig.usePWM)
+ dacSine[i] = ((sinf(2.f * 3.1416f * (float)i / (float)DAC_SINE_SIZE) + 1.f) * 45.f);
else
- modState.dacSine[i] = ((7.f * sinf(2.f * 3.1416f * (float)i / (float)DACSINELEN)) + 8.f);
+ dacSine[i] = ((7.f * sinf(2.f * 3.1416f * (float)i / (float)DAC_SINE_SIZE)) + 8.f);
}
- if(afskCfg.flatAudioIn) //when used with flat audio input, use deemphasis and flat modems
+ if(ModemConfig.flatAudioIn) //when used with flat audio input, use deemphasis and flat modems
{
- demod1.emphasis = EMPHASIS_NONE;
- demod2.emphasis = DEEMPHASIS;
+ demodState[0].emphasis = EMPHASIS_NONE;
+ demodState[1].emphasis = DEEMPHASIS;
}
else //when used with normal (filtered) audio input, use flat and preemphasis modems
{
- demod1.emphasis = EMPHASIS_NONE;
- demod2.emphasis = PREEMPHASIS;
+ demodState[0].emphasis = EMPHASIS_NONE;
+ demodState[1].emphasis = PREEMPHASIS;
}
- if(afskCfg.usePWM)
+ if(ModemConfig.usePWM)
{
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; //configure timer
diff --git a/Src/drivers/systick.c b/Src/drivers/systick.c
index 12f4f18..82d5208 100644
--- a/Src/drivers/systick.c
+++ b/Src/drivers/systick.c
@@ -16,6 +16,7 @@ along with VP-Digi. If not, see .
*/
#include "drivers/systick.h"
+#include "stm32f1xx.h"
volatile uint32_t ticks = 0; //SysTick counter
@@ -25,7 +26,7 @@ volatile uint32_t ticks = 0; //SysTick counter
//ticks++;
//}
-void SysTick_init(void)
+void SysTickInit(void)
{
- SysTick_Config(SystemCoreClock / 100); //SysTick every 10 ms
+ SysTick_Config(SystemCoreClock / SYSTICK_FREQUENCY); //SysTick every 10 ms
}
diff --git a/Src/drivers/uart.c b/Src/drivers/uart.c
index e7bfa1f..3b458eb 100644
--- a/Src/drivers/uart.c
+++ b/Src/drivers/uart.c
@@ -24,94 +24,89 @@ along with VP-Digi. If not, see .
#include "digipeater.h"
-uint8_t USBmode = MODE_KISS;
-uint8_t USBrcvd = DATA_NOTHING;
-uint8_t USBint = 0; /**< Flaga "przerwania" USB dla obslugi w petli glownej */
-
-
-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 volatile void uart_handleInterrupt(Uart *port)
+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
{
port->port->SR &= ~USART_SR_RXNE;
- port->bufrx[port->bufrxidx] = port->port->DR; //store it
- port->bufrxidx++;
- if(port->port == USART1) //handle special functions and characters
- term_handleSpecial(TERM_UART1);
- else if(port->port == USART2)
- term_handleSpecial(TERM_UART2);
+ port->rxBuffer[port->rxBufferHead++] = port->port->DR; //store it
+ port->rxBufferHead %= UART_BUFFER_SIZE;
- port->bufrxidx %= UARTBUFLEN;
+// 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 + 500; //set timeout to 5s in KISS mode
+ port->kissTimer = ticks + (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->bufrxidx == 0)
- return; //no data, stop
-
- if((port->bufrx[0] == 0xc0) && (port->bufrx[port->bufrxidx - 1] == 0xc0)) //data starts with 0xc0 and ends with 0xc0 - this is a KISS frame
- {
- port->rxflag = DATA_KISS;
- port->kissTimer = 0;
- }
-
- if(((port->bufrx[port->bufrxidx - 1] == '\r') || (port->bufrx[port->bufrxidx - 1] == '\n'))) //data ends with \r or \n, process as data
+ if(port->rxBufferHead != 0)
{
- port->rxflag = DATA_TERM;
- port->kissTimer = 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
+ {
+ port->rxType = DATA_TERM;
+ port->kissTimer = 0;
+ }
}
-
}
if(port->port->SR & USART_SR_TXE) //TX buffer empty
{
- if(port->buftxrd != port->buftxwr) //if there is anything to transmit
+ if((port->txBufferHead != port->txBufferTail) || port->txBufferFull) //if there is anything to transmit
{
- port->port->DR = port->buftx[port->buftxrd++]; //push it to the refister
- port->buftxrd %= UARTBUFLEN;
- } else //nothing more to be transmitted
+ port->port->DR = port->txBuffer[port->txBufferTail++]; //push it to the refister
+ port->txBufferTail %= UART_BUFFER_SIZE;
+ port->txBufferFull = 0;
+ }
+ else //nothing more to be transmitted
{
- port->txflag = 0; //stop transmission
port->port->CR1 &= ~USART_CR1_TXEIE;
}
}
@@ -119,159 +114,105 @@ static volatile void uart_handleInterrupt(Uart *port)
if((port->kissTimer > 0) && (ticks >= port->kissTimer)) //KISS timer timeout
{
port->kissTimer = 0;
- port->bufrxidx = 0;
- memset(port->bufrx, 0, UARTBUFLEN);
+ port->rxBufferHead = 0;
+ memset(port->rxBuffer, 0, sizeof(port->rxBuffer));
}
}
void USART1_IRQHandler(void) __attribute__ ((interrupt));
void USART1_IRQHandler(void)
{
- uart_handleInterrupt(&uart1);
+ handleInterrupt(&Uart1);
}
void USART2_IRQHandler(void) __attribute__ ((interrupt));
void USART2_IRQHandler(void)
{
- uart_handleInterrupt(&uart2);
+ handleInterrupt(&Uart2);
}
-
-
-void uart_transmitStart(Uart *port)
+void UartSendByte(Uart *port, uint8_t data)
{
- if(port->enabled == 0)
- {
- port->buftxrd = port->buftxwr;
+ if(!port->enabled)
return;
- }
- port->txflag = 1;
- port->port->CR1 |= USART_CR1_TXEIE;
-}
-
-
-void uartUSB_sendByte(uint8_t data)
-{
- uint8_t a[1];
- a[0] = data;
- CDC_Transmit_FS(a, 1);
-}
-
-
-void uart_sendByte(Uart *port, uint8_t data)
-{
- while(port->txflag == 1);;
- port->buftx[port->buftxwr++] = data;
- port->buftxwr %= (UARTBUFLEN);
-}
-
-
-void uart_sendString(Uart *port, uint8_t *data, uint16_t len)
-{
-
- if(len == 0)
+ if(port->isUsb)
{
- while(*(data + len) != 0)
- {
- len++;
- if(len == UARTBUFLEN)
- break;
- }
+ CDC_Transmit_FS(&data, 1);
}
-
- while(port->txflag == 1);;
- uint16_t i = 0;
- while(i < len)
+ else
{
- port->buftx[port->buftxwr++] = *(data + i);
- port->buftxwr %= (UARTBUFLEN);
- i++;
+ while(port->txBufferFull)
+ ;
+ port->txBuffer[port->txBufferHead++] = data;
+ port->txBufferHead %= UART_BUFFER_SIZE;
+ if(port->txBufferHead == port->txBufferTail)
+ port->txBufferFull = 1;
+ if(0 == (port->port->CR1 & USART_CR1_TXEIE))
+ port->port->CR1 |= USART_CR1_TXEIE;
}
-
}
-void uart_sendNumber(Uart *port, int32_t n)
+void UartSendString(Uart *port, void *data, uint16_t len)
{
- if(n < 0) uart_sendByte(port, '-');
- n = abs(n);
- if(n > 999999) uart_sendByte(port, (n / 1000000) + 48);
- if(n > 99999) uart_sendByte(port, ((n % 1000000) / 100000) + 48);
- if(n > 9999) uart_sendByte(port, ((n % 100000) / 10000) + 48);
- if(n > 999) uart_sendByte(port, ((n % 10000) / 1000) + 48);
- if(n > 99) uart_sendByte(port, ((n % 1000) / 100) + 48);
- if(n > 9) uart_sendByte(port, ((n % 100) / 10) + 48);
- uart_sendByte(port, (n % 10) + 48);
+ if(0 == len)
+ len = strlen((char*)data);
+
+ for(uint16_t i = 0; i < len; i++)
+ {
+ UartSendByte(port, ((uint8_t*)data)[i]);
+ }
}
-void uartUSB_sendString(uint8_t *data, uint16_t len)
+static unsigned int findHighestPosition(unsigned int n)
{
+ unsigned int i = 1;
+ while((i * 10) <= n)
+ i *= 10;
- if(len == 0)
- {
- len = strlen((char*)data);
- }
- uint16_t i = 0;
- uint8_t j = 0;
- uint16_t k = len;
- //USB is quite specific and data must be send in small packets, say in 40-byte packets
- while(i < len)
- {
- if((k / 40) >= 1)
- {
- CDC_Transmit_FS(&data[j * 40], 40);
- j++;
- k -= 40;
- i += 40;
- }
- else
- {
- CDC_Transmit_FS(&data[i], len - i);
- break;
- }
- }
+ return i;
}
-
-void uartUSB_sendNumber(int32_t n)
+void UartSendNumber(Uart *port, int32_t n)
{
if(n < 0)
- uartUSB_sendByte('-');
+ UartSendByte(port, '-');
n = abs(n);
- if(n > 999999) uartUSB_sendByte((n / 1000000) + 48);
- if(n > 99999) uartUSB_sendByte(((n % 1000000) / 100000) + 48);
- if(n > 9999) uartUSB_sendByte(((n % 100000) / 10000) + 48);
- if(n > 999) uartUSB_sendByte(((n % 10000) / 1000) + 48);
- if(n > 99) uartUSB_sendByte(((n % 1000) / 100) + 48);
- if(n > 9) uartUSB_sendByte(((n % 100) / 10) + 48);
- uartUSB_sendByte((n % 10) + 48);
+ unsigned int position = findHighestPosition(n);
+ while(position)
+ {
+ unsigned int number = n / position;
+ UartSendByte(port, (number + 48));
+ n -= (number * position);
+ position /= 10;
+ }
}
-
-void uart_init(Uart *port, USART_TypeDef *uart, uint32_t baud)
+void UartInit(Uart *port, USART_TypeDef *uart, uint32_t baud)
{
port->port = uart;
port->baudrate = baud;
- port->rxflag = DATA_NOTHING;
- port->txflag = 0;
- port->bufrxidx = 0;
- port->buftxrd = 0;
- port->buftxwr = 0;
+ port->rxType = DATA_NOTHING;
+ port->rxBufferHead = 0;
+ port->txBufferHead = 0;
+ port->txBufferTail = 0;
+ port->txBufferFull = 0;
port->mode = MODE_KISS;
port->enabled = 0;
port->kissTimer = 0;
- memset(port->bufrx, 0, UARTBUFLEN);
- memset(port->buftx, 0, UARTBUFLEN);
+ memset(port->rxBuffer, 0, sizeof(port->rxBuffer));
+ memset(port->txBuffer, 0, sizeof(port->txBuffer));
}
-void uart_config(Uart *port, uint8_t state)
+void UartConfig(Uart *port, uint8_t state)
{
if(port->port == USART1)
{
+ RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
GPIOA->CRH |= GPIO_CRH_MODE9_1;
GPIOA->CRH &= ~GPIO_CRH_CNF9_0;
@@ -293,9 +234,11 @@ void uart_config(Uart *port, uint8_t state)
NVIC_DisableIRQ(USART1_IRQn);
port->enabled = state > 0;
+ port->isUsb = 0;
}
else if(port->port == USART2)
{
+ RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
GPIOA->CRL |= GPIO_CRL_MODE2_1;
GPIOA->CRL &= ~GPIO_CRL_CNF2_0;
@@ -316,14 +259,29 @@ void uart_config(Uart *port, uint8_t state)
NVIC_DisableIRQ(USART2_IRQn);
port->enabled = state > 0;
+ port->isUsb = 0;
+ }
+ else
+ {
+ port->isUsb = 1;
+ port->enabled = state > 0;
}
}
-void uart_clearRx(Uart *port)
+void UartClearRx(Uart *port)
{
- port->bufrxidx = 0;
- port->rxflag = 0;
+ port->rxBufferHead = 0;
+ port->rxType = DATA_NOTHING;
}
+void UartHandleKissTimeout(Uart *port)
+{
+ if((port->kissTimer > 0) && (ticks >= port->kissTimer)) //KISS timer timeout
+ {
+ port->kissTimer = 0;
+ port->rxBufferHead = 0;
+ memset(port->rxBuffer, 0, sizeof(port->rxBuffer));
+ }
+}
diff --git a/Src/drivers/watchdog.c b/Src/drivers/watchdog.c
index adb585b..52e2f14 100644
--- a/Src/drivers/watchdog.c
+++ b/Src/drivers/watchdog.c
@@ -18,7 +18,7 @@ along with VP-Digi. If not, see .
#include "drivers/watchdog.h"
#include "stm32f1xx.h"
-void Wdog_init(void)
+void WdogInit(void)
{
IWDG->KR = 0x5555; //configuration mode
IWDG->PR = 0b101; //prescaler
@@ -27,7 +27,7 @@ void Wdog_init(void)
}
-void Wdog_reset(void)
+void WdogReset(void)
{
IWDG->KR = 0xAAAA; //reset
}
diff --git a/Src/main.c b/Src/main.c
index d608d79..305d7ef 100644
--- a/Src/main.c
+++ b/Src/main.c
@@ -85,103 +85,85 @@ static void MX_GPIO_Init(void);
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
+
/**
- * \brief Handle received frame from RF
+ * @brief Handle received frame
*/
-void handleFrame(void)
+static void handleFrame(void)
{
- uint8_t modemReceived = ax25.frameReceived; //store states
- ax25.frameReceived = 0; //clear flag
+ uint8_t modemBitmap = Ax25GetReceivedFrameBitmap(); //store states
+ Ax25ClearReceivedFrameBitmap();
- uint8_t bufto[FRAMELEN + 30], buf[FRAMELEN]; //buffer for raw frames to TNC2 frames conversion
- uint16_t bufidx = 0;
- uint16_t i = ax25.frameBufRd;
+ uint8_t *buf = NULL;
+ uint16_t size = 0;
+ uint16_t signalLevel = 0;
- while(i != ax25.frameBufWr)
+ while(Ax25ReadNextRxFrame(&buf, &size, &signalLevel))
{
- if(ax25.frameBuf[i] != 0xFF)
- {
- buf[bufidx++] = ax25.frameBuf[i++]; //store frame in temporary buffer
- }
- else
- {
- break;
- }
- i %= (FRAMEBUFLEN);
- }
- ax25.frameBufRd = ax25.frameBufWr;
-
- for(i = 0; i < (bufidx); i++)
- {
- if(buf[i] & 1)
- break; //look for path end bit
- }
+ TermSendToAll(MODE_KISS, buf, size);
- SendKiss(buf, bufidx); //send KISS frames if ports available
-
- if(((USBmode == MODE_MONITOR) || (uart1.mode == MODE_MONITOR) || (uart2.mode == MODE_MONITOR)))
- {
- common_toTNC2(buf, bufidx, bufto); //convert to TNC2 format
-
- //in general, the RMS of the frame is calculated (excluding preamble!)
- //it it calculated from samples ranging from -4095 to 4095 (amplitude of 4095)
- //that should give a RMS of around 2900 for pure sine wave
- //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
- ax25.sLvl /= 9;
-
- if(ax25.sLvl > 100)
+ if(((UartUsb.mode == MODE_MONITOR) || (Uart1.mode == MODE_MONITOR) || (Uart2.mode == MODE_MONITOR)))
{
- term_sendMonitor((uint8_t*)"\r\nInput level too high! Please reduce so most stations are around 50-70%.\r\n", 0);
- }
+ //in general, the RMS of the frame is calculated (excluding preamble!)
+ //it it calculated from samples ranging from -4095 to 4095 (amplitude of 4095)
+ //that should give a RMS of around 2900 for pure sine wave
+ //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
+ signalLevel /= 9;
+
+ if(signalLevel > 100)
+ {
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"\r\nInput level too high! Please reduce so most stations are around 50-70%.\r\n", 0);
+ }
+ else if(signalLevel < 10)
+ {
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"\r\nInput level too low! Please increase so most stations are around 50-70%.\r\n", 0);
+ }
+
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"(AX.25) Frame received [", 0); //show which modem received the frame: [FP] (flat and preemphasized), [FD] (flat and deemphasized - in flat audio input mode)
+ //[F_] (only flat), [_P] (only preemphasized) or [_D] (only deemphasized - in flat audio input mode)
+ for(uint8_t i = 0; i < MODEM_DEMODULATOR_COUNT; i++)
+ {
+ if(modemBitmap & (1 << i))
+ {
+ enum ModemEmphasis m = ModemGetFilterType(i);
+ switch(m)
+ {
+ case PREEMPHASIS:
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"P", 1);
+ break;
+ case DEEMPHASIS:
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"D", 1);
+ break;
+ case EMPHASIS_NONE:
+ default:
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"F", 1);
+ break;
+ }
+ }
+ else
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"_", 1);
+ }
+
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"], signal level ", 0);
+ TermSendNumberToAll(MODE_MONITOR, signalLevel);
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"%: ", 0);
+
+ SendTNC2(buf, size);
+ TermSendToAll(MODE_MONITOR, (uint8_t*)"\r\n", 0);
- if(ax25.sLvl < 10)
- {
- term_sendMonitor((uint8_t*)"\r\nInput level too low! Please increase so most stations are around 50-70%.\r\n", 0);
- }
-
- term_sendMonitor((uint8_t*)"(AX.25) Frame received [", 0); //show which modem received the frame: [FP] (flat and preemphasized), [FD] (flat and deemphasized - in flat audio input mode)
- //[F_] (only flat), [_P] (only preemphasized) or [_D] (only deemphasized - in flat audio input mode)
- uint8_t t[2] = {0};
- if(modemReceived & 1)
- {
- t[0] = 'F';
}
- else
- t[0] = '_';
- if(modemReceived & 2)
- {
- if(afskCfg.flatAudioIn)
- t[1] = 'D';
- else
- t[1] = 'P';
- }
- else
- t[1] = '_';
- term_sendMonitor(t, 2);
- term_sendMonitor((uint8_t*)"], signal level ", 0);
- term_sendMonitorNumber(ax25.sLvl);
- term_sendMonitor((uint8_t*)"%: ", 0);
- term_sendMonitor(bufto, 0);
- term_sendMonitor((uint8_t*)"\r\n", 0);
+ DigiDigipeat(buf, size);
+ free(buf);
}
-
-
- if(digi.enable)
- {
- Digi_digipeat(buf, bufidx);
- }
-
-
-
}
@@ -211,15 +193,16 @@ int main(void)
/* USER CODE BEGIN SysInit */
- SysTick_init();
+ SysTickInit();
//force usb re-enumeration after reset
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; //pull D+ to ground for a moment
GPIOA->CRH |= GPIO_CRH_MODE12_1;
GPIOA->CRH &= ~GPIO_CRH_CNF12;
GPIOA->BSRR = GPIO_BSRR_BR12;
- uint32_t t = ticks + 10;
- while(t > ticks);;
+ uint32_t t = ticks + (100 / SYSTICK_INTERVAL);
+ while(t > ticks)
+ ;
GPIOA->CRH &= ~GPIO_CRH_MODE12;
GPIOA->CRH |= GPIO_CRH_CNF12_0;
@@ -233,117 +216,110 @@ int main(void)
- Wdog_init(); //initialize watchdog
+ WdogInit(); //initialize watchdog
+ memset(&beacon, 0, sizeof(beacon));
+ memset(&Ax25Config, 0, sizeof(Ax25Config));
+ memset(&ModemConfig, 0, sizeof(ModemConfig));
+ memset(&DigiConfig, 0, sizeof(DigiConfig));
//set some initial values in case there is no configuration saved in memory
- uart1.baudrate = 9600;
- uart2.baudrate = 9600;
- afskCfg.usePWM = 0;
- afskCfg.flatAudioIn = 0;
- ax25Cfg.quietTime = 300;
- ax25Cfg.txDelayLength = 300;
- ax25Cfg.txTailLength = 30;
- digi.dupeTime = 30;
-
- Config_read();
+ Uart1.baudrate = 9600;
+ Uart2.baudrate = 9600;
+ ModemConfig.usePWM = 0;
+ ModemConfig.flatAudioIn = 0;
+ Ax25Config.quietTime = 300;
+ Ax25Config.txDelayLength = 300;
+ Ax25Config.txTailLength = 30;
+ DigiConfig.dupeTime = 30;
- Ax25_init();
+ ConfigRead();
- uart_init(&uart1, USART1, uart1.baudrate);
- uart_init(&uart2, USART2, uart2.baudrate);
+ Ax25Init();
- uart_config(&uart1, 1);
- uart_config(&uart2, 1);
+ UartInit(&Uart1, USART1, Uart1.baudrate);
+ UartInit(&Uart2, USART2, Uart2.baudrate);
+ UartInit(&UartUsb, NULL, 1);
- Afsk_init();
- Beacon_init();
+ UartConfig(&Uart1, 1);
+ UartConfig(&Uart2, 1);
+ UartConfig(&UartUsb, 1);
-
- autoResetTimer = autoReset * 360000;
+ ModemInit();
+ BeaconInit();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
- static uint32_t usbKissTimer = 0;
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
- Wdog_reset();
+ WdogReset();
- if(ax25.frameReceived)
+ if(Ax25GetReceivedFrameBitmap())
handleFrame();
- Digi_viscousRefresh(); //refresh viscous-delay buffers
-
-
- Ax25_transmitBuffer(); //transmit buffer (will return if nothing to be transmitted)
-
- Ax25_transmitCheck(); //check for pending transmission request
-
- if(USBint) //USB "interrupt"
+ DigiViscousRefresh(); //refresh viscous-delay buffers
+
+ Ax25TransmitBuffer(); //transmit buffer (will return if nothing to be transmitted)
+
+ 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)
{
- 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;
- }
+ TermParse(&UartUsb);
+ UartClearRx(&UartUsb);
}
-
- if((usbKissTimer > 0) && (ticks >= usbKissTimer)) //USB KISS timer timeout
- {
- usbcdcidx = 0;
- memset(usbcdcdata, 0, UARTBUFLEN);
- usbKissTimer = 0;
- }
-
-
- if(USBrcvd != DATA_NOTHING)
+ if(Uart1.rxType != DATA_NOTHING)
{
- term_parse(usbcdcdata, usbcdcidx, TERM_USB, USBrcvd, USBmode);
- USBrcvd = DATA_NOTHING;
- usbcdcidx = 0;
- memset(usbcdcdata, 0, UARTBUFLEN);
+ TermParse(&Uart1);
+ UartClearRx(&Uart1);
}
- if(uart1.rxflag != DATA_NOTHING)
+ if(Uart2.rxType != DATA_NOTHING)
{
- term_parse(uart1.bufrx, uart1.bufrxidx, TERM_UART1, uart1.rxflag, uart1.mode);
- uart1.rxflag = DATA_NOTHING;
- uart1.bufrxidx = 0;
- memset(uart1.bufrx, 0, UARTBUFLEN);
- }
- if(uart2.rxflag != DATA_NOTHING)
- {
- term_parse(uart2.bufrx, uart2.bufrxidx, TERM_UART2, uart2.rxflag, uart2.mode);
- uart2.rxflag = DATA_NOTHING;
- uart2.bufrxidx = 0;
- memset(uart2.bufrx, 0, UARTBUFLEN);
+ TermParse(&Uart2);
+ UartClearRx(&Uart2);
}
+ UartHandleKissTimeout(&UartUsb);
- Beacon_check(); //check beacons
+ BeaconCheck(); //check beacons
- if(((autoResetTimer != 0) && (ticks > autoResetTimer)) || (ticks > 4294960000))
+ if(ticks > 0xFFFFF000)
NVIC_SystemReset();
-
-
-
}
/* USER CODE END 3 */
}
diff --git a/Src/terminal.c b/Src/terminal.c
index 361bd1e..2b931db 100644
--- a/Src/terminal.c
+++ b/Src/terminal.c
@@ -1,5 +1,5 @@
/*
-This file is part of VP-Digi.
+This file is part of VP-DigiConfig.
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
@@ -12,7 +12,7 @@ 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 .
+along with VP-DigiConfig. If not, see .
*/
#include "terminal.h"
@@ -23,738 +23,536 @@ along with VP-Digi. If not, see .
#include "drivers/modem.h"
#include "ax25.h"
-uint8_t termBuf[TERMBUFLEN]; //terminal mode TX buffer
-uint16_t termBufIdx = 0; //terminal mode TX buffer index
-
-uint16_t spLastIdx[3] = {0, 0, 0}; //index buffer was "special" terminal cases
+//uint16_t spLastIdx[3] = {0, 0, 0}; //index buffer was "special" terminal cases
/**
* @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)
+//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)
{
- 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))
+ if(port->mode == MODE_KISS) //check if KISS mode
{
- 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);
+ UartSendByte(port, 0xc0); //send data in kiss format
+ UartSendByte(port, 0x00);
+ UartSendString(port, buf, len);
+ UartSendByte(port, 0xc0);
}
-
}
-/**
- * \brief Send data to all available monitor outputs
- * \param[in] *data Data to send
- * \param[in] len Data length or 0 for NULL-terminated data
- */
-void term_sendMonitor(uint8_t *data, uint16_t len)
+void TermSendToAll(enum UartMode mode, uint8_t *data, uint16_t size)
{
- if(USBmode == MODE_MONITOR)
- {
- uartUSB_sendString(data, len);
- }
- if((uart1.enabled) && (uart1.mode == MODE_MONITOR))
+ if(MODE_KISS == mode)
{
- uart_sendString(&uart1, data, len);
- uart_transmitStart(&uart1);
+ sendKiss(&Uart1, data, size);
+ sendKiss(&Uart2, data, size);
+ sendKiss(&UartUsb, data, size);
}
- if((uart2.enabled) && (uart2.mode == MODE_MONITOR))
+ else if(MODE_MONITOR == mode)
{
- uart_sendString(&uart2, data, len);
- uart_transmitStart(&uart2);
+ if(UartUsb.mode == MODE_MONITOR)
+ UartSendString(&UartUsb, data, size);
+ if(Uart1.mode == MODE_MONITOR)
+ UartSendString(&Uart1, data, size);
+ if(Uart2.mode == MODE_MONITOR)
+ UartSendString(&Uart2, data, size);
}
+
}
-/**
- * \brief Send number to all available monitor outputs
- * \param[in] data Number to send
- */
-void term_sendMonitorNumber(int32_t data)
+void TermSendNumberToAll(enum UartMode mode, int32_t n)
{
- if(USBmode == MODE_MONITOR)
- {
- uartUSB_sendNumber(data);
- }
- if((uart1.enabled) && (uart1.mode == MODE_MONITOR))
- {
- uart_sendNumber(&uart1, data);
- uart_transmitStart(&uart1);
- }
- if((uart2.enabled) && (uart2.mode == MODE_MONITOR))
+ if(MODE_MONITOR == mode)
{
- uart_sendNumber(&uart2, data);
- uart_transmitStart(&uart2);
+ if(UartUsb.mode == MODE_MONITOR)
+ UartSendNumber(&UartUsb, n);
+ if(Uart1.mode == MODE_MONITOR)
+ UartSendNumber(&Uart1, n);
+ if(Uart2.mode == MODE_MONITOR)
+ UartSendNumber(&Uart2, n);
}
+
}
-/**
-* \brief Send terminal buffer using specified stream
-* \param[in] way Stream: TERM_ANY, TERM_USB, TERM_UART1, TERM_UART2
-*/
-void term_sendBuf(Terminal_stream way)
+
+
+
+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"
+ "\tlow - transmits MARK tone, high - transmits SPACE tone, alt - transmits alternating tones (null bytes)\r\n"
+ "beacon - immediately transmits selected beacon (number from 0 to 7)\r\n"
+ "kiss - switches to KISS mode\r\n"
+ "config - switches to config mode\r\n"
+ "reboot - reboots the device\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"
+ "print - prints all configuration parameters\r\n"
+ "list - prints callsign filter list\r\n"
+ "save - saves configuration and reboots the device\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"
+ "version - shows full firmware version info\r\n\r\n"
+ "call - sets callsign with optional SSID\r\n"
+ "dest - sets destination address\r\n"
+ "txdelay <50-2550> - sets TXDelay time (ms)\r\n"
+ "txtail <10-2550> - sets TXTail time (ms)\r\n"
+ "quiet <100-2550> - sets quiet time (ms)\r\n"
+ "rs1baud/rs2baud <1200-115200> - sets UART1/UART2 baudrate\r\n"
+ "pwm [on/off] - enables/disables PWM. If PWM is off, R2R will be used instead\r\n"
+ "flat [on/off] - set to \"on\" if flat audio input is used\r\n"
+ "beacon <0-7> [on/off] - enables/disables specified beacon\r\n"
+ "beacon <0-7> [iv/dl] <0-720> - sets interval/delay for the specified beacon (min)\r\n"
+ "beacon <0-7> path /none - sets path for the specified beacon\r\n"
+ "beacon <0-7> data - sets information field for the specified beacon\r\n"
+ "digi [on/off] - enables/disables whole digipeater\r\n"
+ "digi <0-7> [on/off] - enables/disables specified slot\r\n"
+ "digi <0-7> alias - sets alias for the specified slot\r\n"
+ "digi <0-3> [max/rep] <0/1-7> - sets maximum/replacement N for the specified slot\r\n"
+ "digi <0-7> trac [on/off] - enables/disables packet tracing for the specified slot\r\n"
+ "digi <0-7> viscous [on/off] - enables/disables viscous-delay digipeating for the specified slot\r\n"
+ "digi <0-7> direct [on/off] - enables/disables direct-only digipeating for the specified slot\r\n"\
+ "digi <0-7> filter [on/off] - enables/disables packet filtering for the specified slot\r\n"
+ "digi filter [black/white] - sets filtering type to blacklist/whitelist\r\n"
+ "digi dupe <5-255> - sets anti-dupe buffer time (s)\r\n"
+ "digi list <0-19> [set /remove] - sets/clears specified callsign slot in filter list\r\n"
+ "monkiss [on/off] - send own and digipeated frames to KISS ports\r\n"
+ "nonaprs [on/off] - enable reception of non-APRS frames\r\n";
+
+
+
+static void printConfig(Uart *src)
{
- if((way == TERM_USB) || (way == TERM_ANY))
+ UartSendString(src, "Callsign: ", 0);
+ for(uint8_t i = 0; i < 6; i++)
{
- uartUSB_sendString(termBuf, termBufIdx);
+ if(GeneralConfig.call[i] != (' ' << 1))
+ UartSendByte(src, GeneralConfig.call[i] >> 1);
}
- if((way == TERM_UART1) || (way == TERM_ANY))
+ UartSendByte(src, '-');
+ UartSendNumber(src, GeneralConfig.callSsid);
+
+ UartSendString(src, "\r\nDestination: ", 0);
+ for(uint8_t i = 0; i < 6; i++)
{
- for(uint16_t d = 0; d < termBufIdx; d++)
- {
- uart_sendByte(&uart1, termBuf[d]);
- }
- uart_transmitStart(&uart1);
+ if(GeneralConfig.dest[i] != (' ' << 1))
+ UartSendByte(src, GeneralConfig.dest[i] >> 1);
}
- if((way == TERM_UART2) || (way == TERM_ANY))
+
+ UartSendString(src, "\r\nTXDelay (ms): ", 0);
+ UartSendNumber(src, Ax25Config.txDelayLength);
+ UartSendString(src, "\r\nTXTail (ms): ", 0);
+ UartSendNumber(src, Ax25Config.txTailLength);
+ UartSendString(src, "\r\nQuiet time (ms): ", 0);
+ UartSendNumber(src, Ax25Config.quietTime);
+ UartSendString(src, "\r\nUART1 baudrate: ", 0);
+ UartSendNumber(src, Uart1.baudrate);
+ UartSendString(src, "\r\nUART2 baudrate: ", 0);
+ UartSendNumber(src, Uart2.baudrate);
+ UartSendString(src, "\r\nDAC type: ", 0);
+ if(ModemConfig.usePWM)
+ UartSendString(src, "PWM", 0);
+ else
+ UartSendString(src, "R2R", 0);
+ UartSendString(src, "\r\nFlat audio input: ", 0);
+ if(ModemConfig.flatAudioIn)
+ UartSendString(src, "yes", 0);
+ else
+ UartSendString(src, "no", 0);
+ for(uint8_t i = 0; i < (sizeof(beacon) / sizeof(*beacon)); i++)
{
- for(uint16_t d = 0; d < termBufIdx; d++)
- {
- uart_sendByte(&uart2, termBuf[d]);
+ UartSendString(src, "\r\nBeacon ", 0);
+ UartSendByte(src, i + '0');
+ UartSendString(src, ": ", 0);
+ if(beacon[i].enable)
+ UartSendString(src, "On, Iv: ", 0);
+ else
+ UartSendString(src, "Off, Iv: ", 0);
+ UartSendNumber(src, beacon[i].interval / 6000);
+ UartSendString(src, ", Dl: ", 0);
+ UartSendNumber(src, beacon[i].delay / 60);
+ UartSendByte(src, ',');
+ UartSendByte(src, ' ');
+ if(beacon[i].path[0] != 0)
+ {
+ for(uint8_t j = 0; j < 6; j++)
+ {
+ if(beacon[i].path[j] != (' ' << 1))
+ UartSendByte(src, beacon[i].path[j] >> 1);
+ }
+ UartSendByte(src, '-');
+ UartSendNumber(src, beacon[i].path[6]);
+ if(beacon[i].path[7] != 0)
+ {
+ UartSendByte(src, ',');
+ for(uint8_t j = 7; j < 13; j++)
+ {
+ if(beacon[i].path[j] != (' ' << 1))
+ UartSendByte(src, beacon[i].path[j] >> 1);
+ }
+ UartSendByte(src, '-');
+ UartSendNumber(src, beacon[i].path[13]);
+ }
}
- uart_transmitStart(&uart2);
+ else
+ UartSendString(src, "no path", 0);
+ UartSendByte(src, ',');
+ UartSendByte(src, ' ');
+ UartSendString(src, beacon[i].data, 0);
}
- termBufIdx = 0;
-}
-/**
- * \brief Push byte to terminal buffer
- * \param[in] data Byte to store
- */
-void term_sendByte(uint8_t data)
-{
- if(termBufIdx > TERMBUFLEN - 1)
- return;
- termBuf[termBufIdx++] = data;
-}
+ UartSendString(src, "\r\nDigipeater: ", 0);
+ if(DigiConfig.enable)
+ UartSendString(src, "On\r\n", 0);
+ else
+ UartSendString(src, "Off\r\n", 0);
-/**
- * \brief Push string to terminal buffer
- * \param[in] *data String
- * \param[in] len String length or 0 for NULL-terminated string
- */
-void term_sendString(uint8_t *data, uint16_t len)
-{
- if(len != 0)
+ for(uint8_t i = 0; i < 4; i++) //n-N aliases
{
- for(uint16_t y= 0; y < len; y++)
+ UartSendString(src, "Alias ", 0);
+ if(DigiConfig.alias[i][0] != 0)
{
- if(termBufIdx > TERMBUFLEN - 1) break;
- termBuf[termBufIdx++] = *data;
- data++;
+ for(uint8_t j = 0; j < 5; j++)
+ {
+ if(DigiConfig.alias[i][j] != 0)
+ UartSendByte(src, DigiConfig.alias[i][j] >> 1);
+ else
+ break;
+ }
}
- } else
+ UartSendString(src, ": ", 0);
+ if(DigiConfig.enableAlias & (1 << i))
+ UartSendString(src, "On, max: ", 0);
+ else
+ UartSendString(src, "Off, max: ", 0);
+ UartSendNumber(src, DigiConfig.max[i]);
+ UartSendString(src, ", rep: ", 0);
+ UartSendNumber(src, DigiConfig.rep[i]);
+ if(DigiConfig.traced & (1 << i))
+ UartSendString(src, ", traced, ", 0);
+ else
+ UartSendString(src, ", untraced, ", 0);
+ if(DigiConfig.viscous & (1 << i))
+ UartSendString(src, "viscous-delay, ", 0);
+ else if(DigiConfig.directOnly & (1 << i))
+ UartSendString(src, "direct-only, ", 0);
+ if(DigiConfig.callFilterEnable & (1 << i))
+ UartSendString(src, "filtered\r\n", 0);
+ else
+ UartSendString(src, "unfiltered\r\n", 0);
+ }
+ for(uint8_t i = 0; i < 4; i++) //simple aliases
{
- while(*data != 0)
+ UartSendString(src, "Alias ", 0);
+ if(DigiConfig.alias[i + 4][0] != 0)
{
- if(termBufIdx > TERMBUFLEN - 1) break;
- termBuf[termBufIdx++] = *data;
- data++;
- if(termBufIdx > TERMBUFLEN) break;
+ for(uint8_t j = 0; j < 6; j++)
+ {
+ if(DigiConfig.alias[i + 4][j] != 64)
+ UartSendByte(src, DigiConfig.alias[i + 4][j] >> 1);
+ }
}
+ UartSendByte(src, '-');
+ UartSendNumber(src, DigiConfig.ssid[i]);
+ UartSendString(src, ": ", 0);
+ if(DigiConfig.enableAlias & (1 << (i + 4)))
+ UartSendString(src, "On, ", 0);
+ else
+ UartSendString(src, "Off, ", 0);
+ if(DigiConfig.traced & (1 << (i + 4)))
+ UartSendString(src, "traced, ", 0);
+ else
+ UartSendString(src, "untraced, ", 0);
+ if(DigiConfig.viscous & (1 << (i + 4)))
+ UartSendString(src, "viscous-delay, ", 0);
+ else if(DigiConfig.directOnly & (1 << (i + 4)))
+ UartSendString(src, "direct-only, ", 0);
+ if(DigiConfig.callFilterEnable & (1 << (i + 4)))
+ UartSendString(src, "filtered\r\n", 0);
+ else
+ UartSendString(src, "unfiltered\r\n", 0);
}
- termBuf[termBufIdx] = 0;
-}
-
-/**
- * \brief Push number (in ASCII form) in terminal buffer
- * \param[in] n Number
- */
-void term_sendNumber(int32_t n)
-{
- if(n < 0)
- n = abs(n);
- if(n > 999999) term_sendByte((n / 1000000) + 48);
- if(n > 99999) term_sendByte(((n % 1000000) / 100000) + 48);
- if(n > 9999) term_sendByte(((n % 100000) / 10000) + 48);
- if(n > 999) term_sendByte(((n % 10000) / 1000) + 48);
- if(n > 99) term_sendByte(((n % 1000) / 100) + 48);
- if(n > 9) term_sendByte(((n % 100) / 10) + 48);
- term_sendByte((n % 10) + 48);
-}
-
-/**
- * \brief Chceck if received data and command are matching
- * \param[in] *data Received data
- * \param[in] dlen Data length
- * \param[in] *cmd Command
- * \return 1 if matching, 0 if not
- */
-static uint8_t checkcmd(uint8_t *data, uint8_t dlen, uint8_t *cmd)
-{
- for(uint8_t a = 0; a < dlen; a++)
+ UartSendString(src, "Anti-duplicate buffer hold time (s): ", 0);
+ UartSendNumber(src, DigiConfig.dupeTime);
+ UartSendString(src, "\r\nCallsign filter type: ", 0);
+ if(DigiConfig.filterPolarity)
+ UartSendString(src, "whitelist\r\n", 0);
+ else
+ UartSendString(src, "blacklist\r\n", 0);
+ UartSendString(src, "Callsign filter list: ", 0);
+ uint8_t entries = 0;
+ for(uint8_t i = 0; i < 20; i++)
{
- if(*(data + a) != *(cmd + a))
- return 0;
+ if(DigiConfig.callFilter[i][0] != 0)
+ entries++;
}
- return 1;
+ UartSendNumber(src, entries);
+ UartSendString(src, " entries\r\nKISS monitor: ", 0);
+ if(GeneralConfig.kissMonitor == 1)
+ UartSendString(src, "On\r\n", 0);
+ else
+ UartSendString(src, "Off\r\n", 0);
+ UartSendString(src, "Allow non-APRS frames: ", 0);
+ if(Ax25Config.allowNonAprs == 1)
+ UartSendString(src, "On\r\n", 0);
+ else
+ UartSendString(src, "Off\r\n", 0);
}
-/**
- * \brief Parse and process received data
- * \param[in] *cmd Data
- * \param[in] len Data length
- * \param[in] src Source: TERM_USB, TERM_UART1, TERM_UART2
- * \param[in] type Data type: DATA_KISS, DATA_TERM
- * \param[in] mode Input mode: MODE_KISS, MODE_TERM, MODE_MONITOR
- */
-void term_parse(uint8_t *cmd, uint16_t len, Terminal_stream src, Uart_data_type type, Uart_mode mode)
-{
- if(src == TERM_ANY) //incorrect source
- return;
- if(checkcmd(cmd, 4, (uint8_t*)"kiss"))
+void TermParse(Uart *src)
+{
+ const char *cmd = (char*)src->rxBuffer;
+ uint16_t len = src->rxBufferHead;
+ for(uint16_t i = 0; i < len; i++)
{
- if(src == TERM_USB)
- {
- term_sendString((uint8_t*)"USB switched to KISS mode\r\n", 0);
- term_sendBuf(TERM_USB);
- USBmode = MODE_KISS;
- }
- else if(src == TERM_UART1)
- {
- term_sendString((uint8_t*)"UART1 switched to KISS mode\r\n", 0);
- term_sendBuf(TERM_UART1);
- uart1.mode = MODE_KISS;
- }
- else if(src == TERM_UART2)
+ if((cmd[i] == '\r') || (cmd[i] == '\n'))
{
- term_sendString((uint8_t*)"UART2 switched to KISS mode\r\n", 0);
- term_sendBuf(TERM_UART2);
- uart2.mode = MODE_KISS;
+ len = i;
+ break;
}
- return;
}
- if(checkcmd(cmd, 6, (uint8_t*)"config"))
+ /*
+ * Terminal mode switching commands
+ */
+ if(!strncmp(cmd, "kiss", 4))
{
- term_sendString((uint8_t*)"Switched to configuration mode\r\n"
- "Most settings will take effect immidiately, but\r\n"
+ UartSendString(src, (uint8_t*)"Switched to KISS mode\r\n", 0);
+ src->mode = MODE_KISS;
+ return;
+ }
+ else if(!strncmp(cmd, "config", 6))
+ {
+ UartSendString(src, (uint8_t*)"Switched to configuration mode\r\n"
+ "Most settings will take effect immediately, but\r\n"
"remember to save the configuration using \"save\"\r\n", 0);
- if(src == TERM_USB)
- {
- term_sendBuf(TERM_USB);
- USBmode = MODE_TERM;
- }
- else if(src == TERM_UART1)
- {
- term_sendBuf(TERM_UART1);
- uart1.mode = MODE_TERM;
- }
- else if(src == TERM_UART2)
- {
- term_sendBuf(TERM_UART2);
- uart2.mode = MODE_TERM;
- }
+ src->mode = MODE_TERM;
return;
}
-
- if(checkcmd(cmd, 7, (uint8_t*)"monitor"))
+ else if(!strncmp(cmd, "monitor", 7))
{
- if(src == TERM_USB)
- {
- term_sendString((uint8_t*)"USB switched to monitor mode\r\n", 0);
- term_sendBuf(TERM_USB);
- USBmode = MODE_MONITOR;
- }
- else if(src == TERM_UART1)
- {
- term_sendString((uint8_t*)"UART1 switched to monitor mode\r\n", 0);
- term_sendBuf(TERM_UART1);
- uart1.mode = MODE_MONITOR;
- }
- else if(src == TERM_UART2)
- {
- term_sendString((uint8_t*)"UART2 switched to monitor mode\r\n", 0);
- term_sendBuf(TERM_UART2);
- uart2.mode = MODE_MONITOR;
- }
+ UartSendString(src, (uint8_t*)"USB switched to monitor mode\r\n", 0);
+ src->mode = MODE_MONITOR;
return;
}
-
- if((mode == MODE_KISS) && (type == DATA_KISS))
+ /*
+ * KISS parsing
+ */
+ else if((src->mode == MODE_KISS) && (src->rxType == DATA_KISS))
{
- Uart_txKiss(cmd, len); //if received KISS data, transmit KISS frame
+ //Uart_txKiss(cmd, len); //if received KISS data, transmit KISS frame
return;
}
-
- if((mode == MODE_MONITOR) && (type == DATA_TERM)) //monitor mode
+ /*
+ * Monitor mode handling
+ */
+ else if((src->mode == MODE_MONITOR) && (src->rxType == DATA_TERM)) //monitor mode
{
- if(checkcmd(cmd, 4, (uint8_t*)"help"))
+ if(!strncmp(cmd, "help", 4))
{
- term_sendString((uint8_t*)"\r\nCommans available in monitor mode:\r\n", 0);
- term_sendString((uint8_t*)"help - shows this help page\r\n", 0);
- term_sendString((uint8_t*)"cal {low|high|alt|stop} - transmits/stops transmitter calibration pattern\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"\tlow - transmits MARK tone, high - transmits SPACE tone, alt - transmits alternating tones (null bytes)\r\n", 0);
- term_sendString((uint8_t*)"beacon - immediately transmits selected beacon (number from 0 to 7)\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"kiss - switches to KISS mode\r\n", 0);
- term_sendString((uint8_t*)"config - switches to config mode\r\n", 0);
- term_sendString((uint8_t*)"reboot - reboots the device\r\n", 0);
- term_sendString((uint8_t*)"version - shows full firmware version info\r\n\r\n\r\n", 0);
- term_sendBuf(src);
- return;
+ UartSendString(src, (char *)monitorHelp, 0);
}
- if(checkcmd(cmd, 7, (uint8_t*)"version"))
+ else if(!strncmp(cmd, "version", 7))
{
- term_sendString((uint8_t*)versionString, 0);
- term_sendBuf(src);
- return;
+ UartSendString(src, (char *)versionString, 0);
}
- if(checkcmd(cmd, 6, (uint8_t*)"reboot"))
+ else if(!strncmp(cmd, "reboot", 6))
{
NVIC_SystemReset();
- return;
}
- if(checkcmd(cmd, 7, (uint8_t*)"beacon "))
+ else if(!strncmp(cmd, "beacon ", 7))
{
- if((cmd[7] > 47) && (cmd[7] < 56))
+ if((cmd[7] >= '0') && (cmd[7] <= '7'))
{
- uint8_t bcno = cmd[7] - 48;
- if((beacon[bcno].interval != 0) && (beacon[bcno].enable != 0))
+ uint8_t number = cmd[7] - '0';
+ if((beacon[number].interval != 0) && (beacon[number].enable != 0))
{
- Beacon_send(bcno);
- return;
+ BeaconSend(number);
}
else
{
- term_sendString((uint8_t*)"Beacon " , 0);
- term_sendNumber(bcno);
- term_sendString((uint8_t*)" not enabled. Cannot transmit disabled beacons.\r\n", 0);
- term_sendBuf(src);
+ UartSendString(src, "Beacon " , 0);
+ UartSendNumber(src, number);
+ UartSendString(src, " is not enabled. Cannot transmit disabled beacons.\r\n", 0);
}
- return;
}
else
{
- term_sendString((uint8_t*)"Beacon number must be within 0-7 range\r\n", 0);
- term_sendBuf(src);
- return;
+ UartSendString(src, "Beacon number must be in range of 0 to 7.\r\n", 0);
}
}
-
- if(checkcmd(cmd, 3, (uint8_t*)"cal"))
+ else if(!strncmp(cmd, "cal", 3))
{
- if(checkcmd(&cmd[4], 3, (uint8_t*)"low"))
- {
- term_sendString((uint8_t*)"Starting low tone calibration transmission\r\n", 0);
- term_sendBuf(src);
- Afsk_txTestStart(TEST_MARK);
- return;
- }
- else if(checkcmd(&cmd[4], 4, (uint8_t*)"high"))
- {
- term_sendString((uint8_t*)"Starting high tone calibration transmission\r\n", 0);
- term_sendBuf(src);
- Afsk_txTestStart(TEST_SPACE);
- return;
- }
- else if(checkcmd(&cmd[4], 3, (uint8_t*)"alt"))
- {
- term_sendString((uint8_t*)"Starting alternating tones calibration pattern transmission\r\n", 0);
- term_sendBuf(src);
- Afsk_txTestStart(TEST_ALTERNATING);
- return;
- }
- else if(checkcmd(&cmd[4], 4, (uint8_t*)"stop"))
- {
- term_sendString((uint8_t*)"Stopping calibration transmission\r\n", 0);
- term_sendBuf(src);
- Afsk_txTestStop();
- return;
- }
- term_sendString((uint8_t*)"Usage: cal {low|high|alt|stop}\r\n", 0);
- term_sendBuf(src);
- return;
+ if(!strncmp(&cmd[4], "low", 3))
+ {
+ UartSendString(src, "Starting low tone calibration transmission\r\n", 0);
+ ModemTxTestStart(TEST_MARK);
+ }
+ else if(!strncmp(&cmd[4], "high", 4))
+ {
+ UartSendString(src, "Starting high tone calibration transmission\r\n", 0);
+ ModemTxTestStart(TEST_SPACE);
+ }
+ else if(!strncmp(&cmd[4], "alt", 3))
+ {
+ UartSendString(src, "Starting alternating tones calibration transmission\r\n", 0);
+ ModemTxTestStart(TEST_ALTERNATING);
+ }
+ else if(!strncmp(&cmd[4], "stop", 4))
+ {
+ UartSendString(src, "Stopping calibration transmission\r\n", 0);
+ ModemTxTestStop();
+ }
+ else
+ UartSendString(src, "Usage: cal {low|high|alt|stop}\r\n", 0);
}
+ else
+ UartSendString(src, "Unknown command. For command list type \"help\"\r\n", 0);
- term_sendString((uint8_t*)"Unknown command. For command list type \"help\"\r\n", 0);
- term_sendBuf(src);
return;
}
- if((mode != MODE_TERM)) return;
+ if(src->mode != MODE_TERM)
+ return;
+
+ /*
+ * Configuration mode handling
+ *
+ * General commands
+ */
+ bool err = false;
- if(checkcmd(cmd, 4, (uint8_t*)"help"))
+ if(!strncmp(cmd, "help", 4))
{
- term_sendString((uint8_t*)"\r\nCommands available in config mode:\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"print - prints all configuration parameters\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"list - prints callsign filter list\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"save - saves configuration and reboots the device\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"eraseall - erases all configurations and reboots the device\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"help - shows this help page\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"reboot - reboots the device\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"version - shows full firmware version info\r\n\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"call - sets callsign\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"ssid <0-15> - sets SSID\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"dest - sets destination address\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"txdelay <50-2550> - sets TXDelay time (ms)\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"txtail <10-2550> - sets TXTail time (ms)\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"quiet <100-2550> - sets quiet time (ms)\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"rs1baud/rs2baud <1200-115200> - sets UART1/UART2 baudrate\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"pwm [on/off] - enables/disables PWM. If PWM is off, R2R will be used instead\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"flat [on/off] - set to \"on\" if flat audio input is used\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"beacon <0-7> [on/off] - enables/disables specified beacon\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"beacon <0-7> [iv/dl] <0-720> - sets interval/delay for the specified beacon (min)\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"beacon <0-7> path /none - sets path for the specified beacon\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"beacon <0-7> data - sets information field for the specified beacon\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"digi [on/off] - enables/disables whole digipeater\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"digi <0-7> [on/off] - enables/disables specified slot\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"digi <0-7> alias - sets alias for the specified slot\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"digi <0-3> [max/rep] <0/1-7> - sets maximum/replacement N for the specified slot\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"digi <0-7> trac [on/off] - enables/disables packet tracing for the specified slot\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"digi <0-7> viscous [on/off] - enables/disables viscous-delay digipeating for the specified slot\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"digi <0-7> direct [on/off] - enables/disables direct-only digipeating for the specified slot\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"digi <0-7> filter [on/off] - enables/disables packet filtering for the specified slot\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"digi filter [black/white] - sets filtering type to blacklist/whitelist\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"digi dupe <5-255> - sets anti-dupe buffer time (s)\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"digi list <0-19> [set /remove] - sets/clears specified callsign slot in filter list\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"autoreset <0-255> - sets auto-reset interval (h) - 0 to disable\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"monkiss [on/off] - send own and digipeated frames to KISS ports\r\n", 0);
- term_sendBuf(src);
- term_sendString((uint8_t*)"nonaprs [on/off] - enable reception of non-APRS frames\r\n", 0);
- term_sendBuf(src);
- return;
+ UartSendString(src, (uint8_t*)configHelp, 0);
}
- if(checkcmd(cmd, 7, (uint8_t*)"version"))
+ else if(!strncmp(cmd, "version", 7))
{
- term_sendString((uint8_t*)versionString, 0);
- term_sendBuf(src);
- return;
+ UartSendString(src, (uint8_t*)versionString, 0);
}
- if(checkcmd(cmd, 6, (uint8_t*)"reboot"))
+ else if(!strncmp(cmd, "reboot", 6))
{
NVIC_SystemReset();
- return;
}
- if(checkcmd(cmd, 4, (uint8_t*)"save"))
+ else if(!strncmp(cmd, "save", 4))
{
- Config_write();
+ ConfigWrite();
NVIC_SystemReset();
- return;
}
- if(checkcmd(cmd, 8, (uint8_t*)"eraseall"))
+ else if(!strncmp(cmd, "eraseall", 8))
{
- Config_erase();
+ ConfigErase();
NVIC_SystemReset();
- return;
}
-
- if(checkcmd(cmd, 5, (uint8_t*)"print"))
+ else if(!strncmp(cmd, "print", 5))
{
- term_sendString((uint8_t*)"Callsign: ", 0);
- for(uint8_t i = 0; i < 6; i++)
- {
- if((call[i]) != 64)
- term_sendByte(call[i] >> 1);
- }
- term_sendByte('-');
- term_sendNumber(callSsid);
-
- term_sendString((uint8_t*)"\r\nDestination: ", 0);
- for(uint8_t i = 0; i < 6; i++)
- {
- if((dest[i]) != 64)
- term_sendByte(dest[i] >> 1);
- }
-
- term_sendString((uint8_t*)"\r\nTXDelay (ms): ", 0);
- term_sendNumber(ax25Cfg.txDelayLength);
- term_sendString((uint8_t*)"\r\nTXTail (ms): ", 0);
- term_sendNumber(ax25Cfg.txTailLength);
- term_sendString((uint8_t*)"\r\nQuiet time (ms): ", 0);
- term_sendNumber(ax25Cfg.quietTime);
- term_sendString((uint8_t*)"\r\nUART1 baudrate: ", 0);
- term_sendNumber(uart1.baudrate);
- term_sendString((uint8_t*)"\r\nUART2 baudrate: ", 0);
- term_sendNumber(uart2.baudrate);
- term_sendString((uint8_t*)"\r\nDAC type: ", 0);
- if(afskCfg.usePWM)
- term_sendString((uint8_t*)"PWM", 0);
- else
- term_sendString((uint8_t*)"R2R", 0);
- term_sendString((uint8_t*)"\r\nFlat audio input: ", 0);
- if(afskCfg.flatAudioIn)
- term_sendString((uint8_t*)"yes", 0);
- else
- term_sendString((uint8_t*)"no", 0);
- term_sendBuf(src);
- for(uint8_t i = 0; i < 8; i++)
- {
- term_sendString((uint8_t*)"\r\nBeacon ", 0);
- term_sendByte(i + 48);
- term_sendString((uint8_t*)": ", 0);
- if(beacon[i].enable)
- term_sendString((uint8_t*)"On, Iv: ", 0);
- else
- term_sendString((uint8_t*)"Off, Iv: ", 0);
- term_sendNumber(beacon[i].interval / 6000);
- term_sendString((uint8_t*)", Dl: ", 0);
- term_sendNumber(beacon[i].delay / 60);
- term_sendByte(',');
- term_sendByte(' ');
- if(beacon[i].path[0] != 0)
- {
- for(uint8_t j = 0; j < 6; j++)
- {
- if(beacon[i].path[j] != 32) term_sendByte(beacon[i].path[j]);
- }
- term_sendByte('-');
- term_sendNumber(beacon[i].path[6]);
- if(beacon[i].path[7] != 0)
- {
- term_sendByte(',');
- for(uint8_t j = 7; j < 13; j++)
- {
- if(beacon[i].path[j] != 32) term_sendByte(beacon[i].path[j]);
- }
- term_sendByte('-');
- term_sendNumber(beacon[i].path[13]);
- }
- }
- else term_sendString((uint8_t*)"no path", 0);
- term_sendBuf(src);
- term_sendByte(',');
- term_sendByte(' ');
- term_sendString(beacon[i].data, 0);
- term_sendBuf(src);
- }
-
- term_sendString((uint8_t*)"\r\nDigipeater: ", 0);
- if(digi.enable)
- term_sendString((uint8_t*)"On\r\n", 0);
- else
- term_sendString((uint8_t*)"Off\r\n", 0);
- term_sendBuf(src);
-
- for(uint8_t i = 0; i < 4; i++) //n-N aliases
- {
- term_sendString((uint8_t*)"Alias ", 0);
- if(digi.alias[i][0] != 0)
- {
- for(uint8_t j = 0; j < 5; j++)
- {
- if(digi.alias[i][j] != 0)
- term_sendByte(digi.alias[i][j] >> 1);
- }
- }
- term_sendString((uint8_t*)": ", 0);
- if(digi.enableAlias & (1 << i))
- term_sendString((uint8_t*)"On, max: ", 0);
- else
- term_sendString((uint8_t*)"Off, max: ", 0);
- term_sendNumber(digi.max[i]);
- term_sendString((uint8_t*)", rep: ", 0);
- term_sendNumber(digi.rep[i]);
- if(digi.traced & (1 << i))
- term_sendString((uint8_t*)", traced, ", 0);
- else
- term_sendString((uint8_t*)", untraced, ", 0);
- if(digi.viscous & (1 << i))
- term_sendString((uint8_t*)"viscous-delay, ", 0);
- else if(digi.directOnly & (1 << i))
- term_sendString((uint8_t*)"direct-only, ", 0);
- if(digi.callFilterEnable & (1 << i))
- term_sendString((uint8_t*)"filtered\r\n", 0);
- else
- term_sendString((uint8_t*)"unfiltered\r\n", 0);
- }
- term_sendBuf(src);
- for(uint8_t i = 0; i < 4; i++) //simple aliases
- {
- term_sendString((uint8_t*)"Alias ", 0);
- if(digi.alias[i + 4][0] != 0)
- {
- for(uint8_t j = 0; j < 6; j++)
- {
- if(digi.alias[i + 4][j] != 64)
- term_sendByte(digi.alias[i + 4][j] >> 1);
- }
- }
- term_sendByte('-');
- term_sendNumber(digi.ssid[i]);
- term_sendString((uint8_t*)": ", 0);
- if(digi.enableAlias & (1 << (i + 4)))
- term_sendString((uint8_t*)"On, ", 0);
- else
- term_sendString((uint8_t*)"Off, ", 0);
- if(digi.traced & (1 << (i + 4)))
- term_sendString((uint8_t*)"traced, ", 0);
- else
- term_sendString((uint8_t*)"untraced, ", 0);
- if(digi.viscous & (1 << (i + 4)))
- term_sendString((uint8_t*)"viscous-delay, ", 0);
- else if(digi.directOnly & (1 << (i + 4)))
- term_sendString((uint8_t*)"direct-only, ", 0);
- if(digi.callFilterEnable & (1 << (i + 4)))
- term_sendString((uint8_t*)"filtered\r\n", 0);
- else
- term_sendString((uint8_t*)"unfiltered\r\n", 0);
- }
- term_sendBuf(src);
- term_sendString((uint8_t*)"Anti-duplicate buffer hold time (s): ", 0);
- term_sendNumber(digi.dupeTime);
- term_sendString((uint8_t*)"\r\nCallsign filter type: ", 0);
- if(digi.filterPolarity)
- term_sendString((uint8_t*)"whitelist\r\n", 0);
- else
- term_sendString((uint8_t*)"blacklist\r\n", 0);
- term_sendString((uint8_t*)"Callsign filter list: ", 0);
- uint8_t callent = 0;
- for(uint8_t i = 0; i < 20; i++)
- {
- if(digi.callFilter[i][0] != 0)
- callent++;
- }
- if(callent > 9)
- {
- term_sendByte((callent / 10) + 48);
- term_sendByte((callent % 10) + 48);
- } else
- term_sendByte(callent + 48);
- term_sendString((uint8_t*)" entries\r\nAuto-reset every (h): ", 0);
- if(autoReset == 0)
- term_sendString((uint8_t*)"disabled", 0);
- else
- term_sendNumber(autoReset);
- term_sendString((uint8_t*)"\r\nKISS monitor: ", 0);
- if(kissMonitor == 1)
- term_sendString((uint8_t*)"On\r\n", 0);
- else
- term_sendString((uint8_t*)"Off\r\n", 0);
- term_sendString((uint8_t*)"Allow non-APRS frames: ", 0);
- if(ax25Cfg.allowNonAprs == 1)
- term_sendString((uint8_t*)"On\r\n", 0);
- else
- term_sendString((uint8_t*)"Off\r\n", 0);
- term_sendBuf(src);
- return;
+ printConfig(src);
}
-
-
- if(checkcmd(cmd, 4, (uint8_t*)"list"))
+ else if(!strncmp(cmd, "list", 4)) //list calls in call filter table
{
- term_sendString((uint8_t*)"Callsign filter list: \r\n", 0);
+ UartSendString(src, "Callsign filter list: \r\n", 0);
for(uint8_t i = 0; i < 20; i++)
{
- term_sendNumber(i);
- term_sendString((uint8_t*)". ", 0);
- if(digi.callFilter[i][0] != 0)
+ UartSendNumber(src, i);
+ UartSendString(src, ". ", 0);
+ if(DigiConfig.callFilter[i][0] != 0)
{
uint8_t cl[10] = {0};
uint8_t clidx = 0;
for(uint8_t h = 0; h < 6; h++)
{
- if(digi.callFilter[i][h] == 0xFF)
+ if(DigiConfig.callFilter[i][h] == 0xFF) //wildcard
{
uint8_t g = h;
uint8_t j = 0;
while(g < 6)
{
- if(digi.callFilter[i][g] != 0xFF) j = 1;
+ if(DigiConfig.callFilter[i][g] != 0xFF)
+ j = 1;
g++;
}
if(j == 0)
@@ -768,1067 +566,487 @@ void term_parse(uint8_t *cmd, uint16_t len, Terminal_stream src, Uart_data_type
}
else
{
- if(digi.callFilter[i][h] != ' ')
- cl[clidx++] = digi.callFilter[i][h];
+ if(DigiConfig.callFilter[i][h] != ' ')
+ cl[clidx++] = DigiConfig.callFilter[i][h];
}
}
- if(digi.callFilter[i][6] == 0xFF)
+ if(DigiConfig.callFilter[i][6] == 0xFF)
{
cl[clidx++] = '-';
cl[clidx++] = '*';
}
- else if(digi.callFilter[i][6] != 0)
+ else if(DigiConfig.callFilter[i][6] != 0)
{
cl[clidx++] = '-';
- if(digi.callFilter[i][6] > 9)
+ if(DigiConfig.callFilter[i][6] > 9)
{
- cl[clidx++] = (digi.callFilter[i][6] / 10) + 48;
- cl[clidx++] = (digi.callFilter[i][6] % 10) + 48;
+ cl[clidx++] = (DigiConfig.callFilter[i][6] / 10) + 48;
+ cl[clidx++] = (DigiConfig.callFilter[i][6] % 10) + 48;
}
- else cl[clidx++] = digi.callFilter[i][6] + 48;
+ else cl[clidx++] = DigiConfig.callFilter[i][6] + 48;
}
- term_sendString(cl, 0);
+ UartSendString(src, cl, 0);
}
else
- term_sendString((uint8_t*)"empty", 0);
- term_sendString((uint8_t*)"\r\n", 0);
- term_sendBuf(src);
+ UartSendString(src, "empty", 0);
+ UartSendString(src, "\r\n", 0);
+ return;
}
- return;
}
-
- if(checkcmd(cmd, 4, (uint8_t*)"call"))
+ /*
+ * Settings insertion handling
+ */
+ else if(!strncmp(cmd, "call", 4))
{
- uint8_t tmp[6] = {0};
- uint8_t err = 0;
- for(uint8_t i = 0; i < 7; i++)
- {
- if((cmd[5 + i] == '\r') || (cmd[5 + i] == '\n'))
- {
- if((i == 0))
- err = 1;
- break;
- }
- if(!(((cmd[5 + i] > 47) && (cmd[5 + i] < 58)) || ((cmd[5 + i] > 64) && (cmd[5 + i] < 91)))) //only alphanumeric characters
- {
- err = 1;
- break;
- }
- if(i == 6) //call too long
- {
- err = 1;
- break;
- }
- tmp[i] = cmd[5 + i] << 1;
- }
- if(!err)
- for(uint8_t i = 0; i < 6; i++)
- {
- call[i] = 64; //fill with spaces
- if(tmp[i] != 0)
- call[i] = tmp[i];
- }
- if(err)
+
+ if(!ParseCallsignWithSsid(&cmd[5], len - 5, GeneralConfig.call, &GeneralConfig.callSsid))
{
- term_sendString((uint8_t*)"Incorrect callsign!\r\n", 0);
+ UartSendString(src, "Incorrect callsign!\r\n", 0);
+ return;
}
else
{
- term_sendString((uint8_t*)"OK\r\n", 0);
+ UartSendString(src, "OK\r\n", 0);
}
- term_sendBuf(src);
return;
}
-
- if(checkcmd(cmd, 4, (uint8_t*)"dest"))
+ else if(!strncmp(cmd, "dest", 4))
{
- uint8_t tmp[6] = {0};
- uint8_t err = 0;
- for(uint8_t i = 0; i < 7; i++)
- {
- if((cmd[5 + i] == '\r') || (cmd[5 + i] == '\n'))
- {
- if((i == 0))
- err = 1;
- break;
- }
- if(!(((cmd[5 + i] > 47) && (cmd[5 + i] < 58)) || ((cmd[5 + i] > 64) && (cmd[5 + i] < 91)))) //only alphanumeric characters
- {
- err = 1;
- break;
- }
- if(i == 6) //address too long
- {
- err = 1;
- break;
- }
- tmp[i] = cmd[5 + i] << 1;
- }
- if(!err)
- for(uint8_t i = 0; i < 6; i++)
- {
- dest[i] = 64; //fill with spaces
- if(tmp[i] != 0)
- dest[i] = tmp[i];
- }
- if(err)
+ if(!ParseCallsign(&cmd[5], len - 5, GeneralConfig.dest))
{
- term_sendString((uint8_t*)"Incorrect address!\r\n", 0);
+ UartSendString(src, "Incorrect address!\r\n", 0);
+ return;
}
else
{
- term_sendString((uint8_t*)"OK\r\n", 0);
+ UartSendString(src, "OK\r\n", 0);
}
- term_sendBuf(src);
- return;
}
-
- if(checkcmd(cmd, 4, (uint8_t*)"ssid"))
+ else if(!strncmp(cmd, "txdelay", 7))
{
- uint8_t tmp[3] = {0};
- uint8_t err = 0;
- for(uint8_t i = 0; i < 3; i++)
+ int64_t t = StrToInt(&cmd[8], len - 8);
+ if((t > 2550) || (t < 50))
{
- if((cmd[5 + i] == '\r') || (cmd[5 + i] == '\n'))
- {
- if((i == 0))
- err = 1; //no ssid provided
- break;
- }
- if(!(((cmd[5 + i] > 47) && (cmd[5 + i] < 58)))) //only numbers
- {
- err = 1;
- break;
- }
- if(i == 2) //more than 2 digits in ssid
- {
- err = 1;
- break;
- }
- tmp[i] = cmd[5 + i];
+ UartSendString(src, "Incorrect TXDelay!\r\n", 0);
+ return;
}
- if(!err)
+ else
{
- uint8_t t = 0;
- t = (uint8_t)strToInt(tmp, 0);
- if(t > 15)
- err = 1;
- else
- callSsid = t;
+ Ax25Config.txDelayLength = (uint16_t)t;
+ UartSendString(src, "OK\r\n", 0);
}
- if(err)
+ }
+ else if(!strncmp(cmd, "txtail", 6))
+ {
+ int64_t t = StrToInt(&cmd[7], len - 7);
+ if((t > 2550) || (t < 50))
{
- term_sendString((uint8_t*)"Incorrect SSID!\r\n", 0);
+ UartSendString(src, "Incorrect TXTail!\r\n", 0);
+ return;
}
else
{
- term_sendString((uint8_t*)"OK\r\n", 0);
+ Ax25Config.txTailLength = (uint16_t)t;
+ UartSendString(src, "OK\r\n", 0);
}
- term_sendBuf(src);
- return;
}
- if(checkcmd(cmd, 7, (uint8_t*)"txdelay"))
+ else if(!strncmp(cmd, "quiet", 5))
{
- uint8_t tmp[5] = {0};
- uint8_t err = 0;
- for(uint8_t i = 0; i < 5; i++)
+ int64_t t = StrToInt(&cmd[6], len - 6);
+ if((t > 2550) || (t < 100))
{
- if((cmd[8 + i] == '\r') || (cmd[8 + i] == '\n'))
- {
- if((i == 0))
- err = 1;
- break;
- }
- if(!(((cmd[8 + i] > 47) && (cmd[8 + i] < 58)))) //only digits
- {
- err = 1;
- break;
- }
- if(i == 4)
- {
- err = 1;
- break;
- }
- tmp[i] = cmd[8 + i];
- }
- if(!err)
- {
- uint16_t t = 0;
- t = (uint16_t)strToInt(tmp, 0);
- if((t > 2550) || (t < 50))
- err = 1;
- else
- ax25Cfg.txDelayLength = t;
- }
- if(err)
- {
- term_sendString((uint8_t*)"Incorrect TXDelay!\r\n", 0);
- }
- else
- {
- term_sendString((uint8_t*)"OK\r\n", 0);
- }
- term_sendBuf(src);
- return;
- }
-
- if(checkcmd(cmd, 6, (uint8_t*)"txtail"))
- {
- uint8_t tmp[5] = {0};
- uint8_t err = 0;
- for(uint8_t i = 0; i < 5; i++)
- {
- if((cmd[7 + i] == '\r') || (cmd[7 + i] == '\n'))
- {
- if((i == 0))
- err = 1;
- break;
- }
- if(!(((cmd[7 + i] > 47) && (cmd[7 + i] < 58)))) //only digits
- {
- err = 1;
- break;
- }
- if(i == 4)
- {
- err = 1;
- break;
- }
- tmp[i] = cmd[7 + i];
- }
- if(!err)
- {
- uint16_t t = 0;
- t = (uint16_t)strToInt(tmp, 0);
- if((t > 2550) || (t < 10))
- err = 1;
- else
- ax25Cfg.txTailLength = t;
- }
- if(err)
- {
- term_sendString((uint8_t*)"Incorrect TXTail!\r\n", 0);
+ UartSendString(src, "Incorrect quiet time!\r\n", 0);
+ return;
}
else
{
- term_sendString((uint8_t*)"OK\r\n", 0);
+ Ax25Config.quietTime = (uint16_t)t;
}
- term_sendBuf(src);
- return;
}
-
- if(checkcmd(cmd, 5, (uint8_t*)"quiet"))
+ else if(!strncmp(cmd, "rs1baud", 7) || !strncmp(cmd, "rs2baud", 7))
{
- uint8_t tmp[5] = {0};
- uint8_t err = 0;
- for(uint8_t i = 0; i < 5; i++)
- {
- if((cmd[6 + i] == '\r') || (cmd[6 + i] == '\n'))
- {
- if((i == 0))
- err = 1;
- break;
- }
- if(!(((cmd[6 + i] > 47) && (cmd[6 + i] < 58))))
- {
- err = 1;
- break;
- }
- if(i == 4)
- {
- err = 1;
- break;
- }
- tmp[i] = cmd[6 + i];
- }
- if(!err)
- {
- uint16_t t = 0;
- t = (uint16_t)strToInt(tmp, 0);
- if((t > 2550) || (t < 100))
- err = 1;
- else
- ax25Cfg.quietTime = t;
- }
- if(err)
+ int64_t t = StrToInt(&cmd[8], len - 8);
+ if((t > 115200) || (t < 1200))
{
- term_sendString((uint8_t*)"Incorrect quiet time!\r\n", 0);
+ UartSendString(src, "Incorrect baudrate!\r\n", 0);
}
else
{
- term_sendString((uint8_t*)"OK\r\n", 0);
- }
- term_sendBuf(src);
- return;
- }
-
- if(checkcmd(cmd, 7, (uint8_t*)"rs1baud") || checkcmd(cmd, 7, (uint8_t*)"rs2baud"))
- {
- uint8_t tmp[7] = {0};
- uint8_t err = 0;
- for(uint8_t i = 0; i < 7; i++)
- {
- if((cmd[8 + i] == '\r') || (cmd[8 + i] == '\n'))
- {
- if((i == 0))
- err = 1;
- break;
- }
- if(!(((cmd[8 + i] > 47) && (cmd[8 + i] < 58))))
- {
- err = 1;
- break;
- }
- if(i == 6)
- {
- err = 1;
- break;
- }
- tmp[i] = cmd[8 + i];
- }
- if(!err)
- {
- uint32_t t = 0;
- t = (uint32_t)strToInt(tmp, 0);
- if((t > 115200) || (t < 1200))
- err = 1;
+ if(cmd[2] == '1')
+ Uart1.baudrate = (uint32_t)t;
+ else if(cmd[2] == '2')
+ Uart2.baudrate = (uint32_t)t;
else
{
- if(cmd[2] == '1')
- uart1.baudrate = t;
- else
- uart2.baudrate = t;
+ UartSendString(src, "Incorrect port number!\r\n", 0);
+ return;
}
}
- if(err)
- {
- term_sendString((uint8_t*)"Incorrect baudrate!\r\n", 0);
- }
- else
- {
- term_sendString((uint8_t*)"OK\r\n", 0);
- }
- term_sendBuf(src);
- return;
}
-
- if(checkcmd(cmd, 6, (uint8_t*)"beacon"))
+ else if(!strncmp(cmd, "beacon", 6))
{
uint8_t bcno = 0;
bcno = cmd[7] - 48;
if(bcno > 7)
{
- term_sendString((uint8_t*)"Incorrect beacon number\r\n", 0);
- term_sendBuf(src);
+ UartSendString(src, "Incorrect beacon number\r\n", 0);
+ return;
}
- uint8_t err = 0;
- if(cmd[9] == 'o' && cmd[10] == 'n')
+ if(!strncmp(&cmd[9], "on", 2))
beacon[bcno].enable = 1;
- else if(cmd[9] == 'o' && cmd[10] == 'f' && cmd[11] == 'f')
+ else if(!strncmp(&cmd[9], "off", 3))
beacon[bcno].enable = 0;
- else if((cmd[9] == 'i' && cmd[10] == 'v') || (cmd[9] == 'd' && cmd[10] == 'l')) //interval or delay
+ else if(!strncmp(&cmd[9], "iv", 2) || !strncmp(&cmd[9], "dl", 2)) //interval or delay
{
- uint8_t tmp[4] = {0};
-
- for(uint8_t i = 0; i < 4; i++)
+ int64_t t = StrToInt(&cmd[12], len - 12);
+ if(t > 720)
{
- if((cmd[12 + i] == '\r') || (cmd[12 + i] == '\n'))
- {
- if((i == 0))
- err = 1;
- break;
- }
- if(!(((cmd[12 + i] > 47) && (cmd[12 + i] < 58))))
- {
- err = 1;
- break;
- }
- if(i == 3)
- {
- err = 1;
- break;
- }
- tmp[i] = cmd[12 + i];
- }
- if(!err)
- {
- uint32_t t = 0;
- t = (uint32_t)strToInt(tmp, 0);
- if(t > 720) err = 1;
- else
- {
- if(cmd[9] == 'i')
- beacon[bcno].interval = t * 6000;
- else
- beacon[bcno].delay = t * 60;
- }
+ UartSendString(src, "Interval/delay must lesser or equal to 720 minutes\r\n", 0);
+ return;
}
+ if(!strncmp(&cmd[9], "iv", 2))
+ beacon[bcno].interval = t * 6000;
+ else
+ beacon[bcno].delay = t * 60;
+
}
- else if((cmd[9] == 'd' && cmd[10] == 'a' && cmd[11] == 't' && cmd[12] == 'a'))
+ else if(!strncmp(&cmd[9], "data", 4))
{
- uint8_t dlen = 0;
- if((cmd[len - 1] == '\r') || (cmd[len - 1] == '\n'))
- dlen = len - 15;
- else
- dlen = len - 14;
- if(dlen > 99)
+ if((len - 14) > BEACON_MAX_PAYLOAD_SIZE)
{
- term_sendString((uint8_t*)"Data too long\r\n", 0);
- term_sendBuf(src);
+ UartSendString(src, "Data is too long\r\n", 0);
return;
}
- uint8_t i = 0;
- for(; i < dlen; i++)
- {
+ uint16_t i = 0;
+ for(; i < (len - 14); i++)
beacon[bcno].data[i] = cmd[14 + i];
- }
beacon[bcno].data[i] = 0;
}
- else if((cmd[9] == 'p' && cmd[10] == 'a' && cmd[11] == 't' && cmd[12] == 'h'))
+ else if(!strncmp(&cmd[9], "path", 4))
{
- uint8_t dlen = 0;
- if((cmd[len - 2] == '\r') || (cmd[len - 2] == '\n'))
- dlen = len - 16;
- else
- dlen = len - 15;
- if((dlen == 4) && (cmd[14] == 'n') && (cmd[15] == 'o') && (cmd[16] == 'n') && (cmd[17] == 'e')) //"none" path
+ if((len - 14) < 0)
{
- for(uint8_t i = 0; i < 14; i++)
- beacon[bcno].path[i] = 0;
+ UartSendString(src, "Path cannot be empty. Use \"none\" for empty path. \r\n", 0);
+ return;
+ }
+ if(((len - 14) == 4) && !strncmp(&cmd[14], "none", 4)) //"none" path
+ {
+ memset(beacon[bcno].path, 0, sizeof(beacon[bcno].path));
- term_sendString((uint8_t*)"OK\r\n", 0);
- term_sendBuf(src);
+ UartSendString(src, "OK\r\n", 0);
return;
}
- if(dlen == 0)
- err = 1;
- uint8_t tmp[14] = {0};
- uint8_t elemlen = 0;
- uint8_t tmpidx = 0;
- if(!err)
- for(uint8_t i = 0; i < dlen; i++)
+ uint8_t tmp[14];
+ uint8_t tmpIdx = 0;
+ uint16_t elementStart = 14;
+ for(uint8_t i = 0; i < (len - 14); i++)
{
- if(elemlen > 6)
- {
- err = 1;
- break;
- }
- if(cmd[14 + i] == '-')
+ if((cmd[14 + i] == ',') || ((14 + i + 1) == len))
{
- uint8_t ssid = 0;
- if(((cmd[15 + i] > 47) && (cmd[15 + i] < 58)))
- {
- ssid = cmd[15 + i] - 48;
- }
- else
- {
- err = 1;
- break;
- }
- if(((cmd[16 + i] > 47) && (cmd[16 + i] < 58)))
- {
- ssid *= 10;
- ssid += cmd[16 + i] - 48;
- }
- else if(!((cmd[16 + i] == ',') || (cmd[16 + i] == '\r') || (cmd[16 + i] == '\n')))
- {
- err = 1;
- break;
- }
- if(ssid > 15)
+ if((14 + i + 1) == len) //end of data
{
- err = 1;
- break;
+ i++;
+ tmp[7] = 0;
}
- else
+
+ if((14 + i - elementStart) > 0)
{
- while(tmpidx < ((tmpidx > 7) ? 13 : 6))
+ if(!ParseCallsignWithSsid(&cmd[elementStart], 14 + i - elementStart, &tmp[tmpIdx], &tmp[tmpIdx + 6]))
{
- tmp[tmpidx++] = ' ';
+ err = true;
+ break;
}
- tmp[tmpidx++] = ssid;
- if(ssid > 10)
- i += 2;
- else
- i++;
+ tmpIdx += 7;
+ if(tmpIdx == 14)
+ break;
}
- }
- else if(cmd[14 + i] == ',')
- {
- elemlen = 0;
- }
- else if(((cmd[14 + i] > 47) && (cmd[14 + i] < 58)) || ((cmd[14 + i] > 64) && (cmd[14 + i] < 91)))
- {
- elemlen++;
- tmp[tmpidx++] = cmd[14 + i];
- }
- else
- {
- err = 1;
- break;
+ elementStart = 14 + i + 1;
}
}
if(err)
{
- term_sendString((uint8_t*)"Incorrect path!\r\n", 0);
- term_sendBuf(src);
+ UartSendString(src, "Incorrect path!\r\n", 0);
return;
}
- for(uint8_t i = 0; i < 14; i++)
- beacon[bcno].path[i] = tmp[i];
- err = 0;
+ memcpy(beacon[bcno].path, tmp, 14);
}
-
- else err = 1;
-
- if(err == 1)
+ else
{
- term_sendString((uint8_t*)"Incorrect command\r\n", 0);
+ err = true;
}
- else term_sendString((uint8_t*)"OK\r\n", 0);
- term_sendBuf(src);
- return;
+ UartSendString(src, "OK\r\n", 0);
}
-
- if(checkcmd(cmd, 4, (uint8_t*)"digi"))
+ else if(!strncmp(cmd, "digi", 4))
{
-
- uint8_t err = 0;
- if(cmd[4] == ' ' && cmd[5] == 'o' && cmd[6] == 'n')
- digi.enable = 1;
- else if(cmd[4] == ' ' && cmd[5] == 'o' && cmd[6] == 'f' && cmd[7] == 'f')
- digi.enable = 0;
- else if((((cmd[5] > 47) && (cmd[5] < 58))) && (cmd[4] == ' '))
+ if(!strncmp(&cmd[5], "on", 2))
+ DigiConfig.enable = 1;
+ else if(!strncmp(&cmd[5], "off", 3))
+ DigiConfig.enable = 0;
+ else if(IS_NUMBER(cmd[5]))
{
uint8_t alno = 0;
alno = cmd[5] - 48;
if(alno > 7)
{
- term_sendString((uint8_t*)"Incorrect alias number\r\n", 0);
- term_sendBuf(src);
+ UartSendString(src, "Incorrect alias number\r\n", 0);
return;
}
- if(checkcmd(&cmd[7], 2, (uint8_t*)"on"))
- digi.enableAlias |= (1 << alno);
- else if(checkcmd(&cmd[7], 3, (uint8_t*)"off"))
- digi.enableAlias &= ~(1 << alno);
- else if(checkcmd(&cmd[7], 6, (uint8_t*)"alias "))
+ if(!strncmp(&cmd[7], "on", 2))
+ DigiConfig.enableAlias |= (1 << alno);
+ else if(!strncmp(&cmd[7], "off", 3))
+ DigiConfig.enableAlias &= ~(1 << alno);
+ else if(!strncmp(&cmd[7], "alias ", 6))
{
- uint8_t tmp[5] = {0};
- uint8_t err = 0;
-
if(alno < 4) //New-N aliases
{
- for(uint8_t i = 0; i < 6; i++)
+ if((len - 13) <= 5)
{
- if((cmd[13 + i] == '\r') || (cmd[13 + i] == '\n'))
- {
- if((i == 0))
- err = 1;
- break;
- }
- if(!(((cmd[13 + i] > 47) && (cmd[13 + i] < 58)) || ((cmd[13 + i] > 64) && (cmd[13 + i] < 91))))
- {
- err = 1;
- break;
- }
- if(i == 5)
- {
- err = 1;
- break;
- }
- tmp[i] = cmd[13 + i] << 1;
- }
- if(!err) for(uint8_t i = 0; i < 5; i++)
- {
- digi.alias[alno][i] = tmp[i];
- }
- if(err)
- {
- term_sendString((uint8_t*)"Incorrect alias!\r\n", 0);
+ if(false == (err = !ParseCallsign(&cmd[13], len - 13, DigiConfig.alias[alno])))
+ DigiConfig.alias[alno][len - 13] = 0;
}
else
- {
- term_sendString((uint8_t*)"OK\r\n", 0);
- }
- term_sendBuf(src);
- return;
+ err = true;
}
else //simple aliases
{
- uint8_t dlen = 0;
- if((cmd[len - 2] == '\r') || (cmd[len - 2] == '\n'))
- dlen = len - 16;
- else
- dlen = len - 14;
-
- if(dlen == 0)
- err = 1;
-
- uint8_t tmp[6] = {0};
- uint8_t tmpidx = 0;
- uint8_t elemlen = 0;
- uint8_t ssid = 0;
- if(!err)
- for(uint8_t i = 0; i < dlen; i++)
- {
- if(elemlen > 6)
- {
- err = 1;
- break;
- }
- if(cmd[13 + i] == '-')
- {
- if(((cmd[14 + i] > 47) && (cmd[14 + i] < 58)))
- {
- ssid = cmd[14 + i] - 48;
- }
- else
- {
- err = 1;
- break;
- }
- if(((cmd[15 + i] > 47) && (cmd[15 + i] < 58)))
- {
- ssid *= 10;
- ssid += cmd[15 + i] - 48;
- }
- else if(!((cmd[15 + i] == '\r') || (cmd[15 + i] == '\n')))
- {
- err = 1;
- break;
- }
- if(ssid > 15) err = 1;
- break;
- }
- else if(((cmd[13 + i] > 47) && (cmd[13 + i] < 58)) || ((cmd[13 + i] > 64) && (cmd[13 + i] < 91)))
- {
- elemlen++;
- tmp[tmpidx++] = cmd[13 + i];
- }
- else
- {
- err = 1;
- break;
- }
- }
- if(err)
- {
- term_sendString((uint8_t*)"Incorrect alias!\r\n", 0);
- term_sendBuf(src);
- return;
- }
-
-
- for(uint8_t i = 0; i < 6; i++)
+ if(!ParseCallsignWithSsid(&cmd[13], len - 13, DigiConfig.alias[alno], &DigiConfig.ssid[alno - 4]))
{
- digi.alias[alno][i] = 64;
- if(tmp[i] != 0)
- digi.alias[alno][i] = tmp[i] << 1;
+ err = true;
}
- digi.ssid[alno - 4] = ssid;
- err = 0;
}
-
- }
-
- else if((checkcmd(&cmd[7], 4, (uint8_t*)"max ") || checkcmd(&cmd[7], 4, (uint8_t*)"rep ")) && (alno < 4))
- {
-
- uint8_t err = 0;
-
- if(!((cmd[12] == '\r') || (cmd[12] == '\n')))
+ if(err)
{
- err = 1;
+ UartSendString(src, "Incorrect alias!\r\n", 0);
+ return;
}
- if(!(((cmd[11] > 47) && (cmd[11] < 58))))
+ UartSendString(src, "OK\r\n", 0);
+ }
+ else if((!strncmp(&cmd[7], "max ", 4) || !strncmp(&cmd[7], "rep ", 4)) && (alno < 4))
+ {
+ int64_t t = StrToInt(&cmd[11], len - 11);
+ if(!strncmp(&cmd[7], "max ", 4) && (t >= 1 || t <= 7))
{
- err = 1;
+ DigiConfig.max[alno] = t;
}
-
- uint8_t val = cmd[11] - 48;
- if(cmd[7] == 'm' && (val < 1 || val > 7))
- err = 1;
- if(cmd[7] == 'r' && (val > 7))
- err = 1;
-
- if(err)
+ else if(!strncmp(&cmd[7], "rep ", 4) && (t <= 7))
{
- term_sendString((uint8_t*)"Incorrect value!\r\n", 0);
+ DigiConfig.rep[alno] = t;
}
else
{
- if(cmd[7] == 'm')
- digi.max[alno] = val;
- else digi.rep[alno] = val;
- term_sendString((uint8_t*)"OK\r\n", 0);
+ UartSendString(src, "Incorrect value!\r\n", 0);
+ return;
}
- term_sendBuf(src);
- return;
}
- else if(checkcmd(&cmd[7], 5, (uint8_t*)"trac "))
+ else if(!strncmp(&cmd[7], "trac ", 5))
{
- if(cmd[12] == 'o' && cmd[13] == 'n')
- digi.traced |= 1 << alno;
- else if(cmd[12] == 'o' && cmd[13] == 'f' && cmd[14] == 'f')
- digi.traced &= ~(1 << alno);
- else err = 1;
+ if(!strncmp(&cmd[12], "on", 2))
+ DigiConfig.traced |= 1 << alno;
+ else if(!strncmp(&cmd[12], "off", 3))
+ DigiConfig.traced &= ~(1 << alno);
+ else
+ {
+ err = true;
+ }
}
- else if(checkcmd(&cmd[7], 7, (uint8_t*)"filter "))
+ else if(!strncmp(&cmd[7], "filter ", 7))
{
- if(cmd[14] == 'o' && cmd[15] == 'n')
- digi.callFilterEnable |= 1 << alno;
- else if(cmd[14] == 'o' && cmd[15] == 'f' && cmd[16] == 'f')
- digi.callFilterEnable &= ~(1 << alno);
- else err = 1;
+ if(!strncmp(&cmd[14], "on", 2))
+ DigiConfig.callFilterEnable |= 1 << alno;
+ else if(!strncmp(&cmd[14], "off", 3))
+ DigiConfig.callFilterEnable &= ~(1 << alno);
+ else
+ {
+ err = true;
+ }
}
- else if(checkcmd(&cmd[7], 8, (uint8_t*)"viscous "))
+ else if(!strncmp(&cmd[7], "viscous ", 8))
{
- if(cmd[15] == 'o' && cmd[16] == 'n')
+ if(!strncmp(&cmd[15], "on", 2))
{
- digi.viscous |= (1 << alno);
- digi.directOnly &= ~(1 << alno); //disable directonly mode
+ DigiConfig.viscous |= (1 << alno);
+ DigiConfig.directOnly &= ~(1 << alno); //disable directonly mode
}
- else if(cmd[15] == 'o' && cmd[16] == 'f' && cmd[17] == 'f')
- digi.viscous &= ~(1 << alno);
+ else if(!strncmp(&cmd[15], "off", 3))
+ DigiConfig.viscous &= ~(1 << alno);
else
- err = 1;
+ {
+ err = true;
+ }
}
- else if(checkcmd(&cmd[7], 7, (uint8_t*)"direct "))
+ else if(!strncmp(&cmd[7], "direct ", 7))
{
- if(cmd[14] == 'o' && cmd[15] == 'n')
+ if(!strncmp(&cmd[14], "on", 2))
+ {
+ DigiConfig.directOnly |= (1 << alno);
+ DigiConfig.viscous &= ~(1 << alno); //disable viscous delay mode
+ }
+ else if(!strncmp(&cmd[14], "off", 3))
+ DigiConfig.directOnly &= ~(1 << alno);
+ else
{
- digi.directOnly |= (1 << alno);
- digi.viscous &= ~(1 << alno); //disable viscous delay mode
+ err = true;
}
- else if(cmd[14] == 'o' && cmd[15] == 'f' && cmd[16] == 'f')
- digi.directOnly &= ~(1 << alno);
- else err = 1;
}
+ else
+ err = true;
}
- else if(checkcmd(&cmd[5], 7, (uint8_t*)"filter "))
+ else if(!strncmp(&cmd[5], "filter ", 7))
{
- if(checkcmd(&cmd[12], 5, (uint8_t*)"white"))
- digi.filterPolarity = 1;
- else if(checkcmd(&cmd[12], 5, (uint8_t*)"black"))
- digi.filterPolarity = 0;
+ if(!strncmp(&cmd[12], "white", 5))
+ DigiConfig.filterPolarity = 1;
+ else if(!strncmp(&cmd[12], "black", 5))
+ DigiConfig.filterPolarity = 0;
else
- err = 1;
+ err = true;
}
- else if(checkcmd(&cmd[5], 5, (uint8_t*)"dupe "))
+ else if(!strncmp(&cmd[5], "dupe ", 5))
{
- uint8_t tmp[4] = {0};
- uint8_t err = 0;
- for(uint8_t i = 0; i < 4; i++)
- {
- if((cmd[10 + i] == '\r') || (cmd[10 + i] == '\n'))
- {
- if((i == 0))
- err = 1;
- break;
- }
- if(!(((cmd[10 + i] > 47) && (cmd[10 + i] < 58))))
- {
- err = 1;
- break;
- }
- if(i == 3)
- {
- err = 1;
- break;
- }
- tmp[i] = cmd[10 + i];
- }
- if(!err)
- {
- uint16_t t = 0;
- t = (uint16_t)strToInt(tmp, 0);
- if((t > 255) || (t < 5))
- err = 1;
- else
- digi.dupeTime = (uint8_t)t;
- }
- if(err)
+ int64_t t = StrToInt(&cmd[10], len - 10);
+ if((t > 255) || (t < 5))
{
- term_sendString((uint8_t*)"Incorrect anti-dupe time!\r\n", 0);
+ UartSendString(src, "Incorrect anti-dupe time!\r\n", 0);
+ return;
}
else
- {
- term_sendString((uint8_t*)"OK\r\n", 0);
- }
- term_sendBuf(src);
- return;
+ DigiConfig.dupeTime = (uint8_t)t;
}
- else if(checkcmd(&cmd[5], 5, (uint8_t*)"list "))
+ else if(!strncmp(&cmd[5], "list ", 5))
{
- uint8_t no = 0;
- if((((cmd[10] > 47) && (cmd[10] < 58))))
+ uint16_t shift = 10;
+
+ while(shift < len)
{
- no = cmd[10] - 48;
- }
- else err = 1;
+ if(cmd[shift] == ' ')
+ break;
- if((((cmd[11] > 47) && (cmd[11] < 58))) && !err)
+ shift++;
+ }
+ int64_t number = StrToInt(&cmd[10], shift - 10);
+ if((number < 0) || (number >= (sizeof(DigiConfig.callFilter) / sizeof(*(DigiConfig.callFilter)))))
{
- no *= 10;
- no += cmd[11] - 48;
+ UartSendString(src, "Incorrect filter slot!\r\n", 0);
+ return;
}
-
- if(no > 19) err = 1;
-
- uint8_t shift = 12;
- if(no > 9) shift = 13;
-
- if(checkcmd(&cmd[shift], 4, (uint8_t*)"set "))
+ shift++;
+ if((len - shift) < 4)
{
- uint8_t dlen = 0;
- if((cmd[len - 2] == '\r') || (cmd[len - 2] == '\n'))
- dlen = len - shift - 7;
- else
- dlen = len - shift - 5;
+ UartSendString(src, "Incorrect format!\r\n", 0);
+ return;
+ }
- if(dlen == 0)
- err = 1;
- uint8_t j = 0;
- uint8_t h = 0;
+ if(!strncmp(&cmd[shift], "set ", 4))
+ {
+ shift += 4;
- volatile uint8_t tmp[7] = {0};
+ uint8_t tmp[7] = {0};
+ uint16_t tmpIdx = 0;
- if(!err) for(j = 0; j < dlen; j++)
- {
- if(cmd[shift + 4 + j] == '-')
+ for(uint16_t i = 0; i < len; i++)
+ {
+ if(cmd[shift + i] == '-') //SSID separator
{
- if((cmd[shift + 5 + j] == '*') || (cmd[shift + 5 + j] == '?'))
- {
+ if((cmd[shift + i + 1] == '*') || (cmd[shift + i + 1] == '?')) //and there is any wildcard
tmp[6] = 0xFF;
- break;
- }
- if((dlen - 1 - j) == 2)
- {
- if((cmd[shift + 6 + j] > 47) && (cmd[shift + 6 + j] < 58))
- tmp[6] += cmd[shift + 6 + j] - 48;
- else
- err = 1;
- if((cmd[shift + 5 + j] > 47) && (cmd[shift + 5 + j] < 58))
- tmp[6] += (cmd[shift + 5 + j] - 48) * 10;
- else
- err = 1;
- if(tmp[6] > 15)
- err = 1;
- }
- else if((cmd[shift + 5 + j] > 47) && (cmd[shift + 5 + j] < 58))
- tmp[6] += cmd[shift + 5 + j] - 48;
- else
- err = 1;
+ else if(!ParseSsid(&cmd[shift + i + 1], len - (shift + i + 1), &tmp[6])) //otherwise it is a normal SSID
+ err = true;
break;
}
- if(cmd[shift + 4 + j] == '?')
+ else if(cmd[shift + i] == '?')
{
- tmp[j] = 0xFF;
- continue;
- } else if(cmd[shift + 4 + j] == '*')
+ tmp[tmpIdx++] = 0xFF;
+ }
+ else if(cmd[shift + i] == '*')
{
- h = j;
- while(h < 6)
+ while(tmpIdx < 6)
{
- tmp[h] = 0xFF;
- h++;
+ tmp[tmpIdx++] = 0xFF;
}
continue;
}
- if(((cmd[shift + 4 + j] > 47) && (cmd[shift + 4 + j] < 58)) || ((cmd[shift + 4 + j] > 64) && (cmd[shift + 4 + j] < 91))) tmp[j] = cmd[shift + 4 + j];
- else err = 1;
- }
+ else if(IS_UPPERCASE_ALPHANUMERIC(cmd[shift + i]))
+ tmp[tmpIdx++] = cmd[shift + i];
+ else
+ {
+ err = true;
+ break;
+ }
+ }
if(!err)
{
- while((j + h) < 6) //fill with spaces
+ while(tmpIdx < 6) //fill with spaces
{
- tmp[j] = ' ';
- j++;
+ tmp[tmpIdx++] = ' ';
}
- for(uint8_t i = 0; i < 7; i++)
- digi.callFilter[no][i] = tmp[i];
+
+ memcpy(DigiConfig.callFilter[number], tmp, 7);
}
else
{
- term_sendString((uint8_t*)"Incorrect format!\r\n", 0);
- term_sendBuf(src);
+ UartSendString(src, "Incorrect format!\r\n", 0);
return;
}
}
- else if(checkcmd(&cmd[shift], 6, (uint8_t*)"remove"))
- {
- for(uint8_t i = 0; i < 7; i++)
- digi.callFilter[no][i] = 0;
- }
- else
- err = 1;
-
-
- if(err)
- {
- term_sendString((uint8_t*)"Incorrect command!\r\n", 0);
- }
- else
- {
- term_sendString((uint8_t*)"OK\r\n", 0);
- }
- term_sendBuf(src);
- return;
- }
- else err = 1;
-
- if(err == 1)
- {
- term_sendString((uint8_t*)"Incorrect command\r\n", 0);
- }
- else term_sendString((uint8_t*)"OK\r\n", 0);
-
- term_sendBuf(src);
- return;
- }
-
-
- if(checkcmd(cmd, 10, (uint8_t*)"autoreset "))
- {
- uint8_t tmp[4] = {0};
- uint8_t err = 0;
- for(uint8_t i = 0; i < 4; i++)
- {
- if((cmd[10 + i] == '\r') || (cmd[10 + i] == '\n'))
- {
- if((i == 0))
- err = 1;
- break;
- }
- if(!(((cmd[10 + i] > 47) && (cmd[10 + i] < 58))))
+ else if(!strncmp(&cmd[shift], "remove", 6))
{
- err = 1;
- break;
+ memset(DigiConfig.callFilter[number], 0, 7);
}
- if(i == 3)
- {
- err = 1;
- break;
- }
- tmp[i] = cmd[10 + i];
- }
- if(!err)
- {
- uint8_t t = 0;
- t = strToInt(tmp, 0);
- if(t > 255)
- err = 1;
else
- autoReset = t;
- }
- if(err)
- {
- term_sendString((uint8_t*)"Incorrect time interval!\r\n", 0);
+ err = true;
}
else
- {
- term_sendString((uint8_t*)"OK\r\n", 0);
- }
- term_sendBuf(src);
- return;
+ err = true;
}
- if(checkcmd(cmd, 4, (uint8_t*)"pwm "))
+ else if(!strncmp(cmd, "pwm ", 4))
{
- uint8_t err = 0;
- if(checkcmd(&cmd[4], 2, (uint8_t*)"on"))
- afskCfg.usePWM = 1;
- else if(checkcmd(&cmd[4], 3, (uint8_t*)"off"))
- afskCfg.usePWM = 0;
- else
- err = 1;
-
- if(err)
- {
- term_sendString((uint8_t*)"Incorrect command!\r\n", 0);
- }
+ if(!strncmp(&cmd[4], "on", 2))
+ ModemConfig.usePWM = 1;
+ else if(!strncmp(&cmd[4], "off", 3))
+ ModemConfig.usePWM = 0;
else
- {
- term_sendString((uint8_t*)"OK\r\n", 0);
- }
- term_sendBuf(src);
- return;
+ err = true;
}
- if(checkcmd(cmd, 5, (uint8_t*)"flat "))
+ else if(!strncmp(cmd, "flat ", 5))
{
- uint8_t err = 0;
- if(checkcmd(&cmd[5], 2, (uint8_t*)"on"))
- afskCfg.flatAudioIn = 1;
- else if(checkcmd(&cmd[5], 3, (uint8_t*)"off"))
- afskCfg.flatAudioIn = 0;
+ if(!strncmp(&cmd[5], "on", 2))
+ ModemConfig.flatAudioIn = 1;
+ else if(!strncmp(&cmd[5], "off", 3))
+ ModemConfig.flatAudioIn = 0;
else
- err = 1;
-
- if(err)
- {
- term_sendString((uint8_t*)"Incorrect command!\r\n", 0);
- }
- else
- {
- term_sendString((uint8_t*)"OK\r\n", 0);
- }
- term_sendBuf(src);
- return;
+ err = true;
}
-
- if(checkcmd(cmd, 8, (uint8_t*)"monkiss "))
+ else if(!strncmp(cmd, "monkiss ", 8))
{
- uint8_t err = 0;
- if(checkcmd(&cmd[8], 2, (uint8_t*)"on"))
- kissMonitor = 1;
- else if(checkcmd(&cmd[8], 3, (uint8_t*)"off"))
- kissMonitor = 0;
+ if(!strncmp(&cmd[8], "on", 2))
+ GeneralConfig.kissMonitor = 1;
+ else if(!strncmp(&cmd[8], "off", 3))
+ GeneralConfig.kissMonitor = 0;
else
- err = 1;
-
- if(err)
- {
- term_sendString((uint8_t*)"Incorrect command!\r\n", 0);
- }
- else
- {
- term_sendString((uint8_t*)"OK\r\n", 0);
- }
- term_sendBuf(src);
- return;
+ err = true;
}
- if(checkcmd(cmd, 8, (uint8_t*)"nonaprs "))
+ else if(!strncmp(cmd, "nonaprs ", 8))
{
- uint8_t err = 0;
- if(checkcmd(&cmd[8], 2, (uint8_t*)"on"))
- ax25Cfg.allowNonAprs = 1;
- else if(checkcmd(&cmd[8], 3, (uint8_t*)"off"))
- ax25Cfg.allowNonAprs = 0;
+ if(!strncmp(&cmd[8], "on", 2))
+ Ax25Config.allowNonAprs = 1;
+ else if(!strncmp(&cmd[8], "off", 2))
+ Ax25Config.allowNonAprs = 0;
else
- err = 1;
-
- if(err)
- {
- term_sendString((uint8_t*)"Incorrect command!\r\n", 0);
- }
- else
- {
- term_sendString((uint8_t*)"OK\r\n", 0);
- }
- term_sendBuf(src);
- return;
+ err = true;
}
-
- term_sendString((uint8_t*)"Unknown command. For command list type \"help\"\r\n", 0);
- term_sendBuf(src);
+ else
+ UartSendString(src, "Unknown command. For command list type \"help\"\r\n", 0);
+ if(err)
+ UartSendString(src, "Incorrect command\r\n", 0);
+ else
+ UartSendString(src, "OK\r\n", 0);
}
diff --git a/Src/usbd_cdc_if.c b/Src/usbd_cdc_if.c
index 6880d53..3cc6912 100644
--- a/Src/usbd_cdc_if.c
+++ b/Src/usbd_cdc_if.c
@@ -24,6 +24,7 @@
/* USER CODE BEGIN INCLUDE */
#include "drivers/uart.h"
+#include "drivers/systick.h"
/* USER CODE END INCLUDE */
/* Private typedef -----------------------------------------------------------*/
@@ -132,7 +133,7 @@ static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS(uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
-
+static void handleUsbInterrupt(Uart *port);
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
@@ -264,32 +265,18 @@ static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
- /**
- * Z tej funkcji zaraz po odebraniu danych chcemy wyjsc, bo pozostanie w niej zablokuje mozliwosc nadawania czegokolwiek przez USB.
- * Poza tym ta funkcja jest tak naprawde czescia ISR.
- * Ustawiamy wiec flage z informacja, co odebralismy i to przetwarzamy w innym miejscu (w petli glownej).
- */
-
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
//this function receives 64 bytes max.
//add them to the buffer and set USB "interrupt" flag
- for(uint16_t cv = 0; cv < *Len; cv++)
+ for(uint16_t i = 0; i < *Len; i++)
{
- usbcdcdata[usbcdcidx++] = *(Buf + cv);
- if(usbcdcidx == UARTBUFLEN)
- {
- usbcdcidx = 0;
- return USBD_FAIL;
- }
- USBint = 1;
+ UartUsb.rxBuffer[UartUsb.rxBufferHead++] = Buf[i];
+ UartUsb.rxBufferHead %= UART_BUFFER_SIZE;
}
-
-
-
-
+ handleUsbInterrupt(&UartUsb);
return (USBD_OK);
/* USER CODE END 6 */
@@ -312,15 +299,16 @@ uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
/* USER CODE BEGIN 7 */
if(hUsbDeviceFS.dev_state != 3) return USBD_BUSY;
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
- if (hcdc->TxState > 1){ //jesli cos wiekszego od 1, to USB nie jest podlaczone
+ if (hcdc->TxState > 1)
+ {
return USBD_BUSY;
}
uint32_t to = 0;
while(hcdc->TxState != 0)
{
- //czekamy dopoki USB jest zajete, bo inaczej bedziemy tracic dane
to++;
- if(to > 90000) return USBD_FAIL; //trzeba bylo zrobic jakis timeout
+ if(to > 90000) //wait for a while if USB busy
+ return USBD_FAIL;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
@@ -330,7 +318,30 @@ 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
+ 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
+ {
+ port->rxType = DATA_TERM;
+ port->kissTimer = 0;
+ }
+ }
+}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**