Revised Embedded Artists' MTK3339 library to save all raw GPS messages and enable optional decoding of RMC message.

Fork of MTK3339 by EmbeddedArtists AB

Committer:
embeddedartists
Date:
Thu Nov 07 11:46:53 2013 +0000
Revision:
0:bd0fe2412980
Child:
1:3057ad6a5d4b
First release

Who changed what in which revision?

UserRevisionLine numberNew contents of line
embeddedartists 0:bd0fe2412980 1
embeddedartists 0:bd0fe2412980 2 #include "mbed.h"
embeddedartists 0:bd0fe2412980 3 #include "MTK3339.h"
embeddedartists 0:bd0fe2412980 4
embeddedartists 0:bd0fe2412980 5
embeddedartists 0:bd0fe2412980 6 MTK3339::MTK3339(PinName tx, PinName rx) : _serial(tx, rx) {
embeddedartists 0:bd0fe2412980 7 _serial.baud(9600);
embeddedartists 0:bd0fe2412980 8
embeddedartists 0:bd0fe2412980 9 _state = StateStart;
embeddedartists 0:bd0fe2412980 10 _sentenceMask = 0;
embeddedartists 0:bd0fe2412980 11 _availDataType = NmeaInvalid;
embeddedartists 0:bd0fe2412980 12 memset(&gga, 0, sizeof(GgaType));
embeddedartists 0:bd0fe2412980 13 memset(&vtg, 0, sizeof(VtgType));
embeddedartists 0:bd0fe2412980 14 }
embeddedartists 0:bd0fe2412980 15
embeddedartists 0:bd0fe2412980 16 void MTK3339::start(void (*fptr)(void), int mask) {
embeddedartists 0:bd0fe2412980 17 if (fptr && mask) {
embeddedartists 0:bd0fe2412980 18 _dataCallback.attach(fptr);
embeddedartists 0:bd0fe2412980 19 _sentenceMask = mask;
embeddedartists 0:bd0fe2412980 20 _serial.attach(this, &MTK3339::uartIrq, Serial::RxIrq);
embeddedartists 0:bd0fe2412980 21 }
embeddedartists 0:bd0fe2412980 22 }
embeddedartists 0:bd0fe2412980 23
embeddedartists 0:bd0fe2412980 24 void MTK3339::stop() {
embeddedartists 0:bd0fe2412980 25 _dataCallback.attach(NULL);
embeddedartists 0:bd0fe2412980 26 _sentenceMask = 0;
embeddedartists 0:bd0fe2412980 27 _serial.attach(NULL);
embeddedartists 0:bd0fe2412980 28 }
embeddedartists 0:bd0fe2412980 29
embeddedartists 0:bd0fe2412980 30 MTK3339::NmeaSentence MTK3339::getAvailableDataType() {
embeddedartists 0:bd0fe2412980 31 return _availDataType;
embeddedartists 0:bd0fe2412980 32 }
embeddedartists 0:bd0fe2412980 33
embeddedartists 0:bd0fe2412980 34 double MTK3339::getLatitudeAsDegrees() {
embeddedartists 0:bd0fe2412980 35 if(gga.fix == 0 || gga.nsIndicator == 0) return 0;
embeddedartists 0:bd0fe2412980 36
embeddedartists 0:bd0fe2412980 37 double l = gga.latitude;
embeddedartists 0:bd0fe2412980 38 char ns = gga.nsIndicator;
embeddedartists 0:bd0fe2412980 39
embeddedartists 0:bd0fe2412980 40 // convert from ddmm.mmmm to degrees only
embeddedartists 0:bd0fe2412980 41 // 60 minutes is 1 degree
embeddedartists 0:bd0fe2412980 42
embeddedartists 0:bd0fe2412980 43 int deg = (int)(l / 100);
embeddedartists 0:bd0fe2412980 44 l = (l - deg*100.0) / 60.0;
embeddedartists 0:bd0fe2412980 45 l = deg + l;
embeddedartists 0:bd0fe2412980 46 if (ns == 'S') l = -l;
embeddedartists 0:bd0fe2412980 47
embeddedartists 0:bd0fe2412980 48 return l;
embeddedartists 0:bd0fe2412980 49 }
embeddedartists 0:bd0fe2412980 50
embeddedartists 0:bd0fe2412980 51 double MTK3339::getLongitudeAsDegrees() {
embeddedartists 0:bd0fe2412980 52 if(gga.fix == 0 || gga.ewIndicator == 0) return 0;
embeddedartists 0:bd0fe2412980 53
embeddedartists 0:bd0fe2412980 54 double l = gga.longitude;
embeddedartists 0:bd0fe2412980 55 char ew = gga.ewIndicator;
embeddedartists 0:bd0fe2412980 56
embeddedartists 0:bd0fe2412980 57 // convert from ddmm.mmmm to degrees only
embeddedartists 0:bd0fe2412980 58 // 60 minutes is 1 degree
embeddedartists 0:bd0fe2412980 59
embeddedartists 0:bd0fe2412980 60 int deg = (int)(l / 100);
embeddedartists 0:bd0fe2412980 61 l = (l - deg*100) / 60;
embeddedartists 0:bd0fe2412980 62 l = deg + l;
embeddedartists 0:bd0fe2412980 63 if (ew == 'W') l = -l;
embeddedartists 0:bd0fe2412980 64
embeddedartists 0:bd0fe2412980 65 return l;
embeddedartists 0:bd0fe2412980 66 }
embeddedartists 0:bd0fe2412980 67
embeddedartists 0:bd0fe2412980 68 void MTK3339::parseGGA(char* data, int dataLen) {
embeddedartists 0:bd0fe2412980 69 //http://aprs.gids.nl/nmea/#gga
embeddedartists 0:bd0fe2412980 70
embeddedartists 0:bd0fe2412980 71 double tm = 0;
embeddedartists 0:bd0fe2412980 72
embeddedartists 0:bd0fe2412980 73 memset(&gga, 0, sizeof(GgaType));
embeddedartists 0:bd0fe2412980 74
embeddedartists 0:bd0fe2412980 75 char* p = data;
embeddedartists 0:bd0fe2412980 76 int pos = 0;
embeddedartists 0:bd0fe2412980 77
embeddedartists 0:bd0fe2412980 78 p = strchr(p, ',');
embeddedartists 0:bd0fe2412980 79 while (p != NULL && *p != 0) {
embeddedartists 0:bd0fe2412980 80 p++;
embeddedartists 0:bd0fe2412980 81
embeddedartists 0:bd0fe2412980 82 switch(pos) {
embeddedartists 0:bd0fe2412980 83 case 0: // time: hhmmss.sss
embeddedartists 0:bd0fe2412980 84 tm = strtod(p, NULL);
embeddedartists 0:bd0fe2412980 85 gga.hours = (int)(tm / 10000);
embeddedartists 0:bd0fe2412980 86 gga.minutes = ((int)tm % 10000) / 100;
embeddedartists 0:bd0fe2412980 87 gga.seconds = ((int)tm % 100);
embeddedartists 0:bd0fe2412980 88 gga.milliseconds = (int)(tm * 1000) % 1000;
embeddedartists 0:bd0fe2412980 89 break;
embeddedartists 0:bd0fe2412980 90 case 1: // latitude: ddmm.mmmm
embeddedartists 0:bd0fe2412980 91 gga.latitude = strtod(p, NULL);
embeddedartists 0:bd0fe2412980 92 break;
embeddedartists 0:bd0fe2412980 93 case 2: // N/S indicator (north or south)
embeddedartists 0:bd0fe2412980 94 if (*p == 'N' || *p == 'S') {
embeddedartists 0:bd0fe2412980 95 gga.nsIndicator = *p;
embeddedartists 0:bd0fe2412980 96 }
embeddedartists 0:bd0fe2412980 97 break;
embeddedartists 0:bd0fe2412980 98 case 3: // longitude: dddmm.mmmm
embeddedartists 0:bd0fe2412980 99 gga.longitude = strtod(p, NULL);
embeddedartists 0:bd0fe2412980 100 break;
embeddedartists 0:bd0fe2412980 101 case 4: // E/W indicator (east or west)
embeddedartists 0:bd0fe2412980 102 if (*p == 'E' || *p == 'W') {
embeddedartists 0:bd0fe2412980 103 gga.ewIndicator = *p;
embeddedartists 0:bd0fe2412980 104 }
embeddedartists 0:bd0fe2412980 105 break;
embeddedartists 0:bd0fe2412980 106 case 5: // position indicator (1=no fix, 2=GPS fix, 3=Differential)
embeddedartists 0:bd0fe2412980 107 gga.fix = strtol(p, NULL, 10);
embeddedartists 0:bd0fe2412980 108 break;
embeddedartists 0:bd0fe2412980 109 case 6: // num satellites
embeddedartists 0:bd0fe2412980 110 gga.satellites = strtol(p, NULL, 10);
embeddedartists 0:bd0fe2412980 111 break;
embeddedartists 0:bd0fe2412980 112 case 7: // hdop
embeddedartists 0:bd0fe2412980 113 gga.hdop = strtod(p, NULL);
embeddedartists 0:bd0fe2412980 114 break;
embeddedartists 0:bd0fe2412980 115 case 8: // altitude
embeddedartists 0:bd0fe2412980 116 gga.altitude = strtod(p, NULL);
embeddedartists 0:bd0fe2412980 117 break;
embeddedartists 0:bd0fe2412980 118 case 9: // units
embeddedartists 0:bd0fe2412980 119 // ignore units
embeddedartists 0:bd0fe2412980 120 break;
embeddedartists 0:bd0fe2412980 121 case 10: // geoidal separation
embeddedartists 0:bd0fe2412980 122 gga.geoidal = strtod(p, NULL);
embeddedartists 0:bd0fe2412980 123 break;
embeddedartists 0:bd0fe2412980 124 }
embeddedartists 0:bd0fe2412980 125 pos++;
embeddedartists 0:bd0fe2412980 126
embeddedartists 0:bd0fe2412980 127 p = strchr(p, ',');
embeddedartists 0:bd0fe2412980 128 }
embeddedartists 0:bd0fe2412980 129
embeddedartists 0:bd0fe2412980 130 }
embeddedartists 0:bd0fe2412980 131
embeddedartists 0:bd0fe2412980 132 void MTK3339::parseVTG(char* data, int dataLen) {
embeddedartists 0:bd0fe2412980 133
embeddedartists 0:bd0fe2412980 134
embeddedartists 0:bd0fe2412980 135 char* p = data;
embeddedartists 0:bd0fe2412980 136 int pos = 0;
embeddedartists 0:bd0fe2412980 137
embeddedartists 0:bd0fe2412980 138 memset(&vtg, 0, sizeof(VtgType));
embeddedartists 0:bd0fe2412980 139
embeddedartists 0:bd0fe2412980 140 p = strchr(p, ',');
embeddedartists 0:bd0fe2412980 141 while (p != NULL && *p != 0) {
embeddedartists 0:bd0fe2412980 142 p++;
embeddedartists 0:bd0fe2412980 143
embeddedartists 0:bd0fe2412980 144 switch(pos) {
embeddedartists 0:bd0fe2412980 145 case 0: // course in degrees
embeddedartists 0:bd0fe2412980 146 vtg.course = strtod(p, NULL);
embeddedartists 0:bd0fe2412980 147 break;
embeddedartists 0:bd0fe2412980 148 case 1: // Reference (T)
embeddedartists 0:bd0fe2412980 149 break;
embeddedartists 0:bd0fe2412980 150 case 2: // course magnetic (need customization)
embeddedartists 0:bd0fe2412980 151 break;
embeddedartists 0:bd0fe2412980 152 case 3: // reference (M)
embeddedartists 0:bd0fe2412980 153 break;
embeddedartists 0:bd0fe2412980 154 case 4: // speed in knots
embeddedartists 0:bd0fe2412980 155 vtg.speedKnots = strtod(p, NULL);
embeddedartists 0:bd0fe2412980 156 break;
embeddedartists 0:bd0fe2412980 157 case 5: // units (N)
embeddedartists 0:bd0fe2412980 158 break;
embeddedartists 0:bd0fe2412980 159 case 6: // speed in Km/h
embeddedartists 0:bd0fe2412980 160 vtg.speedKmHour = strtod(p, NULL);
embeddedartists 0:bd0fe2412980 161 break;
embeddedartists 0:bd0fe2412980 162 case 7: // units (K)
embeddedartists 0:bd0fe2412980 163 break;
embeddedartists 0:bd0fe2412980 164 case 8: // mode
embeddedartists 0:bd0fe2412980 165 if (*p == 'A' || *p == 'D' || *p == 'E') {
embeddedartists 0:bd0fe2412980 166 vtg.mode = *p;
embeddedartists 0:bd0fe2412980 167 }
embeddedartists 0:bd0fe2412980 168
embeddedartists 0:bd0fe2412980 169 break;
embeddedartists 0:bd0fe2412980 170
embeddedartists 0:bd0fe2412980 171 }
embeddedartists 0:bd0fe2412980 172
embeddedartists 0:bd0fe2412980 173 pos++;
embeddedartists 0:bd0fe2412980 174
embeddedartists 0:bd0fe2412980 175 p = strchr(p, ',');
embeddedartists 0:bd0fe2412980 176 }
embeddedartists 0:bd0fe2412980 177 }
embeddedartists 0:bd0fe2412980 178
embeddedartists 0:bd0fe2412980 179
embeddedartists 0:bd0fe2412980 180 void MTK3339::parseData(char* data, int len) {
embeddedartists 0:bd0fe2412980 181 do {
embeddedartists 0:bd0fe2412980 182
embeddedartists 0:bd0fe2412980 183 // verify checksum
embeddedartists 0:bd0fe2412980 184 if (len < 3 || (len > 3 && data[len-3] != '*')) {
embeddedartists 0:bd0fe2412980 185 // invalid data
embeddedartists 0:bd0fe2412980 186 break;
embeddedartists 0:bd0fe2412980 187 }
embeddedartists 0:bd0fe2412980 188 int sum = strtol(&data[len-2], NULL, 16);
embeddedartists 0:bd0fe2412980 189 for(int i = 1; i < len-3; i++) {
embeddedartists 0:bd0fe2412980 190 sum ^= data[i];
embeddedartists 0:bd0fe2412980 191 }
embeddedartists 0:bd0fe2412980 192 if (sum != 0) {
embeddedartists 0:bd0fe2412980 193 // invalid checksum
embeddedartists 0:bd0fe2412980 194 break;
embeddedartists 0:bd0fe2412980 195 }
embeddedartists 0:bd0fe2412980 196
embeddedartists 0:bd0fe2412980 197
embeddedartists 0:bd0fe2412980 198 if (strncmp("$GPGGA", data, 6) == 0 && (_sentenceMask & NmeaGga) != 0) {
embeddedartists 0:bd0fe2412980 199 parseGGA(data, len);
embeddedartists 0:bd0fe2412980 200 _availDataType = NmeaGga;
embeddedartists 0:bd0fe2412980 201 _dataCallback.call();
embeddedartists 0:bd0fe2412980 202 _availDataType = NmeaInvalid;
embeddedartists 0:bd0fe2412980 203 }
embeddedartists 0:bd0fe2412980 204 else if (strncmp("$GPVTG", data, 6) == 0 && (_sentenceMask & NmeaVtg) != 0) {
embeddedartists 0:bd0fe2412980 205 parseVTG(data, len);
embeddedartists 0:bd0fe2412980 206 _availDataType = NmeaVtg;
embeddedartists 0:bd0fe2412980 207 _dataCallback.call();
embeddedartists 0:bd0fe2412980 208 _availDataType = NmeaInvalid;
embeddedartists 0:bd0fe2412980 209 }
embeddedartists 0:bd0fe2412980 210
embeddedartists 0:bd0fe2412980 211
embeddedartists 0:bd0fe2412980 212 } while(0);
embeddedartists 0:bd0fe2412980 213 }
embeddedartists 0:bd0fe2412980 214
embeddedartists 0:bd0fe2412980 215 void MTK3339::uartIrq() {
embeddedartists 0:bd0fe2412980 216 char d = 0;
embeddedartists 0:bd0fe2412980 217
embeddedartists 0:bd0fe2412980 218 while(_serial.readable()) {
embeddedartists 0:bd0fe2412980 219 d = _serial.getc();
embeddedartists 0:bd0fe2412980 220
embeddedartists 0:bd0fe2412980 221 switch(_state) {
embeddedartists 0:bd0fe2412980 222 case StateStart:
embeddedartists 0:bd0fe2412980 223 if (d == '$') {
embeddedartists 0:bd0fe2412980 224 _buf[0] = '$';
embeddedartists 0:bd0fe2412980 225 _bufPos = 1;
embeddedartists 0:bd0fe2412980 226 _state = StateData;
embeddedartists 0:bd0fe2412980 227 }
embeddedartists 0:bd0fe2412980 228 break;
embeddedartists 0:bd0fe2412980 229 case StateData:
embeddedartists 0:bd0fe2412980 230 if (_bufPos >= MTK3339_BUF_SZ) {
embeddedartists 0:bd0fe2412980 231 // error
embeddedartists 0:bd0fe2412980 232 _state = StateStart;
embeddedartists 0:bd0fe2412980 233 }
embeddedartists 0:bd0fe2412980 234 else if (d == '\r') {
embeddedartists 0:bd0fe2412980 235
embeddedartists 0:bd0fe2412980 236 _buf[_bufPos] = 0;
embeddedartists 0:bd0fe2412980 237
embeddedartists 0:bd0fe2412980 238 parseData(_buf, _bufPos);
embeddedartists 0:bd0fe2412980 239
embeddedartists 0:bd0fe2412980 240 _state = StateStart;
embeddedartists 0:bd0fe2412980 241 }
embeddedartists 0:bd0fe2412980 242 else {
embeddedartists 0:bd0fe2412980 243 _buf[_bufPos++] = d;
embeddedartists 0:bd0fe2412980 244 }
embeddedartists 0:bd0fe2412980 245
embeddedartists 0:bd0fe2412980 246 break;
embeddedartists 0:bd0fe2412980 247 }
embeddedartists 0:bd0fe2412980 248 }
embeddedartists 0:bd0fe2412980 249 }