EmbeddedArtists AB
/
lpc812_exp_solution_exp-port-gps
Solutions for the GPS experiments for LPC812 MAX
main.cpp@0:a1d4ae5fb9fa, 2013-11-24 (annotated)
- Committer:
- embeddedartists
- Date:
- Sun Nov 24 12:43:53 2013 +0000
- Revision:
- 0:a1d4ae5fb9fa
First version
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
embeddedartists | 0:a1d4ae5fb9fa | 1 | #include "mbed.h" |
embeddedartists | 0:a1d4ae5fb9fa | 2 | |
embeddedartists | 0:a1d4ae5fb9fa | 3 | Serial pc(USBTX, USBRX); // tx, rx |
embeddedartists | 0:a1d4ae5fb9fa | 4 | Serial uart(P0_4, P0_0); |
embeddedartists | 0:a1d4ae5fb9fa | 5 | |
embeddedartists | 0:a1d4ae5fb9fa | 6 | /** |
embeddedartists | 0:a1d4ae5fb9fa | 7 | * Data structure for the GPS values |
embeddedartists | 0:a1d4ae5fb9fa | 8 | */ |
embeddedartists | 0:a1d4ae5fb9fa | 9 | typedef struct gpsData { |
embeddedartists | 0:a1d4ae5fb9fa | 10 | uint8_t satellitesUsed[20]; |
embeddedartists | 0:a1d4ae5fb9fa | 11 | uint8_t utcTime[20]; |
embeddedartists | 0:a1d4ae5fb9fa | 12 | uint8_t altitude[20]; |
embeddedartists | 0:a1d4ae5fb9fa | 13 | uint8_t bufLatitude[20]; |
embeddedartists | 0:a1d4ae5fb9fa | 14 | uint8_t bufLongitude[20]; |
embeddedartists | 0:a1d4ae5fb9fa | 15 | int positionFixed; |
embeddedartists | 0:a1d4ae5fb9fa | 16 | int northSouthIndicator; |
embeddedartists | 0:a1d4ae5fb9fa | 17 | int eastWestIndicator; |
embeddedartists | 0:a1d4ae5fb9fa | 18 | int latitude; |
embeddedartists | 0:a1d4ae5fb9fa | 19 | int longitude; |
embeddedartists | 0:a1d4ae5fb9fa | 20 | } gpsData; |
embeddedartists | 0:a1d4ae5fb9fa | 21 | |
embeddedartists | 0:a1d4ae5fb9fa | 22 | static uint8_t END_OF_MESSAGE = '\0'; |
embeddedartists | 0:a1d4ae5fb9fa | 23 | static uint8_t DIVIDER = ','; |
embeddedartists | 0:a1d4ae5fb9fa | 24 | |
embeddedartists | 0:a1d4ae5fb9fa | 25 | // The parsed data |
embeddedartists | 0:a1d4ae5fb9fa | 26 | static gpsData data; |
embeddedartists | 0:a1d4ae5fb9fa | 27 | |
embeddedartists | 0:a1d4ae5fb9fa | 28 | /***************************************************************************** |
embeddedartists | 0:a1d4ae5fb9fa | 29 | ** Function name: hasPattern |
embeddedartists | 0:a1d4ae5fb9fa | 30 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 31 | ** Descriptions: Tests if pBuf starts with pPattern. |
embeddedartists | 0:a1d4ae5fb9fa | 32 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 33 | ** parameters: Buffer to search and pattern to match |
embeddedartists | 0:a1d4ae5fb9fa | 34 | ** Returned value: 1 if pBuf starts with pPattern, 0 otherwise |
embeddedartists | 0:a1d4ae5fb9fa | 35 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 36 | *****************************************************************************/ |
embeddedartists | 0:a1d4ae5fb9fa | 37 | static uint8_t hasPattern(uint8_t *pBuf, uint8_t *pPattern) |
embeddedartists | 0:a1d4ae5fb9fa | 38 | { |
embeddedartists | 0:a1d4ae5fb9fa | 39 | while(*pBuf != END_OF_MESSAGE && *pPattern != END_OF_MESSAGE) { |
embeddedartists | 0:a1d4ae5fb9fa | 40 | if(*pBuf != *pPattern) { |
embeddedartists | 0:a1d4ae5fb9fa | 41 | return 0; |
embeddedartists | 0:a1d4ae5fb9fa | 42 | } |
embeddedartists | 0:a1d4ae5fb9fa | 43 | pPattern++; |
embeddedartists | 0:a1d4ae5fb9fa | 44 | pBuf++; |
embeddedartists | 0:a1d4ae5fb9fa | 45 | } |
embeddedartists | 0:a1d4ae5fb9fa | 46 | return 1; |
embeddedartists | 0:a1d4ae5fb9fa | 47 | } |
embeddedartists | 0:a1d4ae5fb9fa | 48 | /***************************************************************************** |
embeddedartists | 0:a1d4ae5fb9fa | 49 | ** Function name: pointToNextValue |
embeddedartists | 0:a1d4ae5fb9fa | 50 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 51 | ** Descriptions: Moves past the next divider |
embeddedartists | 0:a1d4ae5fb9fa | 52 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 53 | ** parameters: Pointer to the string to search |
embeddedartists | 0:a1d4ae5fb9fa | 54 | ** Returned value: None |
embeddedartists | 0:a1d4ae5fb9fa | 55 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 56 | *****************************************************************************/ |
embeddedartists | 0:a1d4ae5fb9fa | 57 | static void pointToNextValue(uint8_t **ppBuf) |
embeddedartists | 0:a1d4ae5fb9fa | 58 | { |
embeddedartists | 0:a1d4ae5fb9fa | 59 | while(**ppBuf != END_OF_MESSAGE) { |
embeddedartists | 0:a1d4ae5fb9fa | 60 | if (**ppBuf == DIVIDER) { |
embeddedartists | 0:a1d4ae5fb9fa | 61 | (*ppBuf)++; // point to the start of next value |
embeddedartists | 0:a1d4ae5fb9fa | 62 | break; |
embeddedartists | 0:a1d4ae5fb9fa | 63 | } |
embeddedartists | 0:a1d4ae5fb9fa | 64 | (*ppBuf)++; |
embeddedartists | 0:a1d4ae5fb9fa | 65 | } |
embeddedartists | 0:a1d4ae5fb9fa | 66 | } |
embeddedartists | 0:a1d4ae5fb9fa | 67 | /***************************************************************************** |
embeddedartists | 0:a1d4ae5fb9fa | 68 | ** Function name: convertCordinateToDegree |
embeddedartists | 0:a1d4ae5fb9fa | 69 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 70 | ** Descriptions: Converts the pBuf string which is in the |
embeddedartists | 0:a1d4ae5fb9fa | 71 | ** "ddmm.mmmm" format into an integer representation |
embeddedartists | 0:a1d4ae5fb9fa | 72 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 73 | ** parameters: The buffer, the resulting integer and the |
embeddedartists | 0:a1d4ae5fb9fa | 74 | ** length of the buffer |
embeddedartists | 0:a1d4ae5fb9fa | 75 | ** Returned value: None |
embeddedartists | 0:a1d4ae5fb9fa | 76 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 77 | *****************************************************************************/ |
embeddedartists | 0:a1d4ae5fb9fa | 78 | static void convertCordinateToDegree(uint8_t *pBuf, int* pDegree, int len) |
embeddedartists | 0:a1d4ae5fb9fa | 79 | { |
embeddedartists | 0:a1d4ae5fb9fa | 80 | int index = 0; |
embeddedartists | 0:a1d4ae5fb9fa | 81 | int sum = 0; |
embeddedartists | 0:a1d4ae5fb9fa | 82 | int deg = 0; |
embeddedartists | 0:a1d4ae5fb9fa | 83 | int min = 0; |
embeddedartists | 0:a1d4ae5fb9fa | 84 | int div = 0; |
embeddedartists | 0:a1d4ae5fb9fa | 85 | int pow = 1; |
embeddedartists | 0:a1d4ae5fb9fa | 86 | for (index = len; index >=0; index--) { |
embeddedartists | 0:a1d4ae5fb9fa | 87 | if (pBuf[index] == '.') { |
embeddedartists | 0:a1d4ae5fb9fa | 88 | div = 1; |
embeddedartists | 0:a1d4ae5fb9fa | 89 | continue; |
embeddedartists | 0:a1d4ae5fb9fa | 90 | } |
embeddedartists | 0:a1d4ae5fb9fa | 91 | sum += pow * (pBuf[index] & 0x0F); |
embeddedartists | 0:a1d4ae5fb9fa | 92 | if (index > 0) { |
embeddedartists | 0:a1d4ae5fb9fa | 93 | pow *= 10; |
embeddedartists | 0:a1d4ae5fb9fa | 94 | div *= 10; |
embeddedartists | 0:a1d4ae5fb9fa | 95 | } |
embeddedartists | 0:a1d4ae5fb9fa | 96 | } |
embeddedartists | 0:a1d4ae5fb9fa | 97 | |
embeddedartists | 0:a1d4ae5fb9fa | 98 | div = pow / div; |
embeddedartists | 0:a1d4ae5fb9fa | 99 | deg = sum / (div*100); |
embeddedartists | 0:a1d4ae5fb9fa | 100 | min = sum - (deg*div*100); |
embeddedartists | 0:a1d4ae5fb9fa | 101 | |
embeddedartists | 0:a1d4ae5fb9fa | 102 | // convert to decimal minutes |
embeddedartists | 0:a1d4ae5fb9fa | 103 | min = (min * 100) / 60; |
embeddedartists | 0:a1d4ae5fb9fa | 104 | *pDegree = (deg*div*100) + min; |
embeddedartists | 0:a1d4ae5fb9fa | 105 | if (div > 10000) { |
embeddedartists | 0:a1d4ae5fb9fa | 106 | // normalize minutes to 6 decimal places |
embeddedartists | 0:a1d4ae5fb9fa | 107 | *pDegree /= (div / 10000); |
embeddedartists | 0:a1d4ae5fb9fa | 108 | } |
embeddedartists | 0:a1d4ae5fb9fa | 109 | } |
embeddedartists | 0:a1d4ae5fb9fa | 110 | /***************************************************************************** |
embeddedartists | 0:a1d4ae5fb9fa | 111 | ** Function name: parseUTC |
embeddedartists | 0:a1d4ae5fb9fa | 112 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 113 | ** Descriptions: Extracts the UTC time string in hhmmss.sss, |
embeddedartists | 0:a1d4ae5fb9fa | 114 | ** ignoring the .sss part and stores the result |
embeddedartists | 0:a1d4ae5fb9fa | 115 | ** as a string in data.utcTime. |
embeddedartists | 0:a1d4ae5fb9fa | 116 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 117 | ** parameters: The buffer |
embeddedartists | 0:a1d4ae5fb9fa | 118 | ** Returned value: None |
embeddedartists | 0:a1d4ae5fb9fa | 119 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 120 | *****************************************************************************/ |
embeddedartists | 0:a1d4ae5fb9fa | 121 | static void parseUTC(uint8_t **ppBuf) |
embeddedartists | 0:a1d4ae5fb9fa | 122 | { |
embeddedartists | 0:a1d4ae5fb9fa | 123 | int index = 0; |
embeddedartists | 0:a1d4ae5fb9fa | 124 | // parse utc hhmmss.sss |
embeddedartists | 0:a1d4ae5fb9fa | 125 | while(**ppBuf != END_OF_MESSAGE) { |
embeddedartists | 0:a1d4ae5fb9fa | 126 | if(**ppBuf == '.') { |
embeddedartists | 0:a1d4ae5fb9fa | 127 | pointToNextValue(ppBuf); |
embeddedartists | 0:a1d4ae5fb9fa | 128 | break; //reached end of the value |
embeddedartists | 0:a1d4ae5fb9fa | 129 | } |
embeddedartists | 0:a1d4ae5fb9fa | 130 | data.utcTime[index++] = **ppBuf; |
embeddedartists | 0:a1d4ae5fb9fa | 131 | if(index == 2 || index == 5) { |
embeddedartists | 0:a1d4ae5fb9fa | 132 | //Add divider |
embeddedartists | 0:a1d4ae5fb9fa | 133 | data.utcTime[index++] = ':'; |
embeddedartists | 0:a1d4ae5fb9fa | 134 | } |
embeddedartists | 0:a1d4ae5fb9fa | 135 | (*ppBuf)++; |
embeddedartists | 0:a1d4ae5fb9fa | 136 | } |
embeddedartists | 0:a1d4ae5fb9fa | 137 | data.utcTime[index] = '\0'; |
embeddedartists | 0:a1d4ae5fb9fa | 138 | } |
embeddedartists | 0:a1d4ae5fb9fa | 139 | /***************************************************************************** |
embeddedartists | 0:a1d4ae5fb9fa | 140 | ** Function name: parseLatitude |
embeddedartists | 0:a1d4ae5fb9fa | 141 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 142 | ** Descriptions: Extracts the latitude information and stores |
embeddedartists | 0:a1d4ae5fb9fa | 143 | ** the result as an integer in data.latitude. |
embeddedartists | 0:a1d4ae5fb9fa | 144 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 145 | ** parameters: The buffer |
embeddedartists | 0:a1d4ae5fb9fa | 146 | ** Returned value: None |
embeddedartists | 0:a1d4ae5fb9fa | 147 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 148 | *****************************************************************************/ |
embeddedartists | 0:a1d4ae5fb9fa | 149 | static void parseLatitude(uint8_t **ppBuf) |
embeddedartists | 0:a1d4ae5fb9fa | 150 | { |
embeddedartists | 0:a1d4ae5fb9fa | 151 | int index = 0; |
embeddedartists | 0:a1d4ae5fb9fa | 152 | while(**ppBuf != END_OF_MESSAGE) { |
embeddedartists | 0:a1d4ae5fb9fa | 153 | if (**ppBuf == DIVIDER) { |
embeddedartists | 0:a1d4ae5fb9fa | 154 | (*ppBuf)++; //reached end of the value |
embeddedartists | 0:a1d4ae5fb9fa | 155 | break; |
embeddedartists | 0:a1d4ae5fb9fa | 156 | } |
embeddedartists | 0:a1d4ae5fb9fa | 157 | data.bufLatitude[index++] = **ppBuf; |
embeddedartists | 0:a1d4ae5fb9fa | 158 | (*ppBuf)++; |
embeddedartists | 0:a1d4ae5fb9fa | 159 | } |
embeddedartists | 0:a1d4ae5fb9fa | 160 | convertCordinateToDegree((uint8_t *) &data.bufLatitude, &data.latitude, 8); |
embeddedartists | 0:a1d4ae5fb9fa | 161 | } |
embeddedartists | 0:a1d4ae5fb9fa | 162 | /***************************************************************************** |
embeddedartists | 0:a1d4ae5fb9fa | 163 | ** Function name: GPSRetreiveData |
embeddedartists | 0:a1d4ae5fb9fa | 164 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 165 | ** Descriptions: Reads and parses the next set of GPS data. |
embeddedartists | 0:a1d4ae5fb9fa | 166 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 167 | ** parameters: None |
embeddedartists | 0:a1d4ae5fb9fa | 168 | ** Returned value: The parsed information |
embeddedartists | 0:a1d4ae5fb9fa | 169 | ** |
embeddedartists | 0:a1d4ae5fb9fa | 170 | *****************************************************************************/ |
embeddedartists | 0:a1d4ae5fb9fa | 171 | const gpsData* GPSRetreiveData(void) |
embeddedartists | 0:a1d4ae5fb9fa | 172 | { |
embeddedartists | 0:a1d4ae5fb9fa | 173 | uint8_t * pattern = (uint8_t*)"GPGGA"; |
embeddedartists | 0:a1d4ae5fb9fa | 174 | while (1) { |
embeddedartists | 0:a1d4ae5fb9fa | 175 | uint8_t buf[100]; |
embeddedartists | 0:a1d4ae5fb9fa | 176 | uint8_t ch = 0; |
embeddedartists | 0:a1d4ae5fb9fa | 177 | uint8_t *ptr = 0; |
embeddedartists | 0:a1d4ae5fb9fa | 178 | int index = 0; |
embeddedartists | 0:a1d4ae5fb9fa | 179 | |
embeddedartists | 0:a1d4ae5fb9fa | 180 | // Retrieve the first byte |
embeddedartists | 0:a1d4ae5fb9fa | 181 | //if (!UARTGetChar(&ch)) |
embeddedartists | 0:a1d4ae5fb9fa | 182 | // continue; |
embeddedartists | 0:a1d4ae5fb9fa | 183 | ch = uart.getc(); |
embeddedartists | 0:a1d4ae5fb9fa | 184 | |
embeddedartists | 0:a1d4ae5fb9fa | 185 | // look for "$GPGGA," header |
embeddedartists | 0:a1d4ae5fb9fa | 186 | if (ch != '$') { |
embeddedartists | 0:a1d4ae5fb9fa | 187 | continue; |
embeddedartists | 0:a1d4ae5fb9fa | 188 | } |
embeddedartists | 0:a1d4ae5fb9fa | 189 | |
embeddedartists | 0:a1d4ae5fb9fa | 190 | // Retrieve the next six bytes |
embeddedartists | 0:a1d4ae5fb9fa | 191 | for (index=0; index<6; index++) { |
embeddedartists | 0:a1d4ae5fb9fa | 192 | buf[index] = uart.getc(); |
embeddedartists | 0:a1d4ae5fb9fa | 193 | } |
embeddedartists | 0:a1d4ae5fb9fa | 194 | |
embeddedartists | 0:a1d4ae5fb9fa | 195 | //Check if its Global Positioning System fixed Data |
embeddedartists | 0:a1d4ae5fb9fa | 196 | if (hasPattern((uint8_t*)&buf, pattern) == 0) { |
embeddedartists | 0:a1d4ae5fb9fa | 197 | continue; |
embeddedartists | 0:a1d4ae5fb9fa | 198 | } |
embeddedartists | 0:a1d4ae5fb9fa | 199 | |
embeddedartists | 0:a1d4ae5fb9fa | 200 | //Retrieve the data from the GPS module |
embeddedartists | 0:a1d4ae5fb9fa | 201 | for (index=0; index<100; index++) { |
embeddedartists | 0:a1d4ae5fb9fa | 202 | buf[index] = uart.getc(); |
embeddedartists | 0:a1d4ae5fb9fa | 203 | if (buf[index] == '\r') { |
embeddedartists | 0:a1d4ae5fb9fa | 204 | buf[index] = END_OF_MESSAGE; |
embeddedartists | 0:a1d4ae5fb9fa | 205 | break; |
embeddedartists | 0:a1d4ae5fb9fa | 206 | } |
embeddedartists | 0:a1d4ae5fb9fa | 207 | } |
embeddedartists | 0:a1d4ae5fb9fa | 208 | ptr = &buf[0]; |
embeddedartists | 0:a1d4ae5fb9fa | 209 | |
embeddedartists | 0:a1d4ae5fb9fa | 210 | //parse UTC time |
embeddedartists | 0:a1d4ae5fb9fa | 211 | parseUTC(&ptr); |
embeddedartists | 0:a1d4ae5fb9fa | 212 | |
embeddedartists | 0:a1d4ae5fb9fa | 213 | //parse Latitude |
embeddedartists | 0:a1d4ae5fb9fa | 214 | parseLatitude(&ptr); |
embeddedartists | 0:a1d4ae5fb9fa | 215 | break; |
embeddedartists | 0:a1d4ae5fb9fa | 216 | } |
embeddedartists | 0:a1d4ae5fb9fa | 217 | return &data; |
embeddedartists | 0:a1d4ae5fb9fa | 218 | } |
embeddedartists | 0:a1d4ae5fb9fa | 219 | static void displayGpsData(const gpsData* pData) |
embeddedartists | 0:a1d4ae5fb9fa | 220 | { |
embeddedartists | 0:a1d4ae5fb9fa | 221 | //Time |
embeddedartists | 0:a1d4ae5fb9fa | 222 | printf("\n%s\n", pData->utcTime); |
embeddedartists | 0:a1d4ae5fb9fa | 223 | |
embeddedartists | 0:a1d4ae5fb9fa | 224 | //Latitude (in ddmmmmmm format, convert to dd.mmmmmm) |
embeddedartists | 0:a1d4ae5fb9fa | 225 | printf("Latitude: %d.%06d\n", pData->latitude/1000000, pData->latitude%1000000); |
embeddedartists | 0:a1d4ae5fb9fa | 226 | |
embeddedartists | 0:a1d4ae5fb9fa | 227 | //Longitude (in ddmmmmmm format, convert to dd.mmmmmm) |
embeddedartists | 0:a1d4ae5fb9fa | 228 | printf("Longitude: %d.%06d\n", pData->longitude/1000000, pData->longitude%1000000); |
embeddedartists | 0:a1d4ae5fb9fa | 229 | |
embeddedartists | 0:a1d4ae5fb9fa | 230 | //Number of satellites in view |
embeddedartists | 0:a1d4ae5fb9fa | 231 | printf("#Satellites: %s\n", pData->satellitesUsed); |
embeddedartists | 0:a1d4ae5fb9fa | 232 | } |
embeddedartists | 0:a1d4ae5fb9fa | 233 | |
embeddedartists | 0:a1d4ae5fb9fa | 234 | int main (void) |
embeddedartists | 0:a1d4ae5fb9fa | 235 | { |
embeddedartists | 0:a1d4ae5fb9fa | 236 | //initialize the UART to 9600bps 8N1 |
embeddedartists | 0:a1d4ae5fb9fa | 237 | uart.baud(9600); |
embeddedartists | 0:a1d4ae5fb9fa | 238 | //uart.format(8, Serial::None, 1); |
embeddedartists | 0:a1d4ae5fb9fa | 239 | |
embeddedartists | 0:a1d4ae5fb9fa | 240 | pc.printf("Waiting for GPS data...\n"); |
embeddedartists | 0:a1d4ae5fb9fa | 241 | |
embeddedartists | 0:a1d4ae5fb9fa | 242 | //enter forever loop |
embeddedartists | 0:a1d4ae5fb9fa | 243 | while(1) |
embeddedartists | 0:a1d4ae5fb9fa | 244 | { |
embeddedartists | 0:a1d4ae5fb9fa | 245 | const gpsData* pData = GPSRetreiveData(); |
embeddedartists | 0:a1d4ae5fb9fa | 246 | displayGpsData(pData); |
embeddedartists | 0:a1d4ae5fb9fa | 247 | wait(1); |
embeddedartists | 0:a1d4ae5fb9fa | 248 | } |
embeddedartists | 0:a1d4ae5fb9fa | 249 | } |