From d1c93e04a7d0d28f7e9cecf0ddf058e4361962b8 Mon Sep 17 00:00:00 2001 From: Rick Sellens Date: Sun, 19 Jan 2020 07:43:48 -0500 Subject: [PATCH] Move parse and build to their own source files --- src/Adafruit_GPS.cpp | 362 ------------------------------------------- src/NMEA_build.cpp | 196 +++++++++++++++++++++++ src/NMEA_parse.cpp | 232 +++++++++++++++++++++++++++ 3 files changed, 428 insertions(+), 362 deletions(-) create mode 100644 src/NMEA_build.cpp create mode 100644 src/NMEA_parse.cpp diff --git a/src/Adafruit_GPS.cpp b/src/Adafruit_GPS.cpp index 6315222..ddc7494 100644 --- a/src/Adafruit_GPS.cpp +++ b/src/Adafruit_GPS.cpp @@ -32,206 +32,6 @@ static boolean strStartsWith(const char *str, const char *prefix); -/**************************************************************************/ -/*! - @brief Parse a NMEA string - @param nmea Pointer to the NMEA string - @return True if we parsed it, false if it has an invalid checksum or invalid - data -*/ -/**************************************************************************/ -boolean Adafruit_GPS::parse(char *nmea) { - // do checksum check - if (!check(nmea)) - return false; - // passed the check, so there's a valid source in thisSource and a valid - // sentence in thisSentence - - // look for a few common sentences - char *p = nmea; // Pointer to move through the sentence -- good parsers are - // non-destructive - p = strchr(p, ',') + - 1; // Skip to the character after the next comma, then check sentence. - - if (!strcmp(thisSentence, "GGA")) { - // found GGA - // get time - parseTime(p); - - // parse out latitude - p = strchr(p, ',') + 1; - parseLat(p); - p = strchr(p, ',') + 1; - if (!parseLatDir(p)) - return false; - - // parse out longitude - p = strchr(p, ',') + 1; - parseLon(p); - p = strchr(p, ',') + 1; - if (!parseLonDir(p)) - return false; - - p = strchr(p, ',') + 1; - if (!isEmpty(p)) { - fixquality = atoi(p); - if (fixquality > 0) { - fix = true; - lastFix = sentTime; - } else - fix = false; - } - - p = strchr(p, ',') + 1; - if (!isEmpty(p)) { - satellites = atoi(p); - } - - p = strchr(p, ',') + 1; - if (!isEmpty(p)) { - HDOP = atof(p); - } - - p = strchr(p, ',') + 1; - if (!isEmpty(p)) { - altitude = atof(p); - } - - p = strchr(p, ',') + 1; - p = strchr(p, ',') + 1; - if (!isEmpty(p)) { - geoidheight = atof(p); - } - } - - else if (!strcmp(thisSentence, "RMC")) { - // found RMC - // get time - parseTime(p); - - // fix or no fix - p = strchr(p, ',') + 1; - if (!parseFix(p)) - return false; - - // parse out latitude - p = strchr(p, ',') + 1; - parseLat(p); - p = strchr(p, ',') + 1; - if (!parseLatDir(p)) - return false; - - // parse out longitude - p = strchr(p, ',') + 1; - parseLon(p); - p = strchr(p, ',') + 1; - if (!parseLonDir(p)) - return false; - - // speed - p = strchr(p, ',') + 1; - if (!isEmpty(p)) { - speed = atof(p); - } - - // angle - p = strchr(p, ',') + 1; - if (!isEmpty(p)) { - angle = atof(p); - } - - p = strchr(p, ',') + 1; - if (!isEmpty(p)) { - uint32_t fulldate = atof(p); - day = fulldate / 10000; - month = (fulldate % 10000) / 100; - year = (fulldate % 100); - lastDate = sentTime; - } - } - - else if (!strcmp(thisSentence, "GLL")) { - // found GLL - // parse out latitude - parseLat(p); - p = strchr(p, ',') + 1; - if (!parseLatDir(p)) - return false; - - // parse out longitude - p = strchr(p, ',') + 1; - parseLon(p); - p = strchr(p, ',') + 1; - if (!parseLonDir(p)) - return false; - - // get time - p = strchr(p, ',') + 1; - parseTime(p); - - // fix or no fix - p = strchr(p, ',') + 1; - if (!parseFix(p)) - return false; - } - - else if (!strcmp(thisSentence, "GSA")) { - // found GSA - // parse out Auto selection, but ignore them - // parse out 3d fixquality - p = strchr(p, ',') + 1; - if (!isEmpty(p)) { - fixquality_3d = atoi(p); - } - // skip 12 Satellite PDNs without interpreting them - for (int i = 0; i < 12; i++) - p = strchr(p, ',') + 1; - - // parse out PDOP - p = strchr(p, ',') + 1; - if (!isEmpty(p)) { - PDOP = atof(p); - } - // parse out HDOP, we also parse this from the GGA sentence. Chipset should - // report the same for both - p = strchr(p, ',') + 1; - if (!isEmpty(p)) { - HDOP = atof(p); - } - // parse out VDOP - p = strchr(p, ',') + 1; - if (!isEmpty(p)) { - VDOP = atof(p); - } - } - -#ifdef NMEA_EXTENSIONS // Sentences not required for basic GPS functionality - else if (!strcmp(thisSentence, "TXT")) { //*******************************TXT - if (!isEmpty(p)) - txtTot = atoi(p); - p = strchr(p, ',') + 1; - if (!isEmpty(p)) - txtN = atoi(p); - p = strchr(p, ',') + 1; - if (!isEmpty(p)) - txtID = atoi(p); - p = strchr(p, ',') + 1; - if (!isEmpty(p)) - parseStr(txtTXT, p, 61); // copy the text to NMEA TXT max of 61 characters - } -#endif // NMEA_EXTENSIONS - - // we dont parse the remaining, yet! - else - return false; - - // Record the successful parsing of where the last data came from and when - strcpy(lastSource, thisSource); - strcpy(lastSentence, thisSentence); - lastUpdate = millis(); - return true; -} - /**************************************************************************/ /*! @brief Check an NMEA string for basic format, valid source ID and valid @@ -1055,166 +855,4 @@ static boolean strStartsWith(const char *str, const char *prefix) { /**************************************************************************/ void Adafruit_GPS::resetSentTime() { sentTime = millis(); } -/**************************************************************************/ -/*! - @brief Build an NMEA sentence string based on the relevant variables. - Sentences start with a $, then a two character source identifier, then - a three character sentence name that defines the format, then a comma - and more comma separated fields defined by the sentence name. There are - many sentences listed that are not yet supported. Most of these sentence - definitions were found at http://fort21.ru/download/NMEAdescription.pdf - - build() will work with other lengths for source and sentence to allow - extension to building proprietary sentences like $PMTK220,100*2F. - - build() will not work properly in an environment that does not support - the %f floating point formatter in sprintf(), and will return NULL. - - build() adds Carriage Return and Line Feed to sentences to conform to - NMEA-183, so send your output with a print, not a println. - - Some of the data in these test sentences may be arbitrary, e.g. for the - TXT sentence which has a more complicated protocol for multiple lines - sent as a message set. Also, the data in the class variables are presumed - to be valid, so these sentences may contain values that are stale, or - the result of initialization rather than measurement. - - @param nmea Pointer to the NMEA string buffer. Must be big enough to - hold the sentence. No guarantee what will be in it if the - building of the sentence fails. - @param thisSource Pointer to the source name string (2 upper case) - @param thisSentence Pointer to the sentence name string (3 upper case) - @param ref Reference for the sentence, usually relative (R) or true (T) - @return Pointer to sentence if successful, NULL if fails -*/ -/**************************************************************************/ -char *Adafruit_GPS::build(char *nmea, const char *thisSource, - const char *thisSentence, char ref) { - sprintf(nmea, "%6.2f", 123.45); // fail if sprintf() doesn't handle floats - if (strcmp(nmea, "123.45")) - return NULL; - *nmea = '$'; - char *p = nmea + 1; // Pointer to move through the sentence - strncpy(p, thisSource, strlen(thisSource)); - p += strlen(thisSource); - strncpy(p, thisSentence, strlen(thisSentence)); - p += strlen(thisSentence); - *p = ','; - p += 1; // Now $XXSSS, and need to add argument fields - // This may look inefficient, but an M0 will get down the list in about 1 us / - // strcmp()! Put the GPS sentences from Adafruit_GPS at the top to make - // pruning excess code easier. Otherwise, keep them alphabetical for ease of - // reading. - - if (!strcmp(thisSentence, - "GGA")) { //********************************************GGA - // GGA Global Positioning System Fix Data. Time, Position and fix related - // data for a GPS receiver - // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - // | | | | | | | | | | | | | | | - //$--GGA,hhmmss.ss,ddmm.mm,a,dddmm.mm,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh - // 1) Time (UTC) - // 2) Latitude - // 3) N or S (North or South) - // 4) Longitude - // 5) E or W (East or West) - // 6) GPS Quality Indicator, 0 - fix not available, 1 - GPS fix, 2 - - // Differential GPS fix 7) Number of satellites in view, 00 - 12 8) - // Horizontal Dilution of precision 9) Antenna Altitude above/below - // mean-sea-level (geoid) 10) Units of antenna altitude, meters 11) Geoidal - // separation, the difference between the WGS-84 earth - // ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level below - // ellipsoid - // 12) Units of geoidal separation, meters - // 13) Age of differential GPS data, time in seconds since last SC104 - // type 1 or 9 update, null field when DGPS is not used - // 14) Differential reference station ID, 0000-1023 - // 15) Checksum - sprintf(p, "%09.2f,%09.4f,%c,%010.4f,%c,%d,%02d,%f,%f,M,%f,M,,", - hour * 10000L + minute * 100L + seconds + milliseconds / 1000., - latitude, lat, longitude, lon, fixquality, satellites, HDOP, - altitude, geoidheight); - - } else if (!strcmp(thisSentence, - "GLL")) { //********************************************GLL - // GLL Geographic Position – Latitude/Longitude - // 1 2 3 4 5 6 7 - // | | | | | | | - //$--GLL,llll.ll,a,yyyyy.yy,a,hhmmss.ss,A*hh - // 1) Latitude ddmm.mm format - // 2) N or S (North or South) - // 3) Longitude dddmm.mm format - // 4) E or W (East or West) - // 5) Time (UTC) - // 6) Status A - Data Valid, V - Data Invalid - // 7) Checksum - sprintf(p, "%09.4f,%c,%010.4f,%c,%09.2f,A", latitude, lat, longitude, lon, - hour * 10000L + minute * 100L + seconds + milliseconds / 1000.); - - } else if (!strcmp(thisSentence, - "GSA")) { //******************************************** - // GSA GPS DOP and active satellites - // 1 2 3 14 15 16 17 18 - // | | | | | | | | - //$--GSA,a,a,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x.x,x.x,x.x*hh - // 1) Selection mode - // 2) Mode - // 3) ID of 1st satellite used for fix - // 4) ID of 2nd satellite used for fix - // ... - // 14) ID of 12th satellite used for fix - // 15) PDOP in meters - // 16) HDOP in meters - // 17) VDOP in meters - // 18) Checksum - return NULL; - - } else if (!strcmp(thisSentence, - "RMC")) { //********************************************RMC - // RMC Recommended Minimum Navigation Information - // 12 - // 1 2 3 4 5 6 7 8 9 10 11 | - // | | | | | | | | | | | | - //$--RMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,xxxxxx,x.x,a*hh - // 1) Time (UTC) - // 2) Status, V = Navigation receiver warning - // 3) Latitude - // 4) N or S - // 5) Longitude - // 6) E or W - // 7) Speed over ground, knots - // 8) Track made good, degrees true - // 9) Date, ddmmyy - // 10) Magnetic Variation, degrees - // 11) E or W - // 12) Checksum - sprintf(p, "%09.2f,A,%09.4f,%c,%010.4f,%c,%f,%f,%06d,%f,%c", - hour * 10000L + minute * 100L + seconds + milliseconds / 1000., - latitude, lat, longitude, lon, speed, angle, - day * 10000 + month * 100 + year, magvariation, mag); - - } else if (!strcmp(thisSentence, - "TXT")) { //********************************************TXT - // as mentioned in https://github.com/adafruit/Adafruit_GPS/issues/95 - // TXT Text Transmission - // 1 2 3 4 5 - // | | | | | - //$--TXT,xx,xx,xx,c--c*hh - // 1) Total Number of Sentences 01-99 - // 2) Sentence Number 01-99 - // 3) Text Identifier 01-99 - // 4) Text String, max 61 characters - // 5) Checksum - sprintf(p, "01,01,23,This is the text of the sample message"); - - } else { - return NULL; // didn't find a match for the build request - } - - addChecksum(nmea); // Successful completion - sprintf(nmea, "%s\r\n", - nmea); // Add Carriage Return and Line Feed to comply with NMEA-183 - return nmea; // return pointer to finished product -} - #endif // NMEA_EXTENSIONS diff --git a/src/NMEA_build.cpp b/src/NMEA_build.cpp new file mode 100644 index 0000000..7ca1e25 --- /dev/null +++ b/src/NMEA_build.cpp @@ -0,0 +1,196 @@ +/**************************************************************************/ +/*! + @file NMEA_build.cpp + + @mainpage Adafruit Ultimate GPS Breakout + + @section intro Introduction + + This is the Adafruit GPS library - the ultimate GPS library + for the ultimate GPS module! + + Tested and works great with the Adafruit Ultimate GPS module + using MTK33x9 chipset + ------> http://www.adafruit.com/products/746 + + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + @section author Author + + Written by Limor Fried/Ladyada for Adafruit Industries. + + @section license License + + BSD license, check license.txt for more information + All text above must be included in any redistribution +*/ +/**************************************************************************/ + +#include + +#ifdef NMEA_EXTENSIONS +/**************************************************************************/ +/*! + @brief Build an NMEA sentence string based on the relevant variables. + Sentences start with a $, then a two character source identifier, then + a three character sentence name that defines the format, then a comma + and more comma separated fields defined by the sentence name. There are + many sentences listed that are not yet supported. Most of these sentence + definitions were found at http://fort21.ru/download/NMEAdescription.pdf + + build() will work with other lengths for source and sentence to allow + extension to building proprietary sentences like $PMTK220,100*2F. + + build() will not work properly in an environment that does not support + the %f floating point formatter in sprintf(), and will return NULL. + + build() adds Carriage Return and Line Feed to sentences to conform to + NMEA-183, so send your output with a print, not a println. + + Some of the data in these test sentences may be arbitrary, e.g. for the + TXT sentence which has a more complicated protocol for multiple lines + sent as a message set. Also, the data in the class variables are presumed + to be valid, so these sentences may contain values that are stale, or + the result of initialization rather than measurement. + + @param nmea Pointer to the NMEA string buffer. Must be big enough to + hold the sentence. No guarantee what will be in it if the + building of the sentence fails. + @param thisSource Pointer to the source name string (2 upper case) + @param thisSentence Pointer to the sentence name string (3 upper case) + @param ref Reference for the sentence, usually relative (R) or true (T) + @return Pointer to sentence if successful, NULL if fails +*/ +/**************************************************************************/ +char *Adafruit_GPS::build(char *nmea, const char *thisSource, + const char *thisSentence, char ref) { + sprintf(nmea, "%6.2f", 123.45); // fail if sprintf() doesn't handle floats + if (strcmp(nmea, "123.45")) + return NULL; + *nmea = '$'; + char *p = nmea + 1; // Pointer to move through the sentence + strncpy(p, thisSource, strlen(thisSource)); + p += strlen(thisSource); + strncpy(p, thisSentence, strlen(thisSentence)); + p += strlen(thisSentence); + *p = ','; + p += 1; // Now $XXSSS, and need to add argument fields + // This may look inefficient, but an M0 will get down the list in about 1 us / + // strcmp()! Put the GPS sentences from Adafruit_GPS at the top to make + // pruning excess code easier. Otherwise, keep them alphabetical for ease of + // reading. + + if (!strcmp(thisSentence, + "GGA")) { //********************************************GGA + // GGA Global Positioning System Fix Data. Time, Position and fix related + // data for a GPS receiver + // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + // | | | | | | | | | | | | | | | + //$--GGA,hhmmss.ss,ddmm.mm,a,dddmm.mm,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh + // 1) Time (UTC) + // 2) Latitude + // 3) N or S (North or South) + // 4) Longitude + // 5) E or W (East or West) + // 6) GPS Quality Indicator, 0 - fix not available, 1 - GPS fix, 2 - + // Differential GPS fix 7) Number of satellites in view, 00 - 12 8) + // Horizontal Dilution of precision 9) Antenna Altitude above/below + // mean-sea-level (geoid) 10) Units of antenna altitude, meters 11) Geoidal + // separation, the difference between the WGS-84 earth + // ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level below + // ellipsoid + // 12) Units of geoidal separation, meters + // 13) Age of differential GPS data, time in seconds since last SC104 + // type 1 or 9 update, null field when DGPS is not used + // 14) Differential reference station ID, 0000-1023 + // 15) Checksum + sprintf(p, "%09.2f,%09.4f,%c,%010.4f,%c,%d,%02d,%f,%f,M,%f,M,,", + hour * 10000L + minute * 100L + seconds + milliseconds / 1000., + latitude, lat, longitude, lon, fixquality, satellites, HDOP, + altitude, geoidheight); + + } else if (!strcmp(thisSentence, + "GLL")) { //********************************************GLL + // GLL Geographic Position – Latitude/Longitude + // 1 2 3 4 5 6 7 + // | | | | | | | + //$--GLL,llll.ll,a,yyyyy.yy,a,hhmmss.ss,A*hh + // 1) Latitude ddmm.mm format + // 2) N or S (North or South) + // 3) Longitude dddmm.mm format + // 4) E or W (East or West) + // 5) Time (UTC) + // 6) Status A - Data Valid, V - Data Invalid + // 7) Checksum + sprintf(p, "%09.4f,%c,%010.4f,%c,%09.2f,A", latitude, lat, longitude, lon, + hour * 10000L + minute * 100L + seconds + milliseconds / 1000.); + + } else if (!strcmp(thisSentence, + "GSA")) { //******************************************** + // GSA GPS DOP and active satellites + // 1 2 3 14 15 16 17 18 + // | | | | | | | | + //$--GSA,a,a,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x.x,x.x,x.x*hh + // 1) Selection mode + // 2) Mode + // 3) ID of 1st satellite used for fix + // 4) ID of 2nd satellite used for fix + // ... + // 14) ID of 12th satellite used for fix + // 15) PDOP in meters + // 16) HDOP in meters + // 17) VDOP in meters + // 18) Checksum + return NULL; + + } else if (!strcmp(thisSentence, + "RMC")) { //********************************************RMC + // RMC Recommended Minimum Navigation Information + // 12 + // 1 2 3 4 5 6 7 8 9 10 11 | + // | | | | | | | | | | | | + //$--RMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,xxxxxx,x.x,a*hh + // 1) Time (UTC) + // 2) Status, V = Navigation receiver warning + // 3) Latitude + // 4) N or S + // 5) Longitude + // 6) E or W + // 7) Speed over ground, knots + // 8) Track made good, degrees true + // 9) Date, ddmmyy + // 10) Magnetic Variation, degrees + // 11) E or W + // 12) Checksum + sprintf(p, "%09.2f,A,%09.4f,%c,%010.4f,%c,%f,%f,%06d,%f,%c", + hour * 10000L + minute * 100L + seconds + milliseconds / 1000., + latitude, lat, longitude, lon, speed, angle, + day * 10000 + month * 100 + year, magvariation, mag); + + } else if (!strcmp(thisSentence, + "TXT")) { //********************************************TXT + // as mentioned in https://github.com/adafruit/Adafruit_GPS/issues/95 + // TXT Text Transmission + // 1 2 3 4 5 + // | | | | | + //$--TXT,xx,xx,xx,c--c*hh + // 1) Total Number of Sentences 01-99 + // 2) Sentence Number 01-99 + // 3) Text Identifier 01-99 + // 4) Text String, max 61 characters + // 5) Checksum + sprintf(p, "01,01,23,This is the text of the sample message"); + + } else { + return NULL; // didn't find a match for the build request + } + + addChecksum(nmea); // Successful completion + sprintf(nmea, "%s\r\n", + nmea); // Add Carriage Return and Line Feed to comply with NMEA-183 + return nmea; // return pointer to finished product +} + +#endif // NMEA_EXTENSIONS diff --git a/src/NMEA_parse.cpp b/src/NMEA_parse.cpp new file mode 100644 index 0000000..120a4bd --- /dev/null +++ b/src/NMEA_parse.cpp @@ -0,0 +1,232 @@ +/**************************************************************************/ +/*! + @file NMEA_parse.cpp + + @mainpage Adafruit Ultimate GPS Breakout + + @section intro Introduction + + This is the Adafruit GPS library - the ultimate GPS library + for the ultimate GPS module! + + Tested and works great with the Adafruit Ultimate GPS module + using MTK33x9 chipset + ------> http://www.adafruit.com/products/746 + + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + @section author Author + + Written by Limor Fried/Ladyada for Adafruit Industries. + + @section license License + + BSD license, check license.txt for more information + All text above must be included in any redistribution +*/ +/**************************************************************************/ + +#include + +/**************************************************************************/ +/*! + @brief Parse a NMEA string + @param nmea Pointer to the NMEA string + @return True if we parsed it, false if it has an invalid checksum or invalid + data +*/ +/**************************************************************************/ +boolean Adafruit_GPS::parse(char *nmea) { + // do checksum check + if (!check(nmea)) + return false; + // passed the check, so there's a valid source in thisSource and a valid + // sentence in thisSentence + + // look for a few common sentences + char *p = nmea; // Pointer to move through the sentence -- good parsers are + // non-destructive + p = strchr(p, ',') + + 1; // Skip to the character after the next comma, then check sentence. + + if (!strcmp(thisSentence, "GGA")) { + // found GGA + // get time + parseTime(p); + + // parse out latitude + p = strchr(p, ',') + 1; + parseLat(p); + p = strchr(p, ',') + 1; + if (!parseLatDir(p)) + return false; + + // parse out longitude + p = strchr(p, ',') + 1; + parseLon(p); + p = strchr(p, ',') + 1; + if (!parseLonDir(p)) + return false; + + p = strchr(p, ',') + 1; + if (!isEmpty(p)) { + fixquality = atoi(p); + if (fixquality > 0) { + fix = true; + lastFix = sentTime; + } else + fix = false; + } + + p = strchr(p, ',') + 1; + if (!isEmpty(p)) { + satellites = atoi(p); + } + + p = strchr(p, ',') + 1; + if (!isEmpty(p)) { + HDOP = atof(p); + } + + p = strchr(p, ',') + 1; + if (!isEmpty(p)) { + altitude = atof(p); + } + + p = strchr(p, ',') + 1; + p = strchr(p, ',') + 1; + if (!isEmpty(p)) { + geoidheight = atof(p); + } + } + + else if (!strcmp(thisSentence, "RMC")) { + // found RMC + // get time + parseTime(p); + + // fix or no fix + p = strchr(p, ',') + 1; + if (!parseFix(p)) + return false; + + // parse out latitude + p = strchr(p, ',') + 1; + parseLat(p); + p = strchr(p, ',') + 1; + if (!parseLatDir(p)) + return false; + + // parse out longitude + p = strchr(p, ',') + 1; + parseLon(p); + p = strchr(p, ',') + 1; + if (!parseLonDir(p)) + return false; + + // speed + p = strchr(p, ',') + 1; + if (!isEmpty(p)) { + speed = atof(p); + } + + // angle + p = strchr(p, ',') + 1; + if (!isEmpty(p)) { + angle = atof(p); + } + + p = strchr(p, ',') + 1; + if (!isEmpty(p)) { + uint32_t fulldate = atof(p); + day = fulldate / 10000; + month = (fulldate % 10000) / 100; + year = (fulldate % 100); + lastDate = sentTime; + } + } + + else if (!strcmp(thisSentence, "GLL")) { + // found GLL + // parse out latitude + parseLat(p); + p = strchr(p, ',') + 1; + if (!parseLatDir(p)) + return false; + + // parse out longitude + p = strchr(p, ',') + 1; + parseLon(p); + p = strchr(p, ',') + 1; + if (!parseLonDir(p)) + return false; + + // get time + p = strchr(p, ',') + 1; + parseTime(p); + + // fix or no fix + p = strchr(p, ',') + 1; + if (!parseFix(p)) + return false; + } + + else if (!strcmp(thisSentence, "GSA")) { + // found GSA + // parse out Auto selection, but ignore them + // parse out 3d fixquality + p = strchr(p, ',') + 1; + if (!isEmpty(p)) { + fixquality_3d = atoi(p); + } + // skip 12 Satellite PDNs without interpreting them + for (int i = 0; i < 12; i++) + p = strchr(p, ',') + 1; + + // parse out PDOP + p = strchr(p, ',') + 1; + if (!isEmpty(p)) { + PDOP = atof(p); + } + // parse out HDOP, we also parse this from the GGA sentence. Chipset should + // report the same for both + p = strchr(p, ',') + 1; + if (!isEmpty(p)) { + HDOP = atof(p); + } + // parse out VDOP + p = strchr(p, ',') + 1; + if (!isEmpty(p)) { + VDOP = atof(p); + } + } + +#ifdef NMEA_EXTENSIONS // Sentences not required for basic GPS functionality + else if (!strcmp(thisSentence, "TXT")) { //*******************************TXT + if (!isEmpty(p)) + txtTot = atoi(p); + p = strchr(p, ',') + 1; + if (!isEmpty(p)) + txtN = atoi(p); + p = strchr(p, ',') + 1; + if (!isEmpty(p)) + txtID = atoi(p); + p = strchr(p, ',') + 1; + if (!isEmpty(p)) + parseStr(txtTXT, p, 61); // copy the text to NMEA TXT max of 61 characters + } +#endif // NMEA_EXTENSIONS + + // we dont parse the remaining, yet! + else + return false; + + // Record the successful parsing of where the last data came from and when + strcpy(lastSource, thisSource); + strcpy(lastSentence, thisSentence); + lastUpdate = millis(); + return true; +} +