/*--------------------------------------------------------------------------- Project: WL33_NUCLEO_UART File Name: beacon.c Author: MartinA Description: Beacon task. Sends a beacon frame periodically, based on timer in the setup structure. The beacon include position data in a readable format, which can come from a GPS receiver or the setup struct. Lat/Long data is sent in DDMM.MMMMM format. Define __ENABLE_GPS to enable the code. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version, provided this copyright notice is included. Copyright (c) Alberta Digital Radio Communications Society All rights reserved. Revision History: ---------------------------------------------------------------------------*/ #include #include #include #include #include #include #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 __SPEED_DAEMON 0 // send beacon every 5 seconds for testing purposes // local defines #define MAX_BEACON 80 // max beacon string #define GPS_FIX_LEN 20 // gps fix length #define GPS_BFR_SIZE 140 // GPS buffer size #if __ENABLE_GPS // NMEA GGA Sentence fields 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 }; #define N_NMEA_SEN 14 // number of NMEA sentences enum { NMEA_CMD_DISABLED=0, // disabled NMEA_CMD_ONCE, // once per fix NMEA_CMD_2FIX, // once every 2 fixes NMEA_CMD_3FIX, // once every 3 fixes NMEA_CMD_4FIX, // once every 4 fixes NMEA_CMD_5FIX, // once every 5 fixes }; char *nmeaCmd = "$PMTK314"; // command uint8_t senCmds[N_NMEA_SEN] = { NMEA_CMD_DISABLED, // 0:GLL disabled NMEA_CMD_ONCE, // 1: RMC once NMEA_CMD_DISABLED, // 2: VTG disabled NMEA_CMD_DISABLED, // 3: GGA disabled NMEA_CMD_DISABLED, // 4: GSA disabled NMEA_CMD_DISABLED, // 5: GSV disabled NMEA_CMD_DISABLED, // 6 not used NMEA_CMD_DISABLED, // 7 NMEA_CMD_DISABLED, // 13 NMEA_CMD_DISABLED, // 14 NMEA_CMD_DISABLED, // 15 NMEA_CMD_DISABLED, // 16 NMEA_CMD_DISABLED, // 17 NMEA_CMD_DISABLED // 18 }; #endif // hemispheres enum { N_HEMI=0, // North S_HEMI, // South E_HEMI, // East W_HEMI, // West N_HEMIS }; uint8_t hemispheres[N_HEMIS] = { 'N', 'S', 'E', 'W' }; 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 // 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; char cmdBuf[MAX_BEACON]; // BOOL haveGPSFix = FALSE; BOOL gpsEchoReady=FALSE; // char GPSLat[GPS_FIX_LEN]; char GPSLong[GPS_FIX_LEN]; char GPSFixTime[GPS_FIX_LEN]; char *gpsFlds[GPS_BFR_SIZE]; // fwd Refs in this module in GPS mode BOOL processGPSMessage(uint8_t *GPSMsgBuf, uint8_t bufferSize); void sendGPSCmd(void); #endif //fwd refs w/o GPS void GPSFormat(char *buffer, double value, uint8_t hePos, uint8_t heNeg); // initialization: calculate the init value in // quanta of MAIN_TASK_SCHED void Beacon_Task_init(void) { // higher speed for testing... #if __SPEED_DAEMON timerInitValue = 5 *1000/MAIN_TASK_SCHED; // every 5 seconds for testing timerCtrValue = 0; #else uint32_t timerTick = 60 * 1000/MAIN_TASK_SCHED; timerInitValue = setup_memory.params.setup_data.beaconInt * timerTick; timerCtrValue = 0; // set to timerInitValue to wait #endif // GPS Init #if __ENABLE_GPS gpsMessageRx = FALSE; haveGPSFix = FALSE; gpsEchoReady = FALSE; GPSBufPtr = GPSMsgBuf; GPSBusy = FALSE; NMEAState=NMEA_STATE_SOM; #endif } // this runs every MAIN_TASK_SCHED ms void Beacon_Task_exec(void) { #if __ENABLE_GPS if(gpsMessageRx) { // process the message if(processGPSMessage(GPSProcBuf, (uint8_t)strlen((char *)GPSProcBuf))) { haveGPSFix = TRUE; } gpsMessageRx = FALSE; } #endif if(timerCtrValue > 0) { timerCtrValue--; return; } timerCtrValue = timerInitValue; SendBeacon(); #if __ENABLE_GPS // send a command to the GPS every beacon interval sendGPSCmd(); #endif } void SendBeacon(void) { // start with the header beacon_hdr.setup.flags = setup_memory.params.setup_data.flags; beacon_hdr.setup.txPower = setup_memory.params.radio_setup.outputPower; beacon_hdr.setup.txFrequency = setup_memory.params.radio_setup.lFrequencyBase; beacon_hdr.setup.rxFrequency = setup_memory.params.radio_setup.lFrequencyBase; uint8_t *buf = bcnPayload; // beacon header: flags, txpower // brute force copy: compiler rounds SETUP_FLAGS to 32 bits *buf++ = beacon_hdr.hdrBytes[0]; *buf++ = beacon_hdr.hdrBytes[4]; // tx frequency for(int i=0;i 0.00 ? hePos : heNeg; value = fabs(value); // separate whole and fractional int whole = (int)value; double fract = value - (double)whole; // calculate minutes and fraction double dmin = 60.0 * fract; dmin = round(dmin * 100.0)/100.0; int min = floor(dmin); int ifract = (int)ceil((dmin-min) * 100000); 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 /* * Send a command to the GPS device to limit traffic */ void sendGPSCmd(void) { uint8_t cksum = 0; char *buf = cmdBuf; strcpy(buf, nmeaCmd); buf += strlen(nmeaCmd); for(int j=1;j