diff --git a/code/IP400/Inc/setup.h b/code/IP400/Inc/setup.h index 6e61e79..41bda26 100644 --- a/code/IP400/Inc/setup.h +++ b/code/IP400/Inc/setup.h @@ -29,6 +29,7 @@ #include "usart.h" #define __USE_SETUP_PARAMS 1 // set to 1 to use setup parameters +#define US 0 // station is in the US // defined elsewhere extern char *modTypes[]; diff --git a/code/IP400/Inc/streambuffer.h b/code/IP400/Inc/streambuffer.h index 11deb76..bcad0da 100644 --- a/code/IP400/Inc/streambuffer.h +++ b/code/IP400/Inc/streambuffer.h @@ -12,7 +12,7 @@ typedef uint8_t DATA_ELEMENT; // data element #define BUFFER_EMPTY(x) (x.nDataBytes == 0) #define BUFFER_NO_DATA 0 -#define bufferSIZE 2048 // large buffer +#define bufferSIZE 512 // large buffer #endif /* INC_STREAMBUFFER_H_ */ diff --git a/code/IP400/Inc/usart.h b/code/IP400/Inc/usart.h index c3eb5f7..679d83b 100644 --- a/code/IP400/Inc/usart.h +++ b/code/IP400/Inc/usart.h @@ -33,13 +33,15 @@ typedef uint16_t BUFFER_SIZE_T; // buffer size type typedef uint8_t DATA_ELEMENT; // buffer data element // uart HAL handle -extern UART_HandleTypeDef huart1; +extern UART_HandleTypeDef huart1; // console UART +extern UART_HandleTypeDef hlpuart1 ; // GPS UART // logger defines #define LOG_NOTICE 0 // notice #define LOG_ERROR 1 // error #define LOG_SEVERE 2 // severe error +// logger void logger(int severity, char *format, ...); // API calls @@ -51,4 +53,9 @@ BOOL USART_Send_String(const char *string, size_t len); BOOL USART_Send_Char(const char c); 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_ */ diff --git a/code/IP400/Src/beacon.c b/code/IP400/Src/beacon.c index f22ce18..e035242 100644 --- a/code/IP400/Src/beacon.c +++ b/code/IP400/Src/beacon.c @@ -33,26 +33,41 @@ #include #include +#include "config.h" #include "frame.h" #include "tasks.h" #include "setup.h" #include "utils.h" #include "tod.h" +#include "usart.h" // 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 // local defines -#define MAX_BEACON 80 -#define GPS_FIX_LEN 20 // gps fix length +#define MAX_BEACON 80 // max beacon string +#define GPS_FIX_LEN 20 // gps fix length +#define GPS_BFR_SIZE 140 // GPS buffer size + // NMEA GGA Sentence fields -#define GGA_TAG 0 // message tag -#define GGA_TIMESTAMP 1 // time of fix -#define GGA_LATITUDE 2 // latitude -#define GGA_NS_HEMI 3 // latitude hemisphere -#define GGA_LONGITUDE 4 // longitude -#define GGA_EW_HEMI 5 // longitude hemisphere +char *nmeaMsgTag = "RMC"; // sentence we are processing +enum { + NMEA_TAG=0, // message tag + NMEA_TIMESTAMP, // time of fix' + NMEA_STATUS, // status + 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 enum { N_HEMI=0, // North @@ -68,27 +83,34 @@ uint8_t hemispheres[N_HEMIS] = { uint32_t timerInitValue; // value to initialize timer uint32_t timerCtrValue; // current counter - BEACON_HEADER beacon_hdr; // beacon header uint8_t bcnPayload[MAX_BEACON]; // beacon payload - BOOL gpsMessageRx = FALSE; +BOOL GPSBusy=FALSE; +TIMEOFDAY wallClockTime; #if __ENABLE_GPS -#define GPS_BUFFER_SIZE 200 -// LPUART for GPS receiver -extern hlpuart1 UART_HandleTypeDef; // HAL Handle to LPUART -uint8_t GPSMsgBuf[GPS_BUFFER_SIZE]; +// data for GPS +uint8_t GPSMsgBuf[GPS_BFR_SIZE]; +uint8_t GPSEchoBuf[GPS_BFR_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 GPSLong[GPS_FIX_LEN]; char GPSFixTime[GPS_FIX_LEN]; -BOOL haveGPSFix = FALSE; -char *gpsFlds[GPS_FIX_LEN]; -#else -TIMEOFDAY wallClockTime; +char *gpsFlds[GPS_BFR_SIZE]; + +// fwd Refs in this module in GPS mode +BOOL processGPSMessage(uint8_t *GPSMsgBuf, uint8_t bufferSize); #endif -// fwd refs here.. +//fwd refs w/o GPS void GPSFormat(char *buffer, double value, uint8_t hePos, uint8_t heNeg); // initialization: calculate the init value in @@ -107,9 +129,12 @@ void Beacon_Task_init(void) // GPS Init #if __ENABLE_GPS - HAL_LPUART_Receive_DMA(&hlpuart1, (uint8_t*)GPSMsgBuf, GPS_BUFFER_SIZE); gpsMessageRx = FALSE; haveGPSFix = FALSE; + gpsEchoReady = FALSE; + GPSBufPtr = GPSMsgBuf; + GPSBusy = FALSE; + NMEAState=NMEA_STATE_SOM; #endif } @@ -119,9 +144,11 @@ void Beacon_Task_exec(void) { #if __ENABLE_GPS if(gpsMessageRx) { - gpsMessageRx = FALSE; - ifprocessGPSMessage(GPSMsgBuf, GPS_BUFFER_SIZE)) + // process the message + if(processGPSMessage(GPSProcBuf, (uint8_t)strlen((char *)GPSProcBuf))) { haveGPSFix = TRUE; + } + gpsMessageRx = FALSE; } #endif @@ -148,10 +175,13 @@ void Beacon_Task_exec(void) if(haveGPSFix) { strcpy(pPayload, "GPS,"); strcat(pPayload, GPSLat); + strcat(pPayload, ","); strcat(pPayload, GPSLong); + strcat(pPayload, ","); strcat(pPayload, GPSFixTime); + strcat(pPayload, ","); } else { -#else +#endif // setup struct generated payload strcpy(pPayload, "FXD,"); pPayload += strlen(pPayload); @@ -161,7 +191,10 @@ void Beacon_Task_exec(void) pPayload += strlen(pPayload); double dlong = ascii2double(setup_memory.params.setup_data.longitude); GPSFormat(pPayload, dlong, E_HEMI, W_HEMI); - strcat(pPayload, ","); + strcat(pPayload, ",,"); +#if __ENABLE_GPS + } +#endif pPayload += strlen(pPayload); // Use RTC for time @@ -171,7 +204,6 @@ void Beacon_Task_exec(void) // home grid square strcat(pPayload, setup_memory.params.setup_data.gridSq); -#endif // firmware version 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]); } + + +/* + * 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= 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 /* * Process an inbound GPS message */ -BOOL processGPSMessage(GPSMsgBuf, GPS_BUFFER_SIZE) +BOOL processGPSMessage(uint8_t *GPSdata, uint8_t bufferSize) { - int limit = (int)strlen(GPSMsgBuf); - nParams = explode_string(GPSMsgBuf, gpsFlds, limit, ',', '"'); - if (nParams == 0) + char *msg = (char *)GPSdata; + uint8_t nParams = explode_string(msg, gpsFlds, bufferSize, ',', '"'); + if ((nParams == 0) || (nParams < NMEA_MIN_FLDS)) return FALSE; - //brute force position fix - if(strcmp(gpsFlds[GGA_TAG[strlen(GGA_TAG)-strlen("GGA")]],"GGA")) + // brute force position fix + // check for message with GGA at the end + char *gpsTag = gpsFlds[NMEA_TAG]; + gpsTag += strlen(gpsTag)-strlen(nmeaMsgTag); + if(strcmp(gpsTag, nmeaMsgTag)) return FALSE; - strpy(GPSFixTime, gpsFlds[GGA_TIMESTAMP]); + strcpy(GPSFixTime, gpsFlds[NMEA_TIMESTAMP]); - strcpy(GPSLat, gpsFlds[GGA_LATITUDE]); - strcat(GPSLat, gpsFlds[GGA_NS_HEMI]); + strcpy(GPSLat, gpsFlds[NMEA_LATITUDE]); + strcat(GPSLat, gpsFlds[NMEA_NS_HEMI]); - strcpy(GPSLong, gpsFlds[GGA_LONGITUDE]); - strcat(GPSLong, gpsFlds[GGA_EW_HEMI]); + strcpy(GPSLong, gpsFlds[NMEA_LONGITUDE]); + strcat(GPSLong, gpsFlds[NMEA_EW_HEMI]); 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); - gpsMessageRx = TRUE; - return; + if(!gpsEchoReady) + return; + + USART_Print_string("%s\r\n", (char *)GPSEchoBuf); + gpsEchoReady=FALSE; } #endif diff --git a/code/IP400/Src/frame.c b/code/IP400/Src/frame.c index a668944..fe8bdf2 100644 --- a/code/IP400/Src/frame.c +++ b/code/IP400/Src/frame.c @@ -34,7 +34,6 @@ #include #endif - #include #include #include @@ -429,7 +428,7 @@ void Frame_Rxtask_exec(void) case ICMP_TYPE: Mesh_ProcessBeacon((void *)&rFrame, Stats.lastRSSI); #if __DUMP_BEACON - EnqueChatFrame((void *)&rFrame, length); + EnqueChatFrame((void *)&rFrame, length+3); #endif Stats.nBeacons++; break; diff --git a/code/IP400/Src/menu.c b/code/IP400/Src/menu.c index 29c2dc5..d6690d8 100644 --- a/code/IP400/Src/menu.c +++ b/code/IP400/Src/menu.c @@ -28,6 +28,7 @@ #include "tasks.h" #include "utils.h" #include "tod.h" +#include "config.h" // 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_FSM_state(uint8_t state); uint8_t getEntry(int activeMenu, int item); +uint8_t getKeyEntry(void); // list of menus enum { @@ -212,6 +214,13 @@ uint8_t setParam(void) { return(getEntry(activeMenu, sel_item)); } +#if __ENABLE_GPS +uint8_t gpsEcho(void) +{ + GPSEcho(); + return(getKeyEntry()); +} +#endif /* * main menu definition @@ -226,12 +235,20 @@ struct menuItems_t { }; // 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 +#endif + struct menuItems_t mainMenu[N_MAINMENU] = { { "List setup parameters\r\n", 'A', printAllSetup }, { "Mesh Status\r\n", 'B', listMesh }, { "Chat Mode\r\n", 'C', chatMode }, { "Dump Frame stats\r\n", 'D', showstats }, +#if __ENABLE_GPS + { "GPS Echo mode\r\n", 'G', gpsEcho }, +#endif { "LED test\r\n", 'L', ledTest }, { "Set Radio Parameters\r\n", 'R', setRadio }, { "Set Station Parameters\r\n", 'S', setStation }, diff --git a/code/IP400/Src/setup.c b/code/IP400/Src/setup.c index 789cdff..844f869 100644 --- a/code/IP400/Src/setup.c +++ b/code/IP400/Src/setup.c @@ -96,7 +96,13 @@ STN_PARAMS *GetStationParams(void) // get the station params // returns true if callsigns match 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 FALSE; } diff --git a/code/IP400/Src/usart.c b/code/IP400/Src/usart.c index 0962f68..150a6f5 100644 --- a/code/IP400/Src/usart.c +++ b/code/IP400/Src/usart.c @@ -29,6 +29,7 @@ #include #include +#include "config.h" #include "stream_buffer.h" #include "types.h" #include "streambuffer.h" @@ -46,33 +47,59 @@ StaticStreamBuffer_t USART_StreamBuffer; SemaphoreHandle_t txCompleted; // tx completed semaphore static DATA_ELEMENT USARTRxChar[10]; // last received character -uint8_t buffer_data[bufferSIZE]; +uint8_t usart_data[bufferSIZE]; char usartPrintBuffer[200]; // fwd refs here... 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 */ void USART_API_init(void) { - USART_RxBuffer = xStreamBufferCreateStatic(bufferSIZE, 1, buffer_data, &USART_StreamBuffer); - USART_RxBuffer_reset(); - // create the tx completed semaphore txCompleted = xSemaphoreCreateBinary(); - // start the rx process + // start USART + USART_RxBuffer = xStreamBufferCreateStatic(bufferSIZE, 1, usart_data, &USART_StreamBuffer); + USART_RxBuffer_reset(); 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) { xStreamBufferReset(USART_RxBuffer); 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 size_t databuffer_bytesInBuffer(void) { @@ -99,6 +126,35 @@ DATA_ELEMENT databuffer_get(UART_TIMEOUT_T timeout) 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 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); } + // callback function when rx is completed: overrides previous // __weak definition +// NB: Console USART and GPS LPUART share the same HAL routine void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { - - // do not store any control chars +#if __ENABLE_GPS + // 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); 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