Updated to Rev 0.4a

This commit is contained in:
adrcs 2025-02-07 13:49:26 -07:00 committed by GitHub
parent 41fffe4785
commit a7b2b63790
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 253 additions and 54 deletions

View file

@ -29,6 +29,7 @@
#include "usart.h" #include "usart.h"
#define __USE_SETUP_PARAMS 1 // set to 1 to use setup parameters #define __USE_SETUP_PARAMS 1 // set to 1 to use setup parameters
#define US 0 // station is in the US
// defined elsewhere // defined elsewhere
extern char *modTypes[]; extern char *modTypes[];

View file

@ -12,7 +12,7 @@
typedef uint8_t DATA_ELEMENT; // data element typedef uint8_t DATA_ELEMENT; // data element
#define BUFFER_EMPTY(x) (x.nDataBytes == 0) #define BUFFER_EMPTY(x) (x.nDataBytes == 0)
#define BUFFER_NO_DATA 0 #define BUFFER_NO_DATA 0
#define bufferSIZE 2048 // large buffer #define bufferSIZE 512 // large buffer
#endif /* INC_STREAMBUFFER_H_ */ #endif /* INC_STREAMBUFFER_H_ */

View file

@ -33,13 +33,15 @@ typedef uint16_t BUFFER_SIZE_T; // buffer size type
typedef uint8_t DATA_ELEMENT; // buffer data element typedef uint8_t DATA_ELEMENT; // buffer data element
// uart HAL handle // uart HAL handle
extern UART_HandleTypeDef huart1; extern UART_HandleTypeDef huart1; // console UART
extern UART_HandleTypeDef hlpuart1 ; // GPS UART
// logger defines // logger defines
#define LOG_NOTICE 0 // notice #define LOG_NOTICE 0 // notice
#define LOG_ERROR 1 // error #define LOG_ERROR 1 // error
#define LOG_SEVERE 2 // severe error #define LOG_SEVERE 2 // severe error
// logger
void logger(int severity, char *format, ...); void logger(int severity, char *format, ...);
// API calls // API calls
@ -51,4 +53,9 @@ BOOL USART_Send_String(const char *string, size_t len);
BOOL USART_Send_Char(const char c); BOOL USART_Send_Char(const char c);
void USART_Print_string(char *format, ...); void USART_Print_string(char *format, ...);
// same as USART but for LPUART: no Tx functions
void LPUART_RxBuffer_reset(void);
size_t gpsbuffer_bytesInBuffer(void);
DATA_ELEMENT gpsbuffer_get(UART_TIMEOUT_T timeout);
#endif /* INC_USART_H_ */ #endif /* INC_USART_H_ */

View file

