The software that runs on the Sentinel base station. This code is for the LPC1768.
Dependencies: XBEE_900HP_SPI mbed-rtos mbed
main.cpp@1:dd8228f2263c, 2015-08-18 (annotated)
- 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?
User | Revision | Line number | New 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, °rees); |
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, °rees); |
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 | } |