Revised Embedded Artists' MTK3339 library to save all raw GPS messages and enable optional decoding of RMC message.
Fork of MTK3339 by
MTK3339.cpp@4:c9861b0d3219, 2015-12-29 (annotated)
- Committer:
- tbronez
- Date:
- Tue Dec 29 16:46:07 2015 +0000
- Revision:
- 4:c9861b0d3219
- Parent:
- 3:124e25586234
Added additional statements useful for debugging
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
tbronez | 1:3057ad6a5d4b | 1 | // Original author: Embedded Artists |
tbronez | 4:c9861b0d3219 | 2 | // Revised by T. Bronez, 2015-12-16 |
embeddedartists | 0:bd0fe2412980 | 3 | |
embeddedartists | 0:bd0fe2412980 | 4 | #include "mbed.h" |
embeddedartists | 0:bd0fe2412980 | 5 | #include "MTK3339.h" |
tbronez | 1:3057ad6a5d4b | 6 | #define min(a,b) a>b?a:b |
embeddedartists | 0:bd0fe2412980 | 7 | |
tbronez | 3:124e25586234 | 8 | /* |
tbronez | 3:124e25586234 | 9 | // For DEBUG, can flash LED2 on arrival of RMC message |
tbronez | 1:3057ad6a5d4b | 10 | DigitalOut led2(LED2); |
tbronez | 1:3057ad6a5d4b | 11 | Timeout timeout2; |
tbronez | 1:3057ad6a5d4b | 12 | void led2Off() { |
tbronez | 1:3057ad6a5d4b | 13 | led2 = 1; |
tbronez | 1:3057ad6a5d4b | 14 | } |
tbronez | 1:3057ad6a5d4b | 15 | void flashLED2() { |
tbronez | 1:3057ad6a5d4b | 16 | led2 = 0; |
tbronez | 1:3057ad6a5d4b | 17 | timeout2.attach(&led2Off, 0.1); |
tbronez | 1:3057ad6a5d4b | 18 | } |
tbronez | 3:124e25586234 | 19 | */ |
embeddedartists | 0:bd0fe2412980 | 20 | |
embeddedartists | 0:bd0fe2412980 | 21 | MTK3339::MTK3339(PinName tx, PinName rx) : _serial(tx, rx) { |
embeddedartists | 0:bd0fe2412980 | 22 | _serial.baud(9600); |
embeddedartists | 0:bd0fe2412980 | 23 | _state = StateStart; |
embeddedartists | 0:bd0fe2412980 | 24 | _sentenceMask = 0; |
tbronez | 1:3057ad6a5d4b | 25 | _availDataType = NMEA_NONE; |
tbronez | 1:3057ad6a5d4b | 26 | memset(&rmc, 0, sizeof(RmcType)); |
tbronez | 1:3057ad6a5d4b | 27 | |
tbronez | 2:2391d165df47 | 28 | memset(&ggaMsg, 0, MSG_BUF_SZ+1); |
tbronez | 2:2391d165df47 | 29 | memset(&gsaMsg, 0, MSG_BUF_SZ+1); |
tbronez | 2:2391d165df47 | 30 | memset(&gsvMsg, 0, MSG_BUF_SZ+1); |
tbronez | 2:2391d165df47 | 31 | memset(&rmcMsg, 0, MSG_BUF_SZ+1); |
tbronez | 2:2391d165df47 | 32 | memset(&vtgMsg, 0, MSG_BUF_SZ+1); |
embeddedartists | 0:bd0fe2412980 | 33 | } |
embeddedartists | 0:bd0fe2412980 | 34 | |
embeddedartists | 0:bd0fe2412980 | 35 | void MTK3339::start(void (*fptr)(void), int mask) { |
embeddedartists | 0:bd0fe2412980 | 36 | if (fptr && mask) { |
embeddedartists | 0:bd0fe2412980 | 37 | _dataCallback.attach(fptr); |
embeddedartists | 0:bd0fe2412980 | 38 | _sentenceMask = mask; |
embeddedartists | 0:bd0fe2412980 | 39 | _serial.attach(this, &MTK3339::uartIrq, Serial::RxIrq); |
tbronez | 1:3057ad6a5d4b | 40 | } |
tbronez | 4:c9861b0d3219 | 41 | |
tbronez | 4:c9861b0d3219 | 42 | // DEBUG: Query antenna status |
tbronez | 4:c9861b0d3219 | 43 | //_serial.printf("$PGTOP,11,3*6F\r\n"); |
tbronez | 4:c9861b0d3219 | 44 | //_serial.printf("$PGCMD,33,1*6C\r\n"); |
embeddedartists | 0:bd0fe2412980 | 45 | } |
embeddedartists | 0:bd0fe2412980 | 46 | |
embeddedartists | 0:bd0fe2412980 | 47 | void MTK3339::stop() { |
embeddedartists | 0:bd0fe2412980 | 48 | _dataCallback.attach(NULL); |
embeddedartists | 0:bd0fe2412980 | 49 | _sentenceMask = 0; |
embeddedartists | 0:bd0fe2412980 | 50 | _serial.attach(NULL); |
embeddedartists | 0:bd0fe2412980 | 51 | } |
embeddedartists | 0:bd0fe2412980 | 52 | |
embeddedartists | 0:bd0fe2412980 | 53 | MTK3339::NmeaSentence MTK3339::getAvailableDataType() { |
embeddedartists | 0:bd0fe2412980 | 54 | return _availDataType; |
embeddedartists | 0:bd0fe2412980 | 55 | } |
embeddedartists | 0:bd0fe2412980 | 56 | |
tbronez | 1:3057ad6a5d4b | 57 | void MTK3339::decodeRMC() { |
tbronez | 1:3057ad6a5d4b | 58 | // See http://aprs.gids.nl/nmea/#rmc for RMC sentence definition |
tbronez | 1:3057ad6a5d4b | 59 | const double sixtieth = 1.0/60.0; |
tbronez | 1:3057ad6a5d4b | 60 | int n = 0; // scratch int for conversions |
tbronez | 1:3057ad6a5d4b | 61 | double d = 0; // scratch double for conversions |
tbronez | 1:3057ad6a5d4b | 62 | char* q = NULL; // scratch pointer for conversions |
tbronez | 1:3057ad6a5d4b | 63 | |
tbronez | 1:3057ad6a5d4b | 64 | memset(&rmc, 0, sizeof(RmcType)); |
tbronez | 1:3057ad6a5d4b | 65 | char* p = rmcMsg; |
tbronez | 1:3057ad6a5d4b | 66 | |
tbronez | 1:3057ad6a5d4b | 67 | /** |
tbronez | 1:3057ad6a5d4b | 68 | * Find and decode field 0, UTC time, as hhmmss.sss |
tbronez | 1:3057ad6a5d4b | 69 | */ |
tbronez | 1:3057ad6a5d4b | 70 | p = strchr(p, ','); // First comma |
tbronez | 1:3057ad6a5d4b | 71 | if (p == NULL || *p == 0) return; // Unexpected |
tbronez | 1:3057ad6a5d4b | 72 | p++; // Start of field |
tbronez | 1:3057ad6a5d4b | 73 | |
tbronez | 1:3057ad6a5d4b | 74 | q = p; |
tbronez | 1:3057ad6a5d4b | 75 | // Decode time hours |
tbronez | 1:3057ad6a5d4b | 76 | n = ((*q++) - 48)*10; // tens |
tbronez | 1:3057ad6a5d4b | 77 | n += ((*q++) - 48); // ones |
tbronez | 1:3057ad6a5d4b | 78 | rmc.gps_tm.tm_hour = n; |
tbronez | 1:3057ad6a5d4b | 79 | // Decode time minutes |
tbronez | 1:3057ad6a5d4b | 80 | n = ((*q++) - 48)*10; // tens |
tbronez | 1:3057ad6a5d4b | 81 | n += ((*q++) - 48); // ones |
tbronez | 1:3057ad6a5d4b | 82 | rmc.gps_tm.tm_min = n; |
tbronez | 1:3057ad6a5d4b | 83 | // Decode time seconds |
tbronez | 1:3057ad6a5d4b | 84 | n = ((*q++) - 48)*10; // tens |
tbronez | 1:3057ad6a5d4b | 85 | n += ((*q++) - 48); // ones |
tbronez | 1:3057ad6a5d4b | 86 | rmc.gps_tm.tm_sec = n; |
tbronez | 1:3057ad6a5d4b | 87 | // Decode time milliseconds |
tbronez | 1:3057ad6a5d4b | 88 | q++; // decimal point |
tbronez | 1:3057ad6a5d4b | 89 | n = ((*q++) - 48)*100; // hundreds of msec = tenths of second |
tbronez | 1:3057ad6a5d4b | 90 | n += ((*q++) - 48)*10; // tens of msec = hundredths of second |
tbronez | 1:3057ad6a5d4b | 91 | n += ((*q++) - 48); // ones of msec = thousandths of second |
tbronez | 1:3057ad6a5d4b | 92 | rmc.msec = n; |
tbronez | 1:3057ad6a5d4b | 93 | |
tbronez | 1:3057ad6a5d4b | 94 | /** |
tbronez | 1:3057ad6a5d4b | 95 | * Find and decode field 1, GPS status, as single |
tbronez | 1:3057ad6a5d4b | 96 | * character 'A' for valid or 'V' for invalid |
tbronez | 1:3057ad6a5d4b | 97 | */ |
tbronez | 1:3057ad6a5d4b | 98 | p = strchr(p, ','); // Next comma |
tbronez | 1:3057ad6a5d4b | 99 | if (p == NULL || *p == 0) return; // Unexpected |
tbronez | 1:3057ad6a5d4b | 100 | p++; // Start of field |
tbronez | 1:3057ad6a5d4b | 101 | |
tbronez | 1:3057ad6a5d4b | 102 | if (*p == 'A' || *p == 'V') |
tbronez | 1:3057ad6a5d4b | 103 | rmc.status = *p; |
tbronez | 1:3057ad6a5d4b | 104 | else |
tbronez | 1:3057ad6a5d4b | 105 | rmc.status = ' '; |
tbronez | 1:3057ad6a5d4b | 106 | |
tbronez | 1:3057ad6a5d4b | 107 | /** |
tbronez | 1:3057ad6a5d4b | 108 | * Find and decode field 2, latitude, formatted as ddmm.mmmm |
tbronez | 1:3057ad6a5d4b | 109 | */ |
tbronez | 1:3057ad6a5d4b | 110 | p = strchr(p, ','); // Next comma |
tbronez | 1:3057ad6a5d4b | 111 | if (p == NULL || *p == 0) return; // Unexpected |
tbronez | 1:3057ad6a5d4b | 112 | p++; // Start of field |
tbronez | 1:3057ad6a5d4b | 113 | |
tbronez | 1:3057ad6a5d4b | 114 | q = p; |
tbronez | 1:3057ad6a5d4b | 115 | d = ((*q++) - 48)*10; // tens |
tbronez | 1:3057ad6a5d4b | 116 | d += ((*q++) - 48); // ones |
tbronez | 1:3057ad6a5d4b | 117 | rmc.lat_dd = d; // whole degrees |
embeddedartists | 0:bd0fe2412980 | 118 | |
tbronez | 1:3057ad6a5d4b | 119 | d = ((*q++) - 48)*10; // tens |
tbronez | 1:3057ad6a5d4b | 120 | d += ((*q++) - 48); // ones |
tbronez | 1:3057ad6a5d4b | 121 | q++; // decimal point |
tbronez | 1:3057ad6a5d4b | 122 | d += ((*q++) - 48)*0.1000; // tenths |
tbronez | 1:3057ad6a5d4b | 123 | d += ((*q++) - 48)*0.0100; // hundredths |
tbronez | 1:3057ad6a5d4b | 124 | d += ((*q++) - 48)*0.0010; // thousandths |
tbronez | 1:3057ad6a5d4b | 125 | d += ((*q++) - 48)*0.0001; // ten-thousandths |
tbronez | 1:3057ad6a5d4b | 126 | if (*q == ',') |
tbronez | 1:3057ad6a5d4b | 127 | rmc.lat_dd += sixtieth*d; // decimal degrees |
tbronez | 1:3057ad6a5d4b | 128 | else |
tbronez | 1:3057ad6a5d4b | 129 | rmc.lat_dd = NAN; // Unexpected |
tbronez | 1:3057ad6a5d4b | 130 | |
tbronez | 1:3057ad6a5d4b | 131 | /** |
tbronez | 1:3057ad6a5d4b | 132 | * Find and decode field 3, latitude sense, as single |
tbronez | 1:3057ad6a5d4b | 133 | * character 'N' for north or 'S' for south |
tbronez | 1:3057ad6a5d4b | 134 | */ |
tbronez | 1:3057ad6a5d4b | 135 | p = strchr(p, ','); // Next comma |
tbronez | 1:3057ad6a5d4b | 136 | if (p == NULL || *p == 0) return; // Unexpected |
tbronez | 1:3057ad6a5d4b | 137 | p++; // Start of field |
embeddedartists | 0:bd0fe2412980 | 138 | |
tbronez | 1:3057ad6a5d4b | 139 | if (*p == 'S') rmc.lat_dd = -rmc.lat_dd; |
tbronez | 1:3057ad6a5d4b | 140 | |
tbronez | 1:3057ad6a5d4b | 141 | /** |
tbronez | 1:3057ad6a5d4b | 142 | * Find and decode field 4, longitude, formatted as dddmm.mmmm |
tbronez | 1:3057ad6a5d4b | 143 | */ |
tbronez | 1:3057ad6a5d4b | 144 | p = strchr(p, ','); // Next comma |
tbronez | 1:3057ad6a5d4b | 145 | if (p == NULL || *p == 0) return; // Unexpected |
tbronez | 1:3057ad6a5d4b | 146 | p++; // Start of field |
tbronez | 1:3057ad6a5d4b | 147 | |
tbronez | 1:3057ad6a5d4b | 148 | q = p; |
tbronez | 1:3057ad6a5d4b | 149 | d = ((*q++) - 48)*100; // hundreds |
tbronez | 1:3057ad6a5d4b | 150 | d += ((*q++) - 48)*10; // tens |
tbronez | 1:3057ad6a5d4b | 151 | d += ((*q++) - 48); // ones |
tbronez | 1:3057ad6a5d4b | 152 | rmc.lon_dd = d; // whole degrees |
embeddedartists | 0:bd0fe2412980 | 153 | |
tbronez | 1:3057ad6a5d4b | 154 | d = ((*q++) - 48)*10; // tens |
tbronez | 1:3057ad6a5d4b | 155 | d += ((*q++) - 48); // ones |
tbronez | 1:3057ad6a5d4b | 156 | q++; // decimal point |
tbronez | 1:3057ad6a5d4b | 157 | d += ((*q++) - 48)*0.1000; // tenths |
tbronez | 1:3057ad6a5d4b | 158 | d += ((*q++) - 48)*0.0100; // hundredths |
tbronez | 1:3057ad6a5d4b | 159 | d += ((*q++) - 48)*0.0010; // thousandths |
tbronez | 1:3057ad6a5d4b | 160 | d += ((*q++) - 48)*0.0001; // ten-thousandths |
tbronez | 1:3057ad6a5d4b | 161 | if (*q == ',') |
tbronez | 1:3057ad6a5d4b | 162 | rmc.lon_dd += sixtieth*d; // decimal degrees |
tbronez | 1:3057ad6a5d4b | 163 | else |
tbronez | 1:3057ad6a5d4b | 164 | rmc.lon_dd = NAN; // Unexpected |
tbronez | 1:3057ad6a5d4b | 165 | |
tbronez | 1:3057ad6a5d4b | 166 | /** |
tbronez | 1:3057ad6a5d4b | 167 | * Find and decode field 5, longitude sense, as single |
tbronez | 1:3057ad6a5d4b | 168 | * character 'E' for east or 'W' for west |
tbronez | 1:3057ad6a5d4b | 169 | */ |
tbronez | 1:3057ad6a5d4b | 170 | p = strchr(p, ','); // Next comma |
tbronez | 1:3057ad6a5d4b | 171 | if (p == NULL || *p == 0) return; // Unexpected |
tbronez | 1:3057ad6a5d4b | 172 | p++; // Start of field |
tbronez | 1:3057ad6a5d4b | 173 | |
tbronez | 1:3057ad6a5d4b | 174 | if (*p == 'W') rmc.lon_dd = -rmc.lon_dd; |
embeddedartists | 0:bd0fe2412980 | 175 | |
tbronez | 1:3057ad6a5d4b | 176 | /** |
tbronez | 1:3057ad6a5d4b | 177 | * Find and skip field 6, speed in knots |
tbronez | 1:3057ad6a5d4b | 178 | */ |
tbronez | 1:3057ad6a5d4b | 179 | p = strchr(p, ','); // Next comma |
tbronez | 1:3057ad6a5d4b | 180 | if (p == NULL || *p == 0) return; // Unexpected |
tbronez | 1:3057ad6a5d4b | 181 | p++; // Start of field |
tbronez | 1:3057ad6a5d4b | 182 | |
tbronez | 1:3057ad6a5d4b | 183 | /** |
tbronez | 1:3057ad6a5d4b | 184 | * Find and skip field 7, course in degrees |
tbronez | 1:3057ad6a5d4b | 185 | */ |
tbronez | 1:3057ad6a5d4b | 186 | p = strchr(p, ','); // Next comma |
tbronez | 1:3057ad6a5d4b | 187 | if (p == NULL || *p == 0) return; // Unexpected |
tbronez | 1:3057ad6a5d4b | 188 | p++; // Start of field |
tbronez | 1:3057ad6a5d4b | 189 | |
tbronez | 1:3057ad6a5d4b | 190 | /** |
tbronez | 1:3057ad6a5d4b | 191 | * Find and decode field 8, UTC date, formatted as ddmmyy |
tbronez | 1:3057ad6a5d4b | 192 | * where 1<=dd<=31, 1<=mm<=12, and yy is offset from 2000 |
tbronez | 1:3057ad6a5d4b | 193 | */ |
tbronez | 1:3057ad6a5d4b | 194 | p = strchr(p, ','); // Next comma |
tbronez | 1:3057ad6a5d4b | 195 | if (p == NULL || *p == 0) return; // Unexpected |
tbronez | 1:3057ad6a5d4b | 196 | p++; // Start of field |
tbronez | 1:3057ad6a5d4b | 197 | |
tbronez | 1:3057ad6a5d4b | 198 | q = p; |
tbronez | 1:3057ad6a5d4b | 199 | // Decode date day |
tbronez | 1:3057ad6a5d4b | 200 | n = ((*q++) - 48)*10; // tens |
tbronez | 1:3057ad6a5d4b | 201 | n += ((*q++) - 48); // ones |
tbronez | 1:3057ad6a5d4b | 202 | rmc.gps_tm.tm_mday = n; |
tbronez | 1:3057ad6a5d4b | 203 | // Decode date month |
tbronez | 1:3057ad6a5d4b | 204 | n = ((*q++) - 48)*10; // tens |
tbronez | 1:3057ad6a5d4b | 205 | n += ((*q++) - 48); // ones |
tbronez | 1:3057ad6a5d4b | 206 | rmc.gps_tm.tm_mon = n-1; // tm_mon runs 0-11, not 1-12 |
tbronez | 1:3057ad6a5d4b | 207 | // Decode date year |
tbronez | 1:3057ad6a5d4b | 208 | n = ((*q++) - 48)*10; // tens |
tbronez | 1:3057ad6a5d4b | 209 | n += ((*q++) - 48); // ones |
tbronez | 1:3057ad6a5d4b | 210 | rmc.gps_tm.tm_year = n+100; // tm_year is offset from year 1900, not 2000 |
tbronez | 1:3057ad6a5d4b | 211 | |
tbronez | 1:3057ad6a5d4b | 212 | /** |
tbronez | 1:3057ad6a5d4b | 213 | * Find and skip field 9, magnetic variation |
tbronez | 1:3057ad6a5d4b | 214 | * (not implemented in GPS firmware) |
tbronez | 1:3057ad6a5d4b | 215 | */ |
tbronez | 1:3057ad6a5d4b | 216 | p = strchr(p, ','); // Next comma |
tbronez | 1:3057ad6a5d4b | 217 | if (p == NULL || *p == 0) return; // Unexpected |
tbronez | 1:3057ad6a5d4b | 218 | p++; // Start of field |
tbronez | 1:3057ad6a5d4b | 219 | |
tbronez | 1:3057ad6a5d4b | 220 | /** |
tbronez | 1:3057ad6a5d4b | 221 | * Find and skip field 10, magnetic variation direction |
tbronez | 1:3057ad6a5d4b | 222 | * (not implemented in GPS firmware) |
tbronez | 1:3057ad6a5d4b | 223 | */ |
tbronez | 1:3057ad6a5d4b | 224 | p = strchr(p, ','); // Next comma |
tbronez | 1:3057ad6a5d4b | 225 | if (p == NULL || *p == 0) return; // Unexpected |
tbronez | 1:3057ad6a5d4b | 226 | p++; // Start of field |
embeddedartists | 0:bd0fe2412980 | 227 | } |
embeddedartists | 0:bd0fe2412980 | 228 | |
tbronez | 1:3057ad6a5d4b | 229 | void MTK3339::saveGGA(char* data, int dataLen) { |
tbronez | 1:3057ad6a5d4b | 230 | // See http://aprs.gids.nl/nmea/#gga for GGA sentence definition |
tbronez | 1:3057ad6a5d4b | 231 | memcpy (ggaMsg, data, min(dataLen, MSG_BUF_SZ)); |
tbronez | 1:3057ad6a5d4b | 232 | } |
tbronez | 1:3057ad6a5d4b | 233 | |
tbronez | 1:3057ad6a5d4b | 234 | void MTK3339::saveGSA(char* data, int dataLen) { |
tbronez | 1:3057ad6a5d4b | 235 | // See http://aprs.gids.nl/nmea/#gsa for GSA sentence definition |
tbronez | 1:3057ad6a5d4b | 236 | memcpy (gsaMsg, data, min(dataLen, MSG_BUF_SZ)); |
embeddedartists | 0:bd0fe2412980 | 237 | } |
embeddedartists | 0:bd0fe2412980 | 238 | |
tbronez | 1:3057ad6a5d4b | 239 | void MTK3339::saveGSV(char* data, int dataLen) { |
tbronez | 1:3057ad6a5d4b | 240 | // See http://aprs.gids.nl/nmea/#gsv for GSV sentence definition |
tbronez | 1:3057ad6a5d4b | 241 | memcpy (gsvMsg, data, min(dataLen, MSG_BUF_SZ)); |
embeddedartists | 0:bd0fe2412980 | 242 | } |
embeddedartists | 0:bd0fe2412980 | 243 | |
tbronez | 1:3057ad6a5d4b | 244 | void MTK3339::saveRMC(char* data, int dataLen) { |
tbronez | 1:3057ad6a5d4b | 245 | // See http://aprs.gids.nl/nmea/#rmc for RMC sentence definition |
tbronez | 1:3057ad6a5d4b | 246 | memcpy (rmcMsg, data, min(dataLen, MSG_BUF_SZ)); |
tbronez | 1:3057ad6a5d4b | 247 | } |
embeddedartists | 0:bd0fe2412980 | 248 | |
tbronez | 1:3057ad6a5d4b | 249 | void MTK3339::saveVTG(char* data, int dataLen) { |
tbronez | 1:3057ad6a5d4b | 250 | // See http://aprs.gids.nl/nmea/#vtg for VTG sentence definition |
tbronez | 1:3057ad6a5d4b | 251 | memcpy (vtgMsg, data, min(dataLen, MSG_BUF_SZ)); |
tbronez | 1:3057ad6a5d4b | 252 | } |
tbronez | 1:3057ad6a5d4b | 253 | |
tbronez | 1:3057ad6a5d4b | 254 | void MTK3339::saveData(char* data, int len) { |
embeddedartists | 0:bd0fe2412980 | 255 | do { |
tbronez | 1:3057ad6a5d4b | 256 | // Verify checksum |
embeddedartists | 0:bd0fe2412980 | 257 | if (len < 3 || (len > 3 && data[len-3] != '*')) { |
embeddedartists | 0:bd0fe2412980 | 258 | // invalid data |
embeddedartists | 0:bd0fe2412980 | 259 | break; |
embeddedartists | 0:bd0fe2412980 | 260 | } |
embeddedartists | 0:bd0fe2412980 | 261 | int sum = strtol(&data[len-2], NULL, 16); |
embeddedartists | 0:bd0fe2412980 | 262 | for(int i = 1; i < len-3; i++) { |
embeddedartists | 0:bd0fe2412980 | 263 | sum ^= data[i]; |
embeddedartists | 0:bd0fe2412980 | 264 | } |
embeddedartists | 0:bd0fe2412980 | 265 | if (sum != 0) { |
embeddedartists | 0:bd0fe2412980 | 266 | // invalid checksum |
embeddedartists | 0:bd0fe2412980 | 267 | break; |
tbronez | 1:3057ad6a5d4b | 268 | } |
tbronez | 1:3057ad6a5d4b | 269 | |
tbronez | 4:c9861b0d3219 | 270 | //printf("msg: %s\n", data); // DEBUG |
tbronez | 4:c9861b0d3219 | 271 | |
tbronez | 1:3057ad6a5d4b | 272 | // Save appropriate sentence for later decoding |
tbronez | 1:3057ad6a5d4b | 273 | if (strncmp("$GPRMC", data, 6) == 0 && (_sentenceMask & NMEA_RMC) != 0) { |
tbronez | 3:124e25586234 | 274 | //flashLED2(); // for DEBUG |
tbronez | 1:3057ad6a5d4b | 275 | saveRMC(data, len); |
tbronez | 1:3057ad6a5d4b | 276 | _availDataType = NMEA_RMC; |
embeddedartists | 0:bd0fe2412980 | 277 | _dataCallback.call(); |
tbronez | 1:3057ad6a5d4b | 278 | _availDataType = NMEA_NONE; |
tbronez | 1:3057ad6a5d4b | 279 | } |
tbronez | 1:3057ad6a5d4b | 280 | else if (strncmp("$GPGGA", data, 6) == 0 && (_sentenceMask & NMEA_GGA) != 0) { |
tbronez | 1:3057ad6a5d4b | 281 | saveGGA(data, len); |
tbronez | 1:3057ad6a5d4b | 282 | _availDataType = NMEA_GGA; |
tbronez | 1:3057ad6a5d4b | 283 | _dataCallback.call(); |
tbronez | 1:3057ad6a5d4b | 284 | _availDataType = NMEA_NONE; |
embeddedartists | 0:bd0fe2412980 | 285 | } |
tbronez | 1:3057ad6a5d4b | 286 | else if (strncmp("$GPGSA", data, 6) == 0 && (_sentenceMask & NMEA_GSA) != 0) { |
tbronez | 1:3057ad6a5d4b | 287 | saveGSA(data, len); |
tbronez | 1:3057ad6a5d4b | 288 | _availDataType = NMEA_GSA; |
embeddedartists | 0:bd0fe2412980 | 289 | _dataCallback.call(); |
tbronez | 1:3057ad6a5d4b | 290 | _availDataType = NMEA_NONE; |
tbronez | 1:3057ad6a5d4b | 291 | } |
tbronez | 1:3057ad6a5d4b | 292 | else if (strncmp("$GPGSV", data, 6) == 0 && (_sentenceMask & NMEA_GSV) != 0) { |
tbronez | 1:3057ad6a5d4b | 293 | saveGSV(data, len); |
tbronez | 1:3057ad6a5d4b | 294 | _availDataType = NMEA_GSV; |
tbronez | 1:3057ad6a5d4b | 295 | _dataCallback.call(); |
tbronez | 1:3057ad6a5d4b | 296 | _availDataType = NMEA_NONE; |
tbronez | 1:3057ad6a5d4b | 297 | } |
tbronez | 1:3057ad6a5d4b | 298 | else if (strncmp("$GPVTG", data, 6) == 0 && (_sentenceMask & NMEA_VTG) != 0) { |
tbronez | 1:3057ad6a5d4b | 299 | saveVTG(data, len); |
tbronez | 1:3057ad6a5d4b | 300 | _availDataType = NMEA_VTG; |
tbronez | 1:3057ad6a5d4b | 301 | _dataCallback.call(); |
tbronez | 1:3057ad6a5d4b | 302 | _availDataType = NMEA_NONE; |
tbronez | 4:c9861b0d3219 | 303 | } |
embeddedartists | 0:bd0fe2412980 | 304 | } while(0); |
embeddedartists | 0:bd0fe2412980 | 305 | } |
embeddedartists | 0:bd0fe2412980 | 306 | |
embeddedartists | 0:bd0fe2412980 | 307 | void MTK3339::uartIrq() { |
embeddedartists | 0:bd0fe2412980 | 308 | char d = 0; |
embeddedartists | 0:bd0fe2412980 | 309 | while(_serial.readable()) { |
embeddedartists | 0:bd0fe2412980 | 310 | d = _serial.getc(); |
embeddedartists | 0:bd0fe2412980 | 311 | switch(_state) { |
embeddedartists | 0:bd0fe2412980 | 312 | case StateStart: |
embeddedartists | 0:bd0fe2412980 | 313 | if (d == '$') { |
embeddedartists | 0:bd0fe2412980 | 314 | _buf[0] = '$'; |
embeddedartists | 0:bd0fe2412980 | 315 | _bufPos = 1; |
embeddedartists | 0:bd0fe2412980 | 316 | _state = StateData; |
embeddedartists | 0:bd0fe2412980 | 317 | } |
embeddedartists | 0:bd0fe2412980 | 318 | break; |
embeddedartists | 0:bd0fe2412980 | 319 | case StateData: |
embeddedartists | 0:bd0fe2412980 | 320 | if (_bufPos >= MTK3339_BUF_SZ) { |
embeddedartists | 0:bd0fe2412980 | 321 | // error |
embeddedartists | 0:bd0fe2412980 | 322 | _state = StateStart; |
embeddedartists | 0:bd0fe2412980 | 323 | } |
embeddedartists | 0:bd0fe2412980 | 324 | else if (d == '\r') { |
embeddedartists | 0:bd0fe2412980 | 325 | _buf[_bufPos] = 0; |
tbronez | 1:3057ad6a5d4b | 326 | saveData(_buf, _bufPos); |
embeddedartists | 0:bd0fe2412980 | 327 | _state = StateStart; |
embeddedartists | 0:bd0fe2412980 | 328 | } |
embeddedartists | 0:bd0fe2412980 | 329 | else { |
embeddedartists | 0:bd0fe2412980 | 330 | _buf[_bufPos++] = d; |
embeddedartists | 0:bd0fe2412980 | 331 | } |
embeddedartists | 0:bd0fe2412980 | 332 | break; |
embeddedartists | 0:bd0fe2412980 | 333 | } |
embeddedartists | 0:bd0fe2412980 | 334 | } |
embeddedartists | 0:bd0fe2412980 | 335 | } |
tbronez | 1:3057ad6a5d4b | 336 | |
tbronez | 4:c9861b0d3219 | 337 | /* |
tbronez | 4:c9861b0d3219 | 338 | From http://forum.trenz-electronic.de/index.php?topic=273.0 |
tbronez | 4:c9861b0d3219 | 339 | (untested), other MTK3339 commands and responses: |
tbronez | 4:c9861b0d3219 | 340 | |
tbronez | 4:c9861b0d3219 | 341 | To disable antenna status/advisor messages, |
tbronez | 4:c9861b0d3219 | 342 | $PGCMD,33,0*6D<CR><LF> |
tbronez | 4:c9861b0d3219 | 343 | |
tbronez | 4:c9861b0d3219 | 344 | MTK3339 should acknowledge with |
tbronez | 4:c9861b0d3219 | 345 | $PGACK,33,0*6E<CR><LF> |
tbronez | 2:2391d165df47 | 346 | |
tbronez | 4:c9861b0d3219 | 347 | To enable antenna status/advisor messages, |
tbronez | 4:c9861b0d3219 | 348 | $PGCMD,33,1*6C<CR><LF> |
tbronez | 4:c9861b0d3219 | 349 | |
tbronez | 4:c9861b0d3219 | 350 | MTK3339 should acknowledge with |
tbronez | 4:c9861b0d3219 | 351 | $PGACK,33,1*6F<CR><LF> |
tbronez | 4:c9861b0d3219 | 352 | |
tbronez | 4:c9861b0d3219 | 353 | To query antenna status, |
tbronez | 4:c9861b0d3219 | 354 | $PGTOP,11,3*6F<CR><LF> |
tbronez | 4:c9861b0d3219 | 355 | |
tbronez | 4:c9861b0d3219 | 356 | MTK3339 should respond with one of the following: |
tbronez | 4:c9861b0d3219 | 357 | $PGTOP,11,1*6D active antenna shorted |
tbronez | 4:c9861b0d3219 | 358 | $PGTOP,11,2*6E using internal antenna |
tbronez | 4:c9861b0d3219 | 359 | $PGTOP,11,3*6F using active antenna |
tbronez | 4:c9861b0d3219 | 360 | */ |