@ -33,26 +33,41 @@
#include <FreeRTOS.h> #include <FreeRTOS.h>
#include <stm32wl3x_hal.h> #include <stm32wl3x_hal.h>
#include "config.h"
#include "frame.h" #include "frame.h"
#include "tasks.h" #include "tasks.h"
#include "setup.h" #include "setup.h"
#include "utils.h" #include "utils.h"
#include "tod.h" #include "tod.h"
#include "usart.h"
// config // config
#define __ENABLE_GPS 0 // set to 1 if you have GPS attached
#define __SPEED_DAEMON 0 // send beacon every 5 seconds for testing purposes #define __SPEED_DAEMON 0 // send beacon every 5 seconds for testing purposes
// local defines // local defines
#define MAX_BEACON 80 #define MAX_BEACON 80 // max beacon string
#define GPS_FIX_LEN 20 // gps fix length #define GPS_FIX_LEN 20 // gps fix length
#define GPS_BFR_SIZE 140 // GPS buffer size
// NMEA GGA Sentence fields // NMEA GGA Sentence fields
#define GGA_TAG 0 // message tag char *nmeaMsgTag = "RMC"; // sentence we are processing
#define GGA_TIMESTAMP 1 // time of fix enum {
#define GGA_LATITUDE 2 // latitude NMEA_TAG=0, // message tag
#define GGA_NS_HEMI 3 // latitude hemisphere NMEA_TIMESTAMP, // time of fix'
#define GGA_LONGITUDE 4 // longitude NMEA_STATUS, // status
#define GGA_EW_HEMI 5 // longitude hemisphere NMEA_LATITUDE, // latitude
NMEA_NS_HEMI, // latitude hemisphere
NMEA_LONGITUDE, // longitude
NMEA_EW_HEMI, // longitude hemisphere
NMEA_MIN_FLDS // minimum fields in GPS message
};
// NMEA processing states
enum {
NMEA_STATE_SOM=0, // start of message
NMEA_STATE_MSG, // in the message
};
// hemispheres // hemispheres
enum { enum {
N_HEMI=0, // North N_HEMI=0, // North
@ -68,27 +83,34 @@ uint8_t hemispheres[N_HEMIS] = {
uint32_t timerInitValue; // value to initialize timer uint32_t timerInitValue; // value to initialize timer
uint32_t timerCtrValue; // current counter uint32_t timerCtrValue; // current counter
BEACON_HEADER beacon_hdr; // beacon header BEACON_HEADER beacon_hdr; // beacon header
uint8_t bcnPayload[MAX_BEACON]; // beacon payload uint8_t bcnPayload[MAX_BEACON]; // beacon payload
BOOL gpsMessageRx = FALSE; BOOL gpsMessageRx = FALSE;
BOOL GPSBusy=FALSE;
TIMEOFDAY wallClockTime;
#if __ENABLE_GPS #if __ENABLE_GPS
#define GPS_BUFFER_SIZE 200 // data for GPS
// LPUART for GPS receiver uint8_t GPSMsgBuf[GPS_BFR_SIZE];
extern hlpuart1 UART_HandleTypeDef; // HAL Handle to LPUART uint8_t GPSEchoBuf[GPS_BFR_SIZE];
uint8_t GPSMsgBuf[GPS_BUFFER_SIZE]; uint8_t GPSProcBuf[GPS_BFR_SIZE];
uint8_t *GPSBufPtr;
uint8_t GPSMsgSize;
uint8_t NMEAState;
//
BOOL haveGPSFix = FALSE;
BOOL gpsEchoReady=FALSE;
//
char GPSLat[GPS_FIX_LEN]; char GPSLat[GPS_FIX_LEN];
char GPSLong[GPS_FIX_LEN]; char GPSLong[GPS_FIX_LEN];
char GPSFixTime[GPS_FIX_LEN]; char GPSFixTime[GPS_FIX_LEN];
BOOL haveGPSFix = FALSE; char *gpsFlds[GPS_BFR_SIZE];
char *gpsFlds[GPS_FIX_LEN];
#else // fwd Refs in this module in GPS mode
TIMEOFDAY wallClockTime; BOOL processGPSMessage(uint8_t *GPSMsgBuf, uint8_t bufferSize);
#endif #endif
// fwd refs here.. //fwd refs w/o GPS
void GPSFormat(char *buffer, double value, uint8_t hePos, uint8_t heNeg); void GPSFormat(char *buffer, double value, uint8_t hePos, uint8_t heNeg);
// initialization: calculate the init value in // initialization: calculate the init value in
@ -107,9 +129,12 @@ void Beacon_Task_init(void)
// GPS Init // GPS Init
#if __ENABLE_GPS #if __ENABLE_GPS
HAL_LPUART_Receive_DMA(&hlpuart1, (uint8_t*)GPSMsgBuf, GPS_BUFFER_SIZE);
gpsMessageRx = FALSE; gpsMessageRx = FALSE;
haveGPSFix = FALSE; haveGPSFix = FALSE;
gpsEchoReady = FALSE;
GPSBufPtr = GPSMsgBuf;
GPSBusy = FALSE;
NMEAState=NMEA_STATE_SOM;
#endif #endif
} }
@ -119,10 +144,12 @@ void Beacon_Task_exec(void)
{ {
#if __ENABLE_GPS #if __ENABLE_GPS
if(gpsMessageRx) { if(gpsMessageRx) {
gpsMessageRx = FALSE; // process the message
ifprocessGPSMessage(GPSMsgBuf, GPS_BUFFER_SIZE)) if(processGPSMessage(GPSProcBuf, (uint8_t)strlen((char *)GPSProcBuf))) {
haveGPSFix = TRUE; haveGPSFix = TRUE;
} }
gpsMessageRx = FALSE;
}
#endif #endif
if(timerCtrValue > 0) { if(timerCtrValue > 0) {
@ -148,10 +175,13 @@ void Beacon_Task_exec(void)
if(haveGPSFix) { if(haveGPSFix) {
strcpy(pPayload, "GPS,"); strcpy(pPayload, "GPS,");
strcat(pPayload, GPSLat); strcat(pPayload, GPSLat);
strcat(pPayload, ",");
strcat(pPayload, GPSLong); strcat(pPayload, GPSLong);
strcat(pPayload, ",");
strcat(pPayload, GPSFixTime); strcat(pPayload, GPSFixTime);
strcat(pPayload, ",");
} else { } else {
#else #endif
// setup struct generated payload // setup struct generated payload
strcpy(pPayload, "FXD,"); strcpy(pPayload, "FXD,");
pPayload += strlen(pPayload); pPayload += strlen(pPayload);
@ -161,7 +191,10 @@ void Beacon_Task_exec(void)
pPayload += strlen(pPayload); pPayload += strlen(pPayload);
double dlong = ascii2double(setup_memory.params.setup_data.longitude); double dlong = ascii2double(setup_memory.params.setup_data.longitude);
GPSFormat(pPayload, dlong, E_HEMI, W_HEMI); GPSFormat(pPayload, dlong, E_HEMI, W_HEMI);
strcat(pPayload, ","); strcat(pPayload, ",,");
#if __ENABLE_GPS
}
#endif
pPayload += strlen(pPayload); pPayload += strlen(pPayload);
// Use RTC for time // Use RTC for time
@ -171,7 +204,6 @@ void Beacon_Task_exec(void)
// home grid square // home grid square
strcat(pPayload, setup_memory.params.setup_data.gridSq); strcat(pPayload, setup_memory.params.setup_data.gridSq);
#endif
// firmware version // firmware version
int pos = strlen((char *)p2); int pos = strlen((char *)p2);
@ -206,39 +238,93 @@ void GPSFormat(char *buffer, double value, uint8_t hePos, uint8_t heNeg)
sprintf(buffer, "%d%02d.%05d%c", whole, min, ifract, hemispheres[hemi]); sprintf(buffer, "%d%02d.%05d%c", whole, min, ifract, hemispheres[hemi]);
} }
/*
* Process GPS data from LPUART: runs at a higher priority
*/
void GPS_Task_exec(void)
{
#if __ENABLE_GPS
char c;
int nBytesinBuff;
if((nBytesinBuff=gpsbuffer_bytesInBuffer()) == 0)
return;
for(int i=0;i<nBytesinBuff;i++) {
c = (char)gpsbuffer_get(0);
switch(NMEAState) {
// waiting for a start of message
case NMEA_STATE_SOM:
if(c != '$')
break;
GPSBufPtr = GPSMsgBuf;
NMEAState=NMEA_STATE_MSG;
break;
// collecting chars in a message
case NMEA_STATE_MSG:
*GPSBufPtr++ = c;
GPSMsgSize = GPSBufPtr - GPSMsgBuf;
if((c == '*') || (GPSMsgSize >= GPS_BFR_SIZE)) {
*GPSBufPtr = '\0';
GPSMsgSize++;
memcpy(GPSEchoBuf, GPSMsgBuf, GPSMsgSize);
gpsMessageRx = TRUE;
memcpy(GPSProcBuf, GPSMsgBuf, GPSMsgSize);
memcpy(GPSEchoBuf, GPSMsgBuf, GPSMsgSize);
gpsEchoReady = TRUE;
NMEAState=NMEA_STATE_SOM;
}
break;
}
}
#else
return; // unused code
#endif
}
#if __ENABLE_GPS #if __ENABLE_GPS
/* /*
* Process an inbound GPS message * Process an inbound GPS message
*/ */
BOOL processGPSMessage(GPSMsgBuf, GPS_BUFFER_SIZE) BOOL processGPSMessage(uint8_t *GPSdata, uint8_t bufferSize)
{ {
int limit = (int)strlen(GPSMsgBuf); char *msg = (char *)GPSdata;
nParams = explode_string(GPSMsgBuf, gpsFlds, limit, ',', '"'); uint8_t nParams = explode_string(msg, gpsFlds, bufferSize, ',', '"');
if (nParams == 0) if ((nParams == 0) || (nParams < NMEA_MIN_FLDS))
return FALSE; return FALSE;
// brute force position fix // brute force position fix
if(strcmp(gpsFlds[GGA_TAG[strlen(GGA_TAG)-strlen("GGA")]],"GGA")) // check for message with GGA at the end
char *gpsTag = gpsFlds[NMEA_TAG];
gpsTag += strlen(gpsTag)-strlen(nmeaMsgTag);
if(strcmp(gpsTag, nmeaMsgTag))
return FALSE; return FALSE;
strpy(GPSFixTime, gpsFlds[GGA_TIMESTAMP]); strcpy(GPSFixTime, gpsFlds[NMEA_TIMESTAMP]);
strcpy(GPSLat, gpsFlds[GGA_LATITUDE]); strcpy(GPSLat, gpsFlds[NMEA_LATITUDE]);
strcat(GPSLat, gpsFlds[GGA_NS_HEMI]); strcat(GPSLat, gpsFlds[NMEA_NS_HEMI]);
strcpy(GPSLong, gpsFlds[GGA_LONGITUDE]); strcpy(GPSLong, gpsFlds[NMEA_LONGITUDE]);
strcat(GPSLong, gpsFlds[GGA_EW_HEMI]); strcat(GPSLong, gpsFlds[NMEA_EW_HEMI]);
return TRUE; return TRUE;
} }
/* /*
* callback from GPS receiver when rx is complete * echo the last GPS message on the console
*/ */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) void GPSEcho(void)
{ {
HAL_LPUART_Receive_DMA(&hlpuart1, (uint8_t*)GPSMsgBuf, GPS_BUFFER_SIZE); if(!gpsEchoReady)
gpsMessageRx = TRUE;
return; return;
USART_Print_string("%s\r\n", (char *)GPSEchoBuf);
gpsEchoReady=FALSE;
} }
#endif #endif

View file

@ -34,7 +34,6 @@
#include <stm32wl3x_nucleo.h> #include <stm32wl3x_nucleo.h>
#endif #endif
#include <cmsis_os2.h> #include <cmsis_os2.h>
#include <FreeRTOS.h> #include <FreeRTOS.h>
#include <semphr.h> #include <semphr.h>
@ -429,7 +428,7 @@ void Frame_Rxtask_exec(void)
case ICMP_TYPE: case ICMP_TYPE:
Mesh_ProcessBeacon((void *)&rFrame, Stats.lastRSSI); Mesh_ProcessBeacon((void *)&rFrame, Stats.lastRSSI);
#if __DUMP_BEACON #if __DUMP_BEACON
EnqueChatFrame((void *)&rFrame, length); EnqueChatFrame((void *)&rFrame, length+3);
#endif #endif
Stats.nBeacons++; Stats.nBeacons++;
break; break;

View file

@ -28,6 +28,7 @@
#include "tasks.h" #include "tasks.h"
#include "utils.h" #include "utils.h"
#include "tod.h" #include "tod.h"
#include "config.h"
// menu state // menu state
uint8_t menuState; // menu state uint8_t menuState; // menu state
@ -97,6 +98,7 @@ void Print_Frame_stats(FRAME_STATS *stats);
void Print_Radio_errors(uint32_t errs); void Print_Radio_errors(uint32_t errs);
void Print_FSM_state(uint8_t state); void Print_FSM_state(uint8_t state);
uint8_t getEntry(int activeMenu, int item); uint8_t getEntry(int activeMenu, int item);
uint8_t getKeyEntry(void);
// list of menus // list of menus
enum { enum {
@ -212,6 +214,13 @@ uint8_t setParam(void)
{ {
return(getEntry(activeMenu, sel_item)); return(getEntry(activeMenu, sel_item));
} }
#if __ENABLE_GPS
uint8_t gpsEcho(void)
{
GPSEcho();
return(getKeyEntry());
}
#endif
/* /*
* main menu definition * main menu definition
@ -226,12 +235,20 @@ struct menuItems_t {
}; };
// main menu // main menu
#if __ENABLE_GPS
#define N_MAINMENU 11 // additional menu item for GPS
#else
#define N_MAINMENU 10 // number of lines in the menu #define N_MAINMENU 10 // number of lines in the menu
#endif
struct menuItems_t mainMenu[N_MAINMENU] = { struct menuItems_t mainMenu[N_MAINMENU] = {
{ "List setup parameters\r\n", 'A', printAllSetup }, { "List setup parameters\r\n", 'A', printAllSetup },
{ "Mesh Status\r\n", 'B', listMesh }, { "Mesh Status\r\n", 'B', listMesh },
{ "Chat Mode\r\n", 'C', chatMode }, { "Chat Mode\r\n", 'C', chatMode },
{ "Dump Frame stats\r\n", 'D', showstats }, { "Dump Frame stats\r\n", 'D', showstats },
#if __ENABLE_GPS
{ "GPS Echo mode\r\n", 'G', gpsEcho },
#endif
{ "LED test\r\n", 'L', ledTest }, { "LED test\r\n", 'L', ledTest },
{ "Set Radio Parameters\r\n", 'R', setRadio }, { "Set Radio Parameters\r\n", 'R', setRadio },
{ "Set Station Parameters\r\n", 'S', setStation }, { "Set Station Parameters\r\n", 'S', setStation },

View file

@ -96,7 +96,13 @@ STN_PARAMS *GetStationParams(void) // get the station params
// returns true if callsigns match // returns true if callsigns match
BOOL CompareToMyCall(char *call) BOOL CompareToMyCall(char *call)
{ {
if(!strncmp(call, setup_memory.params.setup_data.stnCall, MAX_CALL)) char expCall[20];
// make sure call sign is padded out to 6 characters b4 comparison
strcpy(expCall, setup_memory.params.setup_data.stnCall);
strcat(expCall, " ");
if(!strncmp(call, expCall, MAX_CALL))
return TRUE; return TRUE;
return FALSE; return FALSE;
} }

View file

@ -29,6 +29,7 @@
#include <FreeRTOS.h> #include <FreeRTOS.h>
#include <semphr.h> #include <semphr.h>
#include "config.h"
#include "stream_buffer.h" #include "stream_buffer.h"
#include "types.h" #include "types.h"
#include "streambuffer.h" #include "streambuffer.h"
@ -46,33 +47,59 @@ StaticStreamBuffer_t USART_StreamBuffer;
SemaphoreHandle_t txCompleted; // tx completed semaphore SemaphoreHandle_t txCompleted; // tx completed semaphore
static DATA_ELEMENT USARTRxChar[10]; // last received character static DATA_ELEMENT USARTRxChar[10]; // last received character
uint8_t buffer_data[bufferSIZE]; uint8_t usart_data[bufferSIZE];
char usartPrintBuffer[200]; char usartPrintBuffer[200];
// fwd refs here... // fwd refs here...
void USART_Receive_char(void); void USART_Receive_char(void);
#if __ENABLE_GPS
#define LPUART_DMA_SIZE 32
static DATA_ELEMENT LPUARTRxChar[LPUART_DMA_SIZE];
void LPUART_Receive_char(void);
StreamBufferHandle_t LPUART_RxBuffer; // handle to buffer
StaticStreamBuffer_t LPUART_StreamBuffer;
uint8_t gps_data[bufferSIZE];
#endif
/* /*
* API for the rx data buffer * API for the rx data buffer
*/ */
void USART_API_init(void) void USART_API_init(void)
{ {
USART_RxBuffer = xStreamBufferCreateStatic(bufferSIZE, 1, buffer_data, &USART_StreamBuffer);
USART_RxBuffer_reset();
// create the tx completed semaphore // create the tx completed semaphore
txCompleted = xSemaphoreCreateBinary(); txCompleted = xSemaphoreCreateBinary();
// start the rx process // start USART
USART_RxBuffer = xStreamBufferCreateStatic(bufferSIZE, 1, usart_data, &USART_StreamBuffer);
USART_RxBuffer_reset();
USART_Receive_char(); USART_Receive_char();
#if __ENABLE_GPS
LPUART_RxBuffer = xStreamBufferCreateStatic(bufferSIZE, 1, gps_data, &LPUART_StreamBuffer);
LPUART_RxBuffer_reset();
LPUART_Receive_char();
#endif
} }
// reset the data buffer
void USART_RxBuffer_reset(void) void USART_RxBuffer_reset(void)
{ {
xStreamBufferReset(USART_RxBuffer); xStreamBufferReset(USART_RxBuffer);
return; return;
} }
#if __ENABLE_GPS
// reset the LPUART Buffer
void LPUART_RxBuffer_reset(void)
{
xStreamBufferReset(LPUART_RxBuffer);
return;
}
#endif
// return the number of byte in the buffer // return the number of byte in the buffer
size_t databuffer_bytesInBuffer(void) size_t databuffer_bytesInBuffer(void)
{ {
@ -99,6 +126,35 @@ DATA_ELEMENT databuffer_get(UART_TIMEOUT_T timeout)
return retval; return retval;
} }
/*
* Similar but from GPS buffer
*/
#if __ENABLE_GPS
// return the number of byte in the buffer
size_t gpsbuffer_bytesInBuffer(void)
{
size_t nBytes = xStreamBufferBytesAvailable(LPUART_RxBuffer);
return nBytes;
}
// get a bytes
DATA_ELEMENT gpsbuffer_get(UART_TIMEOUT_T timeout)
{
DATA_ELEMENT retval;
TickType_t tickTimeout;
if(timeout == 0)
tickTimeout = portMAX_DELAY;
else
tickTimeout = pdMS_TO_TICKS(timeout);
if(xStreamBufferReceive(LPUART_RxBuffer, &retval, 1, tickTimeout) == 0)
return BUFFER_NO_DATA;
return retval;
}
#endif
// see if the buffer contains a keyword, save data up to it if needed // see if the buffer contains a keyword, save data up to it if needed
BOOL databuffer_contains(const char *tag, UART_TIMEOUT_T rx_timeout, BOOL saveData, char *SaveBuffer) BOOL databuffer_contains(const char *tag, UART_TIMEOUT_T rx_timeout, BOOL saveData, char *SaveBuffer)
{ {
@ -193,13 +249,40 @@ void USART_Receive_char(void)
HAL_UART_Receive_IT(&huart1,(uint8_t *)USARTRxChar,1); HAL_UART_Receive_IT(&huart1,(uint8_t *)USARTRxChar,1);
} }
// callback function when rx is completed: overrides previous // callback function when rx is completed: overrides previous
// __weak definition // __weak definition
// NB: Console USART and GPS LPUART share the same HAL routine
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{ {
#if __ENABLE_GPS
// do not store any control chars // service the LPUART
if(huart->Instance == LPUART1) {
xStreamBufferSendFromISR(LPUART_RxBuffer, LPUARTRxChar, 1, NULL);
HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)LPUARTRxChar,1);
return;
}
#endif
// service the USART
xStreamBufferSendFromISR(USART_RxBuffer, USARTRxChar, 1, NULL); xStreamBufferSendFromISR(USART_RxBuffer, USARTRxChar, 1, NULL);
HAL_UART_Receive_IT(&huart1,(uint8_t *)USARTRxChar,1); HAL_UART_Receive_IT(&huart1,(uint8_t *)USARTRxChar,1);
} }
#if __ENABLE_GPS
// receive a byte with DMA, wait for DMA completed interrupt
void LPUART_Receive_char(void)
{
HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)LPUARTRxChar,1);
// HAL_UARTEx_ReceiveToIdle_DMA(&hlpuart1,(uint8_t *)LPUARTRxChar,LPUART_DMA_SIZE);
//__HAL_DMA_DISABLE_IT(&hlpuart1, DMA_IT_HT);
}
// callback from GPS Rx
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
xStreamBufferSendFromISR(LPUART_RxBuffer, LPUARTRxChar, Size, NULL);
HAL_UARTEx_ReceiveToIdle_DMA(&hlpuart1,(uint8_t *)LPUARTRxChar,LPUART_DMA_SIZE);
}
#endif