The software that runs on the Sentinel base station. This code is for the LPC1768.

Dependencies:   XBEE_900HP_SPI mbed-rtos mbed

Committer:
ottaviano3
Date:
Tue Aug 18 00:06:08 2015 +0000
Revision:
1:dd8228f2263c
Parent:
0:1e026f2c8707
Major bug fixes and reliability updates. Fixed erroneous gps serial code. Added neglected mutex code where necessary.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ottaviano3 1:dd8228f2263c 1 /*
ottaviano3 1:dd8228f2263c 2 / Sentinel software for the base station node.
ottaviano3 1:dd8228f2263c 3 /
ottaviano3 1:dd8228f2263c 4 / Design work done by:
ottaviano3 1:dd8228f2263c 5 / Dominic Ottaviano
ottaviano3 1:dd8228f2263c 6 / Sheldon Fernandes
ottaviano3 1:dd8228f2263c 7 / Thien L. Nguyen
ottaviano3 1:dd8228f2263c 8 */
ottaviano3 1:dd8228f2263c 9
ottaviano3 0:1e026f2c8707 10 #include "mbed.h"
ottaviano3 0:1e026f2c8707 11 #include "xbee900hp.h"
ottaviano3 0:1e026f2c8707 12 #include "rtos.h"
ottaviano3 0:1e026f2c8707 13
ottaviano3 1:dd8228f2263c 14 /*===========================================================/
ottaviano3 1:dd8228f2263c 15 / Primary Configuration Area /
ottaviano3 1:dd8228f2263c 16 / Global Variables and Pin Assigments Declared Within /
ottaviano3 1:dd8228f2263c 17 /===========================================================*/
ottaviano3 1:dd8228f2263c 18
ottaviano3 1:dd8228f2263c 19 // Serial Port Mutex to prevent multiple transmissions
ottaviano3 1:dd8228f2263c 20 Mutex serial_mutex;
ottaviano3 1:dd8228f2263c 21
ottaviano3 1:dd8228f2263c 22 // Declare serial output to the host PC over USB
ottaviano3 0:1e026f2c8707 23 Serial pc(USBTX,USBRX);
ottaviano3 0:1e026f2c8707 24
ottaviano3 1:dd8228f2263c 25 // Connected serial GPS pins
ottaviano3 0:1e026f2c8707 26 Serial gps(p28,p27);
ottaviano3 0:1e026f2c8707 27
ottaviano3 1:dd8228f2263c 28 // Declare pins of connected xbee module using spi (EXPERIMENTAL DRIVER)
ottaviano3 0:1e026f2c8707 29 xbee900hp xbee(p11,p12,p13, p8, p9);
ottaviano3 0:1e026f2c8707 30
ottaviano3 1:dd8228f2263c 31 // Led outputs on the MBED
ottaviano3 0:1e026f2c8707 32 DigitalOut led1(LED1);
ottaviano3 0:1e026f2c8707 33 DigitalOut led2(LED2);
ottaviano3 0:1e026f2c8707 34
ottaviano3 1:dd8228f2263c 35 // Global Variables
ottaviano3 0:1e026f2c8707 36 // Buffer for reading in from xbee
ottaviano3 0:1e026f2c8707 37 char buffer[256];
ottaviano3 1:dd8228f2263c 38 // Buffer for storing GPS data
ottaviano3 0:1e026f2c8707 39 char gpsmsg[256];
ottaviano3 0:1e026f2c8707 40
ottaviano3 1:dd8228f2263c 41 // Predefine threads running here
ottaviano3 1:dd8228f2263c 42 // Thread to handle data inputs and outputs to the XBee
ottaviano3 1:dd8228f2263c 43 void xbeeScanner(void const *args);
ottaviano3 1:dd8228f2263c 44 // Thread to handle data inputs from the GPS module
ottaviano3 1:dd8228f2263c 45 void hostScanner(void const *args);
ottaviano3 1:dd8228f2263c 46
ottaviano3 1:dd8228f2263c 47 // Function prototypes
ottaviano3 1:dd8228f2263c 48 // Function to query the GPS
ottaviano3 1:dd8228f2263c 49 int getGPS(char* data);
ottaviano3 1:dd8228f2263c 50
ottaviano3 1:dd8228f2263c 51 /*===========================================================/
ottaviano3 1:dd8228f2263c 52 / END OF Primary Configuration Area /
ottaviano3 1:dd8228f2263c 53 /===========================================================*/
ottaviano3 1:dd8228f2263c 54
ottaviano3 1:dd8228f2263c 55 /*===========================================================/
ottaviano3 1:dd8228f2263c 56 / Code to setup the watchdog timer on the MBED to handle- /
ottaviano3 1:dd8228f2263c 57 / auto resets /
ottaviano3 1:dd8228f2263c 58 /===========================================================*/
ottaviano3 1:dd8228f2263c 59
ottaviano3 1:dd8228f2263c 60 class Watchdog
ottaviano3 1:dd8228f2263c 61 {
ottaviano3 1:dd8228f2263c 62 public:
ottaviano3 1:dd8228f2263c 63 // Load timeout value in watchdog timer and enable
ottaviano3 1:dd8228f2263c 64 void kick(float s) {
ottaviano3 1:dd8228f2263c 65 LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK
ottaviano3 1:dd8228f2263c 66 uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4
ottaviano3 1:dd8228f2263c 67 LPC_WDT->WDTC = s * (float)clk;
ottaviano3 1:dd8228f2263c 68 LPC_WDT->WDMOD = 0x3; // Enabled and Reset
ottaviano3 1:dd8228f2263c 69 kick();
ottaviano3 1:dd8228f2263c 70 }
ottaviano3 1:dd8228f2263c 71 // "kick" or "feed" the dog - reset the watchdog timer
ottaviano3 1:dd8228f2263c 72 // by writing this required bit pattern
ottaviano3 1:dd8228f2263c 73 void kick() {
ottaviano3 1:dd8228f2263c 74 LPC_WDT->WDFEED = 0xAA;
ottaviano3 1:dd8228f2263c 75 LPC_WDT->WDFEED = 0x55;
ottaviano3 1:dd8228f2263c 76 }
ottaviano3 1:dd8228f2263c 77 };
ottaviano3 1:dd8228f2263c 78
ottaviano3 1:dd8228f2263c 79 // Declare watchdog timer
ottaviano3 1:dd8228f2263c 80 Watchdog wdt;
ottaviano3 1:dd8228f2263c 81
ottaviano3 1:dd8228f2263c 82 /*===========================================================/
ottaviano3 1:dd8228f2263c 83 / End of watchdog timer code /
ottaviano3 1:dd8228f2263c 84 /===========================================================*/
ottaviano3 1:dd8228f2263c 85
ottaviano3 1:dd8228f2263c 86 /*===========================================================/
ottaviano3 1:dd8228f2263c 87 / Begin main program code /
ottaviano3 1:dd8228f2263c 88 /===========================================================*/
ottaviano3 0:1e026f2c8707 89
ottaviano3 0:1e026f2c8707 90 int main()
ottaviano3 0:1e026f2c8707 91 {
ottaviano3 1:dd8228f2263c 92 /*===========================/
ottaviano3 1:dd8228f2263c 93 / Configuration Section /
ottaviano3 1:dd8228f2263c 94 /===========================*/
ottaviano3 0:1e026f2c8707 95
ottaviano3 1:dd8228f2263c 96 // Set PC parameters
ottaviano3 1:dd8228f2263c 97 // Baud rate
ottaviano3 0:1e026f2c8707 98 pc.baud(57600);
ottaviano3 1:dd8228f2263c 99 // Other params (8 data bits, no parity, 1 stop bit)
ottaviano3 1:dd8228f2263c 100 pc.format(8,SerialBase::None,1);
ottaviano3 1:dd8228f2263c 101
ottaviano3 1:dd8228f2263c 102 // Set GPS paramters
ottaviano3 1:dd8228f2263c 103 // Baud rate
ottaviano3 0:1e026f2c8707 104 gps.baud(4800);
ottaviano3 1:dd8228f2263c 105 // Other params (8 data bits, no parity, 1 stop bit)
ottaviano3 1:dd8228f2263c 106 gps.format(8,SerialBase::None,1);
ottaviano3 1:dd8228f2263c 107
ottaviano3 1:dd8228f2263c 108 // Configure gps with these parameters:
ottaviano3 1:dd8228f2263c 109 // NMEA, 4800 Baud, 8 Data bits, 1 Stop bit, No Parity
ottaviano3 0:1e026f2c8707 110 unsigned int gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'0'^','^'1'^','^'4'^'8'^'0'^'0'^','^'8'^','^'1'^','^'0';
ottaviano3 1:dd8228f2263c 111 // Trim to 8 bits just in case
ottaviano3 1:dd8228f2263c 112 gpsxor = gpsxor & 0xFF;
ottaviano3 1:dd8228f2263c 113 // Send command to the GPS module
ottaviano3 1:dd8228f2263c 114 gps.printf("$PSRF100,1,4800,8,1,0*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);
ottaviano3 0:1e026f2c8707 115
ottaviano3 1:dd8228f2263c 116 // Disable automatic broadcast of all messages. We are going to poll manually.
ottaviano3 1:dd8228f2263c 117 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'0'^','^'0'^','^'0'^','^'1';
ottaviano3 1:dd8228f2263c 118 // Trim to 8 bits just in case
ottaviano3 1:dd8228f2263c 119 gpsxor = gpsxor & 0xFF;
ottaviano3 1:dd8228f2263c 120 gps.printf("$PSRF103,0,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);
ottaviano3 0:1e026f2c8707 121
ottaviano3 0:1e026f2c8707 122 // Disable GLL
ottaviano3 0:1e026f2c8707 123 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'1'^','^'0'^','^'0'^','^'1';
ottaviano3 1:dd8228f2263c 124 // Trim to 8 bits just in case
ottaviano3 1:dd8228f2263c 125 gpsxor = gpsxor & 0xFF;
ottaviano3 1:dd8228f2263c 126 gps.printf("$PSRF103,1,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);
ottaviano3 0:1e026f2c8707 127
ottaviano3 0:1e026f2c8707 128 // Disable GSA
ottaviano3 0:1e026f2c8707 129 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'2'^','^'0'^','^'0'^','^'1';
ottaviano3 1:dd8228f2263c 130 // Trim to 8 bits just in case
ottaviano3 1:dd8228f2263c 131 gpsxor = gpsxor & 0xFF;
ottaviano3 1:dd8228f2263c 132 gps.printf("$PSRF103,2,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);
ottaviano3 0:1e026f2c8707 133
ottaviano3 0:1e026f2c8707 134 // Disable GSV
ottaviano3 0:1e026f2c8707 135 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'3'^','^'0'^','^'0'^','^'1';
ottaviano3 1:dd8228f2263c 136 // Trim to 8 bits just in case
ottaviano3 1:dd8228f2263c 137 gpsxor = gpsxor & 0xFF;
ottaviano3 1:dd8228f2263c 138 gps.printf("$PSRF103,3,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);
ottaviano3 0:1e026f2c8707 139
ottaviano3 0:1e026f2c8707 140 // Disable RMC
ottaviano3 0:1e026f2c8707 141 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'4'^','^'0'^','^'0'^','^'1';
ottaviano3 1:dd8228f2263c 142 // Trim to 8 bits just in case
ottaviano3 1:dd8228f2263c 143 gpsxor = gpsxor & 0xFF;
ottaviano3 1:dd8228f2263c 144 gps.printf("$PSRF103,4,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);
ottaviano3 0:1e026f2c8707 145
ottaviano3 0:1e026f2c8707 146 // Disable VTG
ottaviano3 0:1e026f2c8707 147 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'5'^','^'0'^','^'0'^','^'1';
ottaviano3 1:dd8228f2263c 148 // Trim to 8 bits just in case
ottaviano3 1:dd8228f2263c 149 gpsxor = gpsxor & 0xFF;
ottaviano3 1:dd8228f2263c 150 gps.printf("$PSRF103,5,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);
ottaviano3 0:1e026f2c8707 151
ottaviano3 1:dd8228f2263c 152 // Enable watchdog with a reasonable half second timeout
ottaviano3 1:dd8228f2263c 153 wdt.kick(1000);
ottaviano3 1:dd8228f2263c 154
ottaviano3 1:dd8228f2263c 155 /*===========================/
ottaviano3 1:dd8228f2263c 156 / END Configuration Section /
ottaviano3 1:dd8228f2263c 157 /===========================*/
ottaviano3 1:dd8228f2263c 158
ottaviano3 1:dd8228f2263c 159
ottaviano3 0:1e026f2c8707 160 while (true) {
ottaviano3 0:1e026f2c8707 161 // Define Keys
ottaviano3 0:1e026f2c8707 162 char startkey[12] = "SentinelOn";
ottaviano3 0:1e026f2c8707 163 char endkey[13] = "SentinelOff";
ottaviano3 1:dd8228f2263c 164 char cmdbuff[30];
ottaviano3 0:1e026f2c8707 165
ottaviano3 1:dd8228f2263c 166 // LED 1 on shows ready status.
ottaviano3 1:dd8228f2263c 167 led1 = 1;
ottaviano3 1:dd8228f2263c 168 // Start loop waiting for start message
ottaviano3 0:1e026f2c8707 169 do {
ottaviano3 0:1e026f2c8707 170 if (pc.readable() == true) {
ottaviano3 0:1e026f2c8707 171 // Get bytes from computer
ottaviano3 1:dd8228f2263c 172 pc.scanf("%s",cmdbuff);
ottaviano3 0:1e026f2c8707 173 }
ottaviano3 1:dd8228f2263c 174 wdt.kick();
ottaviano3 1:dd8228f2263c 175 } while (strcmp( startkey, cmdbuff ) != 0);
ottaviano3 1:dd8228f2263c 176 // Clear string in buffer
ottaviano3 1:dd8228f2263c 177 cmdbuff[0] = '\0';
ottaviano3 1:dd8228f2263c 178 // LED 1 off as we enter next segment
ottaviano3 0:1e026f2c8707 179 led1 = 0;
ottaviano3 0:1e026f2c8707 180
ottaviano3 1:dd8228f2263c 181 // Let host know that we are starting.
ottaviano3 0:1e026f2c8707 182 pc.printf("SLON\r\n");
ottaviano3 0:1e026f2c8707 183
ottaviano3 0:1e026f2c8707 184 xbee.clearBuff();
ottaviano3 0:1e026f2c8707 185
ottaviano3 0:1e026f2c8707 186 // Start xbeeScanner Thread
ottaviano3 0:1e026f2c8707 187 Thread xbscan(xbeeScanner);
ottaviano3 0:1e026f2c8707 188 Thread hostscan(hostScanner);
ottaviano3 0:1e026f2c8707 189
ottaviano3 0:1e026f2c8707 190 // Main runloop
ottaviano3 1:dd8228f2263c 191 led2 = 1;
ottaviano3 0:1e026f2c8707 192 do {
ottaviano3 1:dd8228f2263c 193 serial_mutex.lock();
ottaviano3 0:1e026f2c8707 194 if (pc.readable() == true) {
ottaviano3 0:1e026f2c8707 195 // Get bytes from computer
ottaviano3 1:dd8228f2263c 196 pc.scanf("%s",cmdbuff);
ottaviano3 0:1e026f2c8707 197 }
ottaviano3 1:dd8228f2263c 198 serial_mutex.unlock();
ottaviano3 1:dd8228f2263c 199 wdt.kick();
ottaviano3 1:dd8228f2263c 200 } while (strcmp( endkey, cmdbuff ) != 0);
ottaviano3 1:dd8228f2263c 201 led2 = 0;
ottaviano3 0:1e026f2c8707 202
ottaviano3 1:dd8228f2263c 203 // Clear string in buffer
ottaviano3 1:dd8228f2263c 204 cmdbuff[0] = '\0';
ottaviano3 0:1e026f2c8707 205
ottaviano3 0:1e026f2c8707 206 xbscan.terminate();
ottaviano3 0:1e026f2c8707 207 hostscan.terminate();
ottaviano3 0:1e026f2c8707 208 }
ottaviano3 0:1e026f2c8707 209 }
ottaviano3 0:1e026f2c8707 210
ottaviano3 0:1e026f2c8707 211 // Thread to update host position
ottaviano3 0:1e026f2c8707 212 void hostScanner(void const *args)
ottaviano3 0:1e026f2c8707 213 {
ottaviano3 1:dd8228f2263c 214 // Set variables, there are more than we need here but it would be useful in the future if we did need any.
ottaviano3 1:dd8228f2263c 215 char nodeid[5] = "BASE";
ottaviano3 0:1e026f2c8707 216 char ns, ew;
ottaviano3 0:1e026f2c8707 217 int lock;
ottaviano3 1:dd8228f2263c 218 double satsused;
ottaviano3 1:dd8228f2263c 219 double hdop;
ottaviano3 1:dd8228f2263c 220 double latitude, longitude;
ottaviano3 1:dd8228f2263c 221 double altitude;
ottaviano3 1:dd8228f2263c 222 double time;
ottaviano3 1:dd8228f2263c 223 char altunits;
ottaviano3 1:dd8228f2263c 224 double geoidsep;
ottaviano3 1:dd8228f2263c 225 char geoidunits;
ottaviano3 1:dd8228f2263c 226 int difrefstationid;
ottaviano3 1:dd8228f2263c 227 unsigned int gpschecksum;
ottaviano3 0:1e026f2c8707 228
ottaviano3 1:dd8228f2263c 229 serial_mutex.lock();
ottaviano3 1:dd8228f2263c 230 // Announce base node to computer application
ottaviano3 1:dd8228f2263c 231 pc.printf("ANCE,%s,\r\n",nodeid);
ottaviano3 1:dd8228f2263c 232 serial_mutex.unlock();
ottaviano3 1:dd8228f2263c 233
ottaviano3 1:dd8228f2263c 234 // Main run loop
ottaviano3 1:dd8228f2263c 235 while (true) {
ottaviano3 1:dd8228f2263c 236 // Get new data from the GPS and if data is read successfully continue
ottaviano3 1:dd8228f2263c 237 if (!(getGPS(gpsmsg))) {
ottaviano3 1:dd8228f2263c 238 // Parse the recieved data and check if its valid (HINT: lf = double since pointers aren't promoted)
ottaviano3 1:dd8228f2263c 239 if(sscanf(gpsmsg, "$GPGGA,%lf,%lf,%c,%lf,%c,%i,%lf,%lf,%lf,%c,%lf,%c,,%i*%x", &time, &latitude, &ns, &longitude, &ew, &lock, &satsused, &hdop, &altitude, &altunits, &geoidsep, &geoidunits, &difrefstationid, &gpschecksum) == 14) {
ottaviano3 1:dd8228f2263c 240 // Check if the lock is valid
ottaviano3 1:dd8228f2263c 241 if((lock != 1) && (lock != 2) && (lock != 6)) {
ottaviano3 1:dd8228f2263c 242 // Lock is not valid, let host know.
ottaviano3 1:dd8228f2263c 243 serial_mutex.lock();
ottaviano3 1:dd8228f2263c 244 pc.printf("DNLK,%s,NOLOCK\r\n",nodeid);
ottaviano3 1:dd8228f2263c 245 serial_mutex.unlock();
ottaviano3 1:dd8228f2263c 246 } else {
ottaviano3 1:dd8228f2263c 247 // Convert latitude into proper form for display on a map.
ottaviano3 1:dd8228f2263c 248 double degrees;
ottaviano3 1:dd8228f2263c 249 double minutes = modf(latitude/100.0f, &degrees);
ottaviano3 1:dd8228f2263c 250 minutes = (minutes*100.0f)/60.0f;
ottaviano3 1:dd8228f2263c 251 latitude = degrees + minutes;
ottaviano3 1:dd8228f2263c 252 // Convert longitude
ottaviano3 1:dd8228f2263c 253 minutes = modf(longitude/100.0f, &degrees);
ottaviano3 1:dd8228f2263c 254 minutes = (minutes*100.0f)/60.0f;
ottaviano3 1:dd8228f2263c 255 longitude = degrees + minutes;
ottaviano3 1:dd8228f2263c 256
ottaviano3 1:dd8228f2263c 257 // Correct for south and west.
ottaviano3 1:dd8228f2263c 258 if(ns == 'S') {
ottaviano3 1:dd8228f2263c 259 latitude *= -1.0;
ottaviano3 1:dd8228f2263c 260 }
ottaviano3 1:dd8228f2263c 261 if(ew == 'W') {
ottaviano3 1:dd8228f2263c 262 longitude *= -1.0;
ottaviano3 1:dd8228f2263c 263 }
ottaviano3 1:dd8228f2263c 264
ottaviano3 1:dd8228f2263c 265 serial_mutex.lock();
ottaviano3 1:dd8228f2263c 266 // Send formatted info to the host
ottaviano3 1:dd8228f2263c 267 pc.printf("DLIN,%s,%f,%f,%f,%f,\r\n",nodeid, latitude, longitude, altitude, satsused);
ottaviano3 1:dd8228f2263c 268 serial_mutex.unlock();
ottaviano3 1:dd8228f2263c 269 }
ottaviano3 1:dd8228f2263c 270 // Wait a second for GPS data to be fresh again and not waste cycles.
ottaviano3 1:dd8228f2263c 271 Thread::wait(1000);
ottaviano3 0:1e026f2c8707 272 } else {
ottaviano3 1:dd8228f2263c 273 // GPS hasn't found a good enough lock
ottaviano3 1:dd8228f2263c 274 serial_mutex.lock();
ottaviano3 1:dd8228f2263c 275 pc.printf("DNLK,%s,NOLOCK\r\n",nodeid);
ottaviano3 1:dd8228f2263c 276 serial_mutex.unlock();
ottaviano3 1:dd8228f2263c 277 // If this check fails we give up cpu time to another thread but only momentarily, we need to get this data successfully.
ottaviano3 1:dd8228f2263c 278 Thread::wait(500);
ottaviano3 0:1e026f2c8707 279 }
ottaviano3 1:dd8228f2263c 280 } else {
ottaviano3 1:dd8228f2263c 281 // GPS hasn't found lock or sent a corrupted message
ottaviano3 1:dd8228f2263c 282 serial_mutex.lock();
ottaviano3 1:dd8228f2263c 283 pc.printf("DNLK,%s,NOLOCK\r\n",nodeid);
ottaviano3 1:dd8228f2263c 284 serial_mutex.unlock();
ottaviano3 1:dd8228f2263c 285 // If this check fails we give up cpu time to another thread but only momentarily, we need to get this data successfully.
ottaviano3 1:dd8228f2263c 286 Thread::wait(500);
ottaviano3 0:1e026f2c8707 287 }
ottaviano3 0:1e026f2c8707 288 }
ottaviano3 0:1e026f2c8707 289 }
ottaviano3 0:1e026f2c8707 290
ottaviano3 0:1e026f2c8707 291 // Thread to scan the xbee
ottaviano3 0:1e026f2c8707 292 void xbeeScanner(void const *args)
ottaviano3 0:1e026f2c8707 293 {
ottaviano3 0:1e026f2c8707 294 // Main runloop
ottaviano3 0:1e026f2c8707 295 while (true) {
ottaviano3 0:1e026f2c8707 296 // check if xbee is flagging data to be read
ottaviano3 0:1e026f2c8707 297 while(xbee.attn() == 0) {
ottaviano3 0:1e026f2c8707 298 // Read in data and run all background checksum and validation stuff
ottaviano3 0:1e026f2c8707 299 if (xbee.readPacket(buffer) == 0) {
ottaviano3 1:dd8228f2263c 300 serial_mutex.lock();
ottaviano3 1:dd8228f2263c 301 pc.printf("%s\r\n", buffer);
ottaviano3 1:dd8228f2263c 302 serial_mutex.unlock();
ottaviano3 0:1e026f2c8707 303 } else {
ottaviano3 1:dd8228f2263c 304 serial_mutex.lock();
ottaviano3 1:dd8228f2263c 305 pc.printf("Packet Failed Validation\r\n");
ottaviano3 1:dd8228f2263c 306 serial_mutex.unlock();
ottaviano3 0:1e026f2c8707 307 xbee.clearBuff();
ottaviano3 0:1e026f2c8707 308 }
ottaviano3 0:1e026f2c8707 309 }
ottaviano3 0:1e026f2c8707 310 // Give up rest of timeslice to boost that performance
ottaviano3 0:1e026f2c8707 311 Thread::yield();
ottaviano3 0:1e026f2c8707 312 }
ottaviano3 0:1e026f2c8707 313 }
ottaviano3 0:1e026f2c8707 314
ottaviano3 1:dd8228f2263c 315 // Function to get the gps message and make sure its valid.
ottaviano3 1:dd8228f2263c 316 int getGPS(char* data)
ottaviano3 0:1e026f2c8707 317 {
ottaviano3 1:dd8228f2263c 318 // Request a query of GGA
ottaviano3 1:dd8228f2263c 319 // Precomputed checksum to save cpu cycles
ottaviano3 1:dd8228f2263c 320 serial_mutex.lock();
ottaviano3 1:dd8228f2263c 321 gps.printf("$PSRF103,0,1,0,1*%u%u\r\n",0x2,0x5);
ottaviano3 1:dd8228f2263c 322 serial_mutex.unlock();
ottaviano3 1:dd8228f2263c 323
ottaviano3 1:dd8228f2263c 324 // Timer to prevent hangs if gps doesn't respond.
ottaviano3 1:dd8228f2263c 325 Timer gpsTO;
ottaviano3 1:dd8228f2263c 326 gpsTO.start();
ottaviano3 1:dd8228f2263c 327
ottaviano3 1:dd8228f2263c 328 // Wait for gps to becom readable.
ottaviano3 1:dd8228f2263c 329 while (gps.readable() == false) {
ottaviano3 1:dd8228f2263c 330 // Timeout
ottaviano3 1:dd8228f2263c 331 if (gpsTO.read() > 2) {
ottaviano3 1:dd8228f2263c 332 return 1;
ottaviano3 0:1e026f2c8707 333 }
ottaviano3 0:1e026f2c8707 334 }
ottaviano3 1:dd8228f2263c 335
ottaviano3 1:dd8228f2263c 336 // Wait a tiny bit to allow the gps to send the whole line.
ottaviano3 1:dd8228f2263c 337 Thread::wait(50);
ottaviano3 1:dd8228f2263c 338 // Get data from gps
ottaviano3 1:dd8228f2263c 339 serial_mutex.lock();
ottaviano3 1:dd8228f2263c 340 gps.scanf("%s",data);
ottaviano3 1:dd8228f2263c 341 serial_mutex.unlock();
ottaviano3 1:dd8228f2263c 342
ottaviano3 1:dd8228f2263c 343 // Compute checksum of recieved gps data
ottaviano3 1:dd8228f2263c 344 int i = 0;
ottaviano3 1:dd8228f2263c 345 unsigned int calcgpschecksum = 0;
ottaviano3 1:dd8228f2263c 346 // Checksum is calculated between and not including the $ and *
ottaviano3 1:dd8228f2263c 347 while ((data[i] != '\0') && (data[i] != '*')) {
ottaviano3 1:dd8228f2263c 348 // Skip the $
ottaviano3 1:dd8228f2263c 349 if (data[i] != '$') {
ottaviano3 1:dd8228f2263c 350 calcgpschecksum = calcgpschecksum ^ data[i];
ottaviano3 1:dd8228f2263c 351 }
ottaviano3 1:dd8228f2263c 352 i++;
ottaviano3 1:dd8228f2263c 353 }
ottaviano3 1:dd8228f2263c 354 // Shift the checksum to match the format we recieve from the gps
ottaviano3 1:dd8228f2263c 355 calcgpschecksum = calcgpschecksum & 0xFF;
ottaviano3 1:dd8228f2263c 356
ottaviano3 1:dd8228f2263c 357 // Get checksum sent by gps out of string
ottaviano3 1:dd8228f2263c 358 unsigned int realgpschecksum = 0;
ottaviano3 1:dd8228f2263c 359 char checksumarray[3];
ottaviano3 1:dd8228f2263c 360 for (int i = 0; i < 256; i++) {
ottaviano3 1:dd8228f2263c 361 if (data[i] == '*') {
ottaviano3 1:dd8228f2263c 362 // Create little array with ascii hex values.
ottaviano3 1:dd8228f2263c 363 checksumarray[0] = data[i+1];
ottaviano3 1:dd8228f2263c 364 checksumarray[1] = data[i+2];
ottaviano3 1:dd8228f2263c 365 checksumarray[2] = '\0';
ottaviano3 1:dd8228f2263c 366 // Convert ascii values to regular integer
ottaviano3 1:dd8228f2263c 367 sscanf(checksumarray,"%x",&realgpschecksum);
ottaviano3 1:dd8228f2263c 368 break;
ottaviano3 1:dd8228f2263c 369 }
ottaviano3 1:dd8228f2263c 370 }
ottaviano3 1:dd8228f2263c 371
ottaviano3 1:dd8228f2263c 372 // Check for checksum match
ottaviano3 1:dd8228f2263c 373 if( calcgpschecksum == realgpschecksum ) {
ottaviano3 1:dd8228f2263c 374 return 0;
ottaviano3 1:dd8228f2263c 375 }
ottaviano3 1:dd8228f2263c 376
ottaviano3 1:dd8228f2263c 377 // No checksum match
ottaviano3 1:dd8228f2263c 378 return 1;
ottaviano3 0:1e026f2c8707 379 }