diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml new file mode 100644 index 0000000..3ad404b --- /dev/null +++ b/.github/workflows/githubci.yml @@ -0,0 +1,32 @@ +name: Arduino Library CI + +on: [pull_request, push, repository_dispatch] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/setup-python@v1 + with: + python-version: '3.x' + - uses: actions/checkout@v2 + - uses: actions/checkout@v2 + with: + repository: adafruit/ci-arduino + path: ci + + - name: pre-install + run: bash ci/actions_install.sh + + - name: test platforms + run: python3 ci/build_platform.py main_platforms + + - name: clang + run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r . + + - name: doxygen + env: + GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }} + PRETTYNAME : "Adafruit GPS Library" + run: bash ci/doxy_gen_and_deploy.sh diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 2f8075b..0000000 --- a/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ -language: c -sudo: false -# Blacklist -branches: - except: - - gh-pages -cache: - directories: - - ~/arduino_ide - - ~/.arduino15/packages/ -git: - depth: false - quiet: true -env: - global: - - PRETTYNAME="Adafruit GPS" -# Optional, will default to "$TRAVIS_BUILD_DIR/Doxyfile" -# - DOXYFILE: $TRAVIS_BUILD_DIR/Doxyfile - -before_install: - - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh) - -script: - - build_main_platforms - -# Generate and deploy documentation -after_success: - - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/library_check.sh) - - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/doxy_gen_and_deploy.sh) diff --git a/Adafruit_GPS.cpp b/Adafruit_GPS.cpp index 2cf809e..38c8f27 100755 --- a/Adafruit_GPS.cpp +++ b/Adafruit_GPS.cpp @@ -30,116 +30,118 @@ #include -static boolean strStartsWith(const char* str, const char* prefix); +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 + @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 + 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. + 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")) { + if (!strcmp(thisSentence, "GGA")) { // found GGA // get time parseTime(p); // parse out latitude - p = strchr(p, ',')+1; + p = strchr(p, ',') + 1; parseLat(p); - p = strchr(p, ',')+1; - if(!parseLatDir(p)) return false; + p = strchr(p, ',') + 1; + if (!parseLatDir(p)) + return false; // parse out longitude - p = strchr(p, ',')+1; + p = strchr(p, ',') + 1; parseLon(p); - p = strchr(p, ',')+1; - if(!parseLonDir(p)) return false; + p = strchr(p, ',') + 1; + if (!parseLonDir(p)) + return false; - p = strchr(p, ',')+1; - if (',' != *p) - { + p = strchr(p, ',') + 1; + if (',' != *p) { fixquality = atoi(p); - if(fixquality > 0){ + if (fixquality > 0) { fix = true; lastFix = sentTime; } else fix = false; } - p = strchr(p, ',')+1; - if (',' != *p) - { + p = strchr(p, ',') + 1; + if (',' != *p) { satellites = atoi(p); } - p = strchr(p, ',')+1; - if (',' != *p) - { + p = strchr(p, ',') + 1; + if (',' != *p) { HDOP = atof(p); } - p = strchr(p, ',')+1; - if (',' != *p) - { + p = strchr(p, ',') + 1; + if (',' != *p) { altitude = atof(p); } - p = strchr(p, ',')+1; - p = strchr(p, ',')+1; - if (',' != *p) - { + p = strchr(p, ',') + 1; + p = strchr(p, ',') + 1; + if (',' != *p) { geoidheight = atof(p); } - } + } - else if (!strcmp(thisSentence,"RMC")) { + else if (!strcmp(thisSentence, "RMC")) { // found RMC // get time parseTime(p); // fix or no fix - p = strchr(p, ',')+1; - if(!parseFix(p)) return false; + p = strchr(p, ',') + 1; + if (!parseFix(p)) + return false; // parse out latitude - p = strchr(p, ',')+1; + p = strchr(p, ',') + 1; parseLat(p); - p = strchr(p, ',')+1; - if(!parseLatDir(p)) return false; + p = strchr(p, ',') + 1; + if (!parseLatDir(p)) + return false; // parse out longitude - p = strchr(p, ',')+1; + p = strchr(p, ',') + 1; parseLon(p); - p = strchr(p, ',')+1; - if(!parseLonDir(p)) return false; + p = strchr(p, ',') + 1; + if (!parseLonDir(p)) + return false; // speed - p = strchr(p, ',')+1; - if (',' != *p) - { + p = strchr(p, ',') + 1; + if (',' != *p) { speed = atof(p); } // angle - p = strchr(p, ',')+1; - if (',' != *p) - { + p = strchr(p, ',') + 1; + if (',' != *p) { angle = atof(p); } - p = strchr(p, ',')+1; - if (',' != *p) - { + p = strchr(p, ',') + 1; + if (',' != *p) { uint32_t fulldate = atof(p); day = fulldate / 10000; month = (fulldate % 10000) / 100; @@ -148,119 +150,130 @@ boolean Adafruit_GPS::parse(char *nmea) { } } - else if (!strcmp(thisSentence,"GLL")) { + else if (!strcmp(thisSentence, "GLL")) { // found GLL // parse out latitude parseLat(p); - p = strchr(p, ',')+1; - if(!parseLatDir(p)) return false; + p = strchr(p, ',') + 1; + if (!parseLatDir(p)) + return false; // parse out longitude - p = strchr(p, ',')+1; + p = strchr(p, ',') + 1; parseLon(p); - p = strchr(p, ',')+1; - if(!parseLonDir(p)) return false; + p = strchr(p, ',') + 1; + if (!parseLonDir(p)) + return false; // get time - p = strchr(p, ',')+1; + p = strchr(p, ',') + 1; parseTime(p); // fix or no fix - p = strchr(p, ',')+1; - if(!parseFix(p)) return false; + p = strchr(p, ',') + 1; + if (!parseFix(p)) + return false; } - else if (!strcmp(thisSentence,"GSA")) { + else if (!strcmp(thisSentence, "GSA")) { // found GSA // parse out Auto selection, but ignore them // parse out 3d fixquality - p = strchr(p, ',')+1; - if (',' != *p) - { + p = strchr(p, ',') + 1; + if (',' != *p) { fixquality_3d = atoi(p); } // skip 12 Satellite PDNs without interpreting them - for(int i = 0;i < 12;i++) p = strchr(p, ',')+1; + for (int i = 0; i < 12; i++) + p = strchr(p, ',') + 1; - //parse out PDOP - p = strchr(p, ',')+1; - if (',' != *p) - { + // parse out PDOP + p = strchr(p, ',') + 1; + if (',' != *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 (',' != *p) - { + // parse out HDOP, we also parse this from the GGA sentence. Chipset should + // report the same for both + p = strchr(p, ',') + 1; + if (',' != *p) { HDOP = atof(p); } // parse out VDOP - p = strchr(p, ',')+1; - if (',' != *p) - { + p = strchr(p, ',') + 1; + if (',' != *p) { VDOP = atof(p); } } - // we dont parse the remaining, yet! - else return false; - + else + return false; + // Record the successful parsing of where the last data came from and when - strcpy(lastSource,thisSource); - strcpy(lastSentence,thisSentence); + strcpy(lastSource, thisSource); + strcpy(lastSentence, thisSentence); lastUpdate = millis(); - return true; + return true; } /**************************************************************************/ /*! @brief Check an NMEA string for basic format, valid source ID and valid - and valid sentence ID. Update the values of thisCheck, thisSource and - thisSentence. + and valid sentence ID. Update the values of thisCheck, thisSource and + thisSentence. @param nmea Pointer to the NMEA string @return True if well formed, false if it has problems */ /**************************************************************************/ boolean Adafruit_GPS::check(char *nmea) { - thisCheck = 0; // new check - if(*nmea != '$') return false; // doesn't start with $ - else thisCheck += NMEA_HAS_DOLLAR; - // do checksum check -- first look if we even have one -- ignore all but last * - char *ast = nmea; // not strchr(nmea,'*'); for first * - while(*ast) ast++; // go to the end - while(*ast != '*' && ast > nmea) ast--; // then back to * if it's there - if (*ast != '*') return false; // there is no asterisk + thisCheck = 0; // new check + if (*nmea != '$') + return false; // doesn't start with $ + else + thisCheck += NMEA_HAS_DOLLAR; + // do checksum check -- first look if we even have one -- ignore all but last + // * + char *ast = nmea; // not strchr(nmea,'*'); for first * + while (*ast) + ast++; // go to the end + while (*ast != '*' && ast > nmea) + ast--; // then back to * if it's there + if (*ast != '*') + return false; // there is no asterisk else { - uint16_t sum = parseHex(*(ast+1)) * 16; // extract checksum - sum += parseHex(*(ast+2)); - char *p = nmea; // check checksum - for (char *p1 = p+1; p1 < ast; p1++) sum ^= *p1; - if (sum != 0) return false; // bad checksum :( - else thisCheck += NMEA_HAS_CHECKSUM; + uint16_t sum = parseHex(*(ast + 1)) * 16; // extract checksum + sum += parseHex(*(ast + 2)); + char *p = nmea; // check checksum + for (char *p1 = p + 1; p1 < ast; p1++) + sum ^= *p1; + if (sum != 0) + return false; // bad checksum :( + else + thisCheck += NMEA_HAS_CHECKSUM; } // extract source of variable length - char *p = nmea +1; - const char *src = tokenOnList(p,sources); - if(src){ - strcpy(thisSource,src); + char *p = nmea + 1; + const char *src = tokenOnList(p, sources); + if (src) { + strcpy(thisSource, src); thisCheck += NMEA_HAS_SOURCE; - } else return false; + } else + return false; p += strlen(src); // extract sentence id and check if parsed - const char *snc = tokenOnList(p,sentences_parsed); - if(snc){ - strcpy(thisSentence,snc); + const char *snc = tokenOnList(p, sentences_parsed); + if (snc) { + strcpy(thisSentence, snc); thisCheck += NMEA_HAS_SENTENCE_P + NMEA_HAS_SENTENCE; - } else { // check if known - snc = tokenOnList(p,sentences_known); - if(snc){ - strcpy(thisSentence,snc); + } else { // check if known + snc = tokenOnList(p, sentences_known); + if (snc) { + strcpy(thisSentence, snc); thisCheck += NMEA_HAS_SENTENCE; return false; - } + } } - return true; // passed all the tests + return true; // passed all the tests } /**************************************************************************/ @@ -271,35 +284,37 @@ boolean Adafruit_GPS::check(char *nmea) { @return Pointer to the found token, or NULL if it fails */ /**************************************************************************/ -const char * Adafruit_GPS::tokenOnList(char *token, const char **list) { - int i = 0; // index in the list - while(strncmp(list[i],"ZZ",2) && i < 1000){ // stop at terminator and don't crash without it +const char *Adafruit_GPS::tokenOnList(char *token, const char **list) { + int i = 0; // index in the list + while (strncmp(list[i], "ZZ", 2) && + i < 1000) { // stop at terminator and don't crash without it // test for a match on the sentence name - if(!strncmp((const char *)list[i],(const char *)token,strlen(list[i]))) return list[i]; + if (!strncmp((const char *)list[i], (const char *)token, strlen(list[i]))) + return list[i]; i++; } - return NULL; // couldn't find a match + return NULL; // couldn't find a match } /**************************************************************************/ /*! - @brief Add *CS where CS is the two character hex checksum for all but + @brief Add *CS where CS is the two character hex checksum for all but the first character in the string. The checksum is the result of an - exclusive or of all the characters in the string. Also useful if you + exclusive or of all the characters in the string. Also useful if you are creating new PMTK strings for controlling a GPS module and need a checksum added. - @param buff Pointer to the string, which must be long enough + @param buff Pointer to the string, which must be long enough @return none */ /**************************************************************************/ -void Adafruit_GPS::addChecksum(char *buff){ +void Adafruit_GPS::addChecksum(char *buff) { char cs = 0; int i = 1; - while(buff[i]){ + while (buff[i]) { cs ^= buff[i]; i++; } - sprintf(buff,"%s*%02X",buff,cs); + sprintf(buff, "%s*%02X", buff, cs); } /**************************************************************************/ @@ -309,15 +324,15 @@ void Adafruit_GPS::addChecksum(char *buff){ */ /**************************************************************************/ void Adafruit_GPS::parseTime(char *p) { - // get time - uint32_t time = atol(p); - hour = time / 10000; - minute = (time % 10000) / 100; - seconds = (time % 100); + // get time + uint32_t time = atol(p); + hour = time / 10000; + minute = (time % 10000) / 100; + seconds = (time % 100); - p = strchr(p, '.')+1; - milliseconds = atoi(p); - lastTime = sentTime; + p = strchr(p, '.') + 1; + milliseconds = atoi(p); + lastTime = sentTime; } /**************************************************************************/ @@ -330,22 +345,21 @@ void Adafruit_GPS::parseLat(char *p) { int32_t degree; long minutes; char degreebuff[10]; - if (',' != *p) - { - strncpy(degreebuff, p, 2); - p += 2; - degreebuff[2] = '\0'; - long degree = atol(degreebuff) * 10000000; - strncpy(degreebuff, p, 2); // minutes - p += 3; // skip decimal point - strncpy(degreebuff + 2, p, 4); - degreebuff[6] = '\0'; - long minutes = 50 * atol(degreebuff) / 3; - latitude_fixed = degree + minutes; - latitude = degree / 100000 + minutes * 0.000006F; - latitudeDegrees = (latitude-100*int(latitude/100))/60.0; - latitudeDegrees += int(latitude/100); - } + if (',' != *p) { + strncpy(degreebuff, p, 2); + p += 2; + degreebuff[2] = '\0'; + long degree = atol(degreebuff) * 10000000; + strncpy(degreebuff, p, 2); // minutes + p += 3; // skip decimal point + strncpy(degreebuff + 2, p, 4); + degreebuff[6] = '\0'; + long minutes = 50 * atol(degreebuff) / 3; + latitude_fixed = degree + minutes; + latitude = degree / 100000 + minutes * 0.000006F; + latitudeDegrees = (latitude - 100 * int(latitude / 100)) / 60.0; + latitudeDegrees += int(latitude / 100); + } } /**************************************************************************/ @@ -356,18 +370,18 @@ void Adafruit_GPS::parseLat(char *p) { */ /**************************************************************************/ boolean Adafruit_GPS::parseLatDir(char *p) { - if (p[0] == 'S') { - lat = 'S'; - latitudeDegrees *= -1.0; - latitude_fixed *= -1; - } else if (p[0] == 'N') { - lat = 'N'; - } else if (p[0] == ',') { - lat = 0; - } else { - return false; - } - return true; + if (p[0] == 'S') { + lat = 'S'; + latitudeDegrees *= -1.0; + latitude_fixed *= -1; + } else if (p[0] == 'N') { + lat = 'N'; + } else if (p[0] == ',') { + lat = 0; + } else { + return false; + } + return true; } /**************************************************************************/ @@ -380,22 +394,21 @@ void Adafruit_GPS::parseLon(char *p) { int32_t degree; long minutes; char degreebuff[10]; - if (',' != *p) - { - strncpy(degreebuff, p, 3); - p += 3; - degreebuff[3] = '\0'; - degree = atol(degreebuff) * 10000000; - strncpy(degreebuff, p, 2); // minutes - p += 3; // skip decimal point - strncpy(degreebuff + 2, p, 4); - degreebuff[6] = '\0'; - minutes = 50 * atol(degreebuff) / 3; - longitude_fixed = degree + minutes; - longitude = degree / 100000 + minutes * 0.000006F; - longitudeDegrees = (longitude-100*int(longitude/100))/60.0; - longitudeDegrees += int(longitude/100); - } + if (',' != *p) { + strncpy(degreebuff, p, 3); + p += 3; + degreebuff[3] = '\0'; + degree = atol(degreebuff) * 10000000; + strncpy(degreebuff, p, 2); // minutes + p += 3; // skip decimal point + strncpy(degreebuff + 2, p, 4); + degreebuff[6] = '\0'; + minutes = 50 * atol(degreebuff) / 3; + longitude_fixed = degree + minutes; + longitude = degree / 100000 + minutes * 0.000006F; + longitudeDegrees = (longitude - 100 * int(longitude / 100)) / 60.0; + longitudeDegrees += int(longitude / 100); + } } /**************************************************************************/ @@ -406,21 +419,20 @@ void Adafruit_GPS::parseLon(char *p) { */ /**************************************************************************/ boolean Adafruit_GPS::parseLonDir(char *p) { - if (',' != *p) - { - if (p[0] == 'W') { - lon = 'W'; - longitudeDegrees *= -1.0; - longitude_fixed *= -1; - } else if (p[0] == 'E') { - lon = 'E'; - } else if (p[0] == ',') { - lon = 0; - } else { - return false; - } + if (',' != *p) { + if (p[0] == 'W') { + lon = 'W'; + longitudeDegrees *= -1.0; + longitude_fixed *= -1; + } else if (p[0] == 'E') { + lon = 'E'; + } else if (p[0] == ',') { + lon = 0; + } else { + return false; } - return true; + } + return true; } /**************************************************************************/ @@ -431,15 +443,14 @@ boolean Adafruit_GPS::parseLonDir(char *p) { */ /**************************************************************************/ boolean Adafruit_GPS::parseFix(char *p) { - if (p[0] == 'A'){ - fix = true; - lastFix = sentTime; - } - else if (p[0] == 'V') - fix = false; - else - return false; - return true; + if (p[0] == 'A') { + fix = true; + lastFix = sentTime; + } else if (p[0] == 'V') + fix = false; + else + return false; + return true; } /**************************************************************************/ @@ -449,9 +460,7 @@ boolean Adafruit_GPS::parseFix(char *p) { @return float value in seconds since last fix. */ /**************************************************************************/ -float Adafruit_GPS::secondsSinceFix() { - return (millis()-lastFix) / 1000.; -} +float Adafruit_GPS::secondsSinceFix() { return (millis() - lastFix) / 1000.; } /**************************************************************************/ /*! @@ -460,9 +469,7 @@ float Adafruit_GPS::secondsSinceFix() { @return float value in seconds since last GPS time. */ /**************************************************************************/ -float Adafruit_GPS::secondsSinceTime() { - return (millis()-lastTime) / 1000.; -} +float Adafruit_GPS::secondsSinceTime() { return (millis() - lastTime) / 1000.; } /**************************************************************************/ /*! @@ -471,18 +478,18 @@ float Adafruit_GPS::secondsSinceTime() { @return float value in seconds since last GPS date. */ /**************************************************************************/ -float Adafruit_GPS::secondsSinceDate() { - return (millis()-lastDate) / 1000.; -} +float Adafruit_GPS::secondsSinceDate() { return (millis() - lastDate) / 1000.; } /**************************************************************************/ /*! - @brief How many bytes are available to read - part of 'Print'-class functionality + @brief How many bytes are available to read - part of 'Print'-class + functionality @return Bytes available, 0 if none */ /**************************************************************************/ size_t Adafruit_GPS::available(void) { - if (paused) return 0; + if (paused) + return 0; #if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL) if (gpsSwSerial) { @@ -493,14 +500,16 @@ size_t Adafruit_GPS::available(void) { return gpsHwSerial->available(); } if (gpsI2C || gpsSPI) { - return 1; // I2C/SPI doesnt have 'availability' so always has a byte at least to read! + return 1; // I2C/SPI doesnt have 'availability' so always has a byte at + // least to read! } return 0; } /**************************************************************************/ /*! - @brief Write a byte to the underlying transport - part of 'Print'-class functionality + @brief Write a byte to the underlying transport - part of 'Print'-class + functionality @param c A single byte to send @return Bytes written - 1 on success, 0 on failure */ @@ -524,7 +533,7 @@ size_t Adafruit_GPS::write(uint8_t c) { } } if (gpsSPI) { - gpsSPI->beginTransaction(gpsSPI_settings); + gpsSPI->beginTransaction(gpsSPI_settings); if (gpsSPI_cs >= 0) { digitalWrite(gpsSPI_cs, LOW); } @@ -546,14 +555,15 @@ size_t Adafruit_GPS::write(uint8_t c) { */ /**************************************************************************/ char Adafruit_GPS::read(void) { - static uint32_t firstChar = 0; // first character received in current sentence - uint32_t tStart = millis(); // as close as we can get to time char was sent + static uint32_t firstChar = 0; // first character received in current sentence + uint32_t tStart = millis(); // as close as we can get to time char was sent char c = 0; - if (paused) return c; + if (paused) + return c; #if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL) - if(gpsSwSerial) { + if (gpsSwSerial) { if (!gpsSwSerial->available()) return c; c = gpsSwSerial->read(); @@ -570,25 +580,26 @@ char Adafruit_GPS::read(void) { _buff_idx++; } else { // refill the buffer! - if (gpsI2C->requestFrom(0x10, GPS_MAX_I2C_TRANSFER, true) == GPS_MAX_I2C_TRANSFER) { - // got data! - _buff_max = 0; - char curr_char = 0; - for (int i=0; iread(); - if ((curr_char == 0x0A) && (last_char != 0x0D)) { - // skip duplicate 0x0A's - but keep as part of a CRLF - continue; - } - last_char = curr_char; - _i2cbuffer[_buff_max] = curr_char; - _buff_max++; - } - _buff_max--; // back up to the last valid slot - if ((_buff_max == 0) && (_i2cbuffer[0] == 0x0A)) { - _buff_max = -1; // ahh there was nothing to read after all - } - _buff_idx = 0; + if (gpsI2C->requestFrom(0x10, GPS_MAX_I2C_TRANSFER, true) == + GPS_MAX_I2C_TRANSFER) { + // got data! + _buff_max = 0; + char curr_char = 0; + for (int i = 0; i < GPS_MAX_I2C_TRANSFER; i++) { + curr_char = gpsI2C->read(); + if ((curr_char == 0x0A) && (last_char != 0x0D)) { + // skip duplicate 0x0A's - but keep as part of a CRLF + continue; + } + last_char = curr_char; + _i2cbuffer[_buff_max] = curr_char; + _buff_max++; + } + _buff_max--; // back up to the last valid slot + if ((_buff_max == 0) && (_i2cbuffer[0] == 0x0A)) { + _buff_max = -1; // ahh there was nothing to read after all + } + _buff_idx = 0; } return c; } @@ -596,24 +607,26 @@ char Adafruit_GPS::read(void) { if (gpsSPI) { do { - gpsSPI->beginTransaction(gpsSPI_settings); + gpsSPI->beginTransaction(gpsSPI_settings); if (gpsSPI_cs >= 0) { - digitalWrite(gpsSPI_cs, LOW); + digitalWrite(gpsSPI_cs, LOW); } c = gpsSPI->transfer(0xFF); if (gpsSPI_cs >= 0) { - digitalWrite(gpsSPI_cs, HIGH); + digitalWrite(gpsSPI_cs, HIGH); } gpsSPI->endTransaction(); // skip duplicate 0x0A's - but keep as part of a CRLF - } while (((c == 0x0A) && (last_char != 0x0D)) || (!isprint(c) && !isspace(c)) ); + } while (((c == 0x0A) && (last_char != 0x0D)) || + (!isprint(c) && !isspace(c))); last_char = c; } - //Serial.print(c); + // Serial.print(c); currentline[lineidx++] = c; if (lineidx >= MAXLINELENGTH) - lineidx = MAXLINELENGTH-1; // ensure there is someplace to put the next received character + lineidx = MAXLINELENGTH - + 1; // ensure there is someplace to put the next received character if (c == '\n') { currentline[lineidx] = 0; @@ -626,18 +639,19 @@ char Adafruit_GPS::read(void) { lastline = line2; } - //Serial.println("----"); - //Serial.println((char *)lastline); - //Serial.println("----"); + // Serial.println("----"); + // Serial.println((char *)lastline); + // Serial.println("----"); lineidx = 0; recvdflag = true; - recvdTime = millis(); // time we got the end of the string + recvdTime = millis(); // time we got the end of the string sentTime = firstChar; - firstChar = 0; // there are no characters yet - return c; // wait until next character to set time + firstChar = 0; // there are no characters yet + return c; // wait until next character to set time } - if(firstChar == 0) firstChar = tStart; + if (firstChar == 0) + firstChar = tStart; return c; } @@ -648,8 +662,7 @@ char Adafruit_GPS::read(void) { */ /**************************************************************************/ #if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL) -Adafruit_GPS::Adafruit_GPS(SoftwareSerial *ser) -{ +Adafruit_GPS::Adafruit_GPS(SoftwareSerial *ser) { common_init(); // Set everything to common state, then... gpsSwSerial = ser; // ...override gpsSwSerial with value passed. } @@ -662,7 +675,7 @@ Adafruit_GPS::Adafruit_GPS(SoftwareSerial *ser) */ /**************************************************************************/ Adafruit_GPS::Adafruit_GPS(HardwareSerial *ser) { - common_init(); // Set everything to common state, then... + common_init(); // Set everything to common state, then... gpsHwSerial = ser; // ...override gpsHwSerial with value passed. } @@ -673,7 +686,7 @@ Adafruit_GPS::Adafruit_GPS(HardwareSerial *ser) { */ /**************************************************************************/ Adafruit_GPS::Adafruit_GPS(TwoWire *theWire) { - common_init(); // Set everything to common state, then... + common_init(); // Set everything to common state, then... gpsI2C = theWire; // ...override gpsI2C } @@ -685,12 +698,11 @@ Adafruit_GPS::Adafruit_GPS(TwoWire *theWire) { */ /**************************************************************************/ Adafruit_GPS::Adafruit_GPS(SPIClass *theSPI, int8_t cspin) { - common_init(); // Set everything to common state, then... + common_init(); // Set everything to common state, then... gpsSPI = theSPI; // ...override gpsSPI gpsSPI_cs = cspin; } - /**************************************************************************/ /*! @brief Initialization code used by all constructor types @@ -701,21 +713,21 @@ void Adafruit_GPS::common_init(void) { gpsSwSerial = NULL; // Set both to NULL, then override correct #endif gpsHwSerial = NULL; // port pointer in corresponding constructor - gpsI2C = NULL; - gpsSPI = NULL; - recvdflag = false; - paused = false; - lineidx = 0; + gpsI2C = NULL; + gpsSPI = NULL; + recvdflag = false; + paused = false; + lineidx = 0; currentline = line1; - lastline = line2; + lastline = line2; - hour = minute = seconds = year = month = day = - fixquality = fixquality_3d = satellites = 0; // uint8_t + hour = minute = seconds = year = month = day = fixquality = fixquality_3d = + satellites = 0; // uint8_t lat = lon = mag = 0; // char - fix = false; // boolean - milliseconds = 0; // uint16_t - latitude = longitude = geoidheight = altitude = - speed = angle = magvariation = HDOP = VDOP = PDOP = 0.0; // float + fix = false; // boolean + milliseconds = 0; // uint16_t + latitude = longitude = geoidheight = altitude = speed = angle = magvariation = + HDOP = VDOP = PDOP = 0.0; // float } /**************************************************************************/ @@ -725,10 +737,9 @@ void Adafruit_GPS::common_init(void) { @returns True on successful hardware init, False on failure */ /**************************************************************************/ -bool Adafruit_GPS::begin(uint32_t baud_or_i2caddr) -{ +bool Adafruit_GPS::begin(uint32_t baud_or_i2caddr) { #if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL) - if(gpsSwSerial) { + if (gpsSwSerial) { gpsSwSerial->begin(baud_or_i2caddr); } #endif @@ -744,7 +755,7 @@ bool Adafruit_GPS::begin(uint32_t baud_or_i2caddr) } // A basic scanner, see if it ACK's gpsI2C->beginTransmission(_i2caddr); - return (gpsI2C->endTransmission () == 0); + return (gpsI2C->endTransmission() == 0); } if (gpsSPI) { gpsSPI->begin(); @@ -765,9 +776,7 @@ bool Adafruit_GPS::begin(uint32_t baud_or_i2caddr) @param str Pointer to a string holding the command to send */ /**************************************************************************/ -void Adafruit_GPS::sendCommand(const char *str) { - println(str); -} +void Adafruit_GPS::sendCommand(const char *str) { println(str); } /**************************************************************************/ /*! @@ -775,9 +784,7 @@ void Adafruit_GPS::sendCommand(const char *str) { @return True if received, false if not */ /**************************************************************************/ -boolean Adafruit_GPS::newNMEAreceived(void) { - return recvdflag; -} +boolean Adafruit_GPS::newNMEAreceived(void) { return recvdflag; } /**************************************************************************/ /*! @@ -785,9 +792,7 @@ boolean Adafruit_GPS::newNMEAreceived(void) { @param p True = pause, false = unpause */ /**************************************************************************/ -void Adafruit_GPS::pause(boolean p) { - paused = p; -} +void Adafruit_GPS::pause(boolean p) { paused = p; } /**************************************************************************/ /*! @@ -804,21 +809,22 @@ char *Adafruit_GPS::lastNMEA(void) { /*! @brief Parse a hex character and return the appropriate decimal value @param c Hex character, e.g. '0' or 'B' - @return Integer value of the hex character. Returns 0 if c is not a proper character + @return Integer value of the hex character. Returns 0 if c is not a proper + character */ /**************************************************************************/ // read a Hex value and return the decimal equivalent uint8_t Adafruit_GPS::parseHex(char c) { - if (c < '0') - return 0; - if (c <= '9') - return c - '0'; - if (c < 'A') - return 0; - if (c <= 'F') - return (c - 'A')+10; - // if (c > 'F') + if (c < '0') return 0; + if (c <= '9') + return c - '0'; + if (c < 'A') + return 0; + if (c <= 'F') + return (c - 'A') + 10; + // if (c > 'F') + return 0; } /**************************************************************************/ @@ -826,12 +832,14 @@ uint8_t Adafruit_GPS::parseHex(char c) { @brief Wait for a specified sentence from the device @param wait4me Pointer to a string holding the desired response @param max How long to wait, default is MAXWAITSENTENCE - @param usingInterrupts True if using interrupts to read from the GPS (default is false) + @param usingInterrupts True if using interrupts to read from the GPS + (default is false) @return True if we got what we wanted, false otherwise */ /**************************************************************************/ -boolean Adafruit_GPS::waitForSentence(const char *wait4me, uint8_t max, boolean usingInterrupts) { - uint8_t i=0; +boolean Adafruit_GPS::waitForSentence(const char *wait4me, uint8_t max, + boolean usingInterrupts) { + uint8_t i = 0; while (i < max) { if (!usingInterrupts) read(); @@ -841,7 +849,7 @@ boolean Adafruit_GPS::waitForSentence(const char *wait4me, uint8_t max, boolean i++; if (strStartsWith(nmea, wait4me)) - return true; + return true; } } @@ -881,23 +889,23 @@ boolean Adafruit_GPS::LOCUS_StopLogger(void) { boolean Adafruit_GPS::LOCUS_ReadStatus(void) { sendCommand(PMTK_LOCUS_QUERY_STATUS); - if (! waitForSentence("$PMTKLOG")) + if (!waitForSentence("$PMTKLOG")) return false; char *response = lastNMEA(); uint16_t parsed[10]; uint8_t i; - for (i=0; i<10; i++) parsed[i] = -1; + for (i = 0; i < 10; i++) + parsed[i] = -1; response = strchr(response, ','); - for (i=0; i<10; i++) { + for (i = 0; i < 10; i++) { if (!response || (response[0] == 0) || (response[0] == '*')) break; response++; - parsed[i]=0; - while ((response[0] != ',') && - (response[0] != '*') && (response[0] != 0)) { + parsed[i] = 0; + while ((response[0] != ',') && (response[0] != '*') && (response[0] != 0)) { parsed[i] *= 10; char c = response[0]; if (isDigit(c)) @@ -932,12 +940,13 @@ boolean Adafruit_GPS::LOCUS_ReadStatus(void) { /**************************************************************************/ boolean Adafruit_GPS::standby(void) { if (inStandbyMode) { - return false; // Returns false if already in standby mode, so that you do not wake it up by sending commands to GPS - } - else { + return false; // Returns false if already in standby mode, so that you do + // not wake it up by sending commands to GPS + } else { inStandbyMode = true; sendCommand(PMTK_STANDBY); - //return waitForSentence(PMTK_STANDBY_SUCCESS); // don't seem to be fast enough to catch the message, or something else just is not working + // return waitForSentence(PMTK_STANDBY_SUCCESS); // don't seem to be fast + // enough to catch the message, or something else just is not working return true; } } @@ -950,12 +959,11 @@ boolean Adafruit_GPS::standby(void) { /**************************************************************************/ boolean Adafruit_GPS::wakeup(void) { if (inStandbyMode) { - inStandbyMode = false; - sendCommand(""); // send byte to wake it up + inStandbyMode = false; + sendCommand(""); // send byte to wake it up return waitForSentence(PMTK_AWAKE); - } - else { - return false; // Returns false if not in standby mode, nothing to wakeup + } else { + return false; // Returns false if not in standby mode, nothing to wakeup } } @@ -967,8 +975,7 @@ boolean Adafruit_GPS::wakeup(void) { @return True if str starts with prefix, false otherwise */ /**************************************************************************/ -static boolean strStartsWith(const char* str, const char* prefix) -{ +static boolean strStartsWith(const char *str, const char *prefix) { while (*prefix) { if (*prefix++ != *str++) return false; diff --git a/Adafruit_GPS.h b/Adafruit_GPS.h index c004f1e..2b4f4da 100644 --- a/Adafruit_GPS.h +++ b/Adafruit_GPS.h @@ -26,107 +26,141 @@ #ifndef _ADAFRUIT_GPS_H #define _ADAFRUIT_GPS_H -#define USE_SW_SERIAL ///< comment this out if you don't want to include software serial in the library -#define GPS_DEFAULT_I2C_ADDR 0x10 ///< The default address for I2C transport of GPS data -#define GPS_MAX_I2C_TRANSFER 32 ///< The max number of bytes we'll try to read at once -#define GPS_MAX_SPI_TRANSFER 100 ///< The max number of bytes we'll try to read at once +#define USE_SW_SERIAL ///< comment this out if you don't want to include + ///< software serial in the library +#define GPS_DEFAULT_I2C_ADDR \ + 0x10 ///< The default address for I2C transport of GPS data +#define GPS_MAX_I2C_TRANSFER \ + 32 ///< The max number of bytes we'll try to read at once +#define GPS_MAX_SPI_TRANSFER \ + 100 ///< The max number of bytes we'll try to read at once #define MAXLINELENGTH 120 ///< how long are max NMEA lines to parse? -#define NMEA_MAX_SENTENCE_ID 20 ///< maximum length of a sentence ID name, including terminating 0 -#define NMEA_MAX_SOURCE_ID 3 ///< maximum length of a source ID name, including terminating 0 - +#define NMEA_MAX_SENTENCE_ID \ + 20 ///< maximum length of a sentence ID name, including terminating 0 +#define NMEA_MAX_SOURCE_ID \ + 3 ///< maximum length of a source ID name, including terminating 0 #include "Arduino.h" #if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL) - #include +#include #endif -#include #include +#include /**************************************************************************/ /** - Different commands to set the update rate from once a second (1 Hz) to 10 times a second (10Hz) - Note that these only control the rate at which the position is echoed, to actually speed up the - position fix you must also send one of the position fix rate commands below too. */ -#define PMTK_SET_NMEA_UPDATE_100_MILLIHERTZ "$PMTK220,10000*2F" ///< Once every 10 seconds, 100 millihertz. -#define PMTK_SET_NMEA_UPDATE_200_MILLIHERTZ "$PMTK220,5000*1B" ///< Once every 5 seconds, 200 millihertz. -#define PMTK_SET_NMEA_UPDATE_1HZ "$PMTK220,1000*1F" ///< 1 Hz -#define PMTK_SET_NMEA_UPDATE_2HZ "$PMTK220,500*2B" ///< 2 Hz -#define PMTK_SET_NMEA_UPDATE_5HZ "$PMTK220,200*2C" ///< 5 Hz -#define PMTK_SET_NMEA_UPDATE_10HZ "$PMTK220,100*2F" ///< 10 Hz + Different commands to set the update rate from once a second (1 Hz) to 10 times + a second (10Hz) Note that these only control the rate at which the position is + echoed, to actually speed up the position fix you must also send one of the + position fix rate commands below too. */ +#define PMTK_SET_NMEA_UPDATE_100_MILLIHERTZ \ + "$PMTK220,10000*2F" ///< Once every 10 seconds, 100 millihertz. +#define PMTK_SET_NMEA_UPDATE_200_MILLIHERTZ \ + "$PMTK220,5000*1B" ///< Once every 5 seconds, 200 millihertz. +#define PMTK_SET_NMEA_UPDATE_1HZ "$PMTK220,1000*1F" ///< 1 Hz +#define PMTK_SET_NMEA_UPDATE_2HZ "$PMTK220,500*2B" ///< 2 Hz +#define PMTK_SET_NMEA_UPDATE_5HZ "$PMTK220,200*2C" ///< 5 Hz +#define PMTK_SET_NMEA_UPDATE_10HZ "$PMTK220,100*2F" ///< 10 Hz // Position fix update rate commands. -#define PMTK_API_SET_FIX_CTL_100_MILLIHERTZ "$PMTK300,10000,0,0,0,0*2C" ///< Once every 10 seconds, 100 millihertz. -#define PMTK_API_SET_FIX_CTL_200_MILLIHERTZ "$PMTK300,5000,0,0,0,0*18" ///< Once every 5 seconds, 200 millihertz. -#define PMTK_API_SET_FIX_CTL_1HZ "$PMTK300,1000,0,0,0,0*1C" ///< 1 Hz -#define PMTK_API_SET_FIX_CTL_5HZ "$PMTK300,200,0,0,0,0*2F" ///< 5 Hz +#define PMTK_API_SET_FIX_CTL_100_MILLIHERTZ \ + "$PMTK300,10000,0,0,0,0*2C" ///< Once every 10 seconds, 100 millihertz. +#define PMTK_API_SET_FIX_CTL_200_MILLIHERTZ \ + "$PMTK300,5000,0,0,0,0*18" ///< Once every 5 seconds, 200 millihertz. +#define PMTK_API_SET_FIX_CTL_1HZ "$PMTK300,1000,0,0,0,0*1C" ///< 1 Hz +#define PMTK_API_SET_FIX_CTL_5HZ "$PMTK300,200,0,0,0,0*2F" ///< 5 Hz // Can't fix position faster than 5 times a second! -#define PMTK_SET_BAUD_115200 "$PMTK251,115200*1F" ///< 115200 bps -#define PMTK_SET_BAUD_57600 "$PMTK251,57600*2C" ///< 57600 bps -#define PMTK_SET_BAUD_9600 "$PMTK251,9600*17" ///< 9600 bps +#define PMTK_SET_BAUD_115200 "$PMTK251,115200*1F" ///< 115200 bps +#define PMTK_SET_BAUD_57600 "$PMTK251,57600*2C" ///< 57600 bps +#define PMTK_SET_BAUD_9600 "$PMTK251,9600*17" ///< 9600 bps -#define PMTK_SET_NMEA_OUTPUT_GLLONLY "$PMTK314,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29" ///< turn on only the GPGLL sentence -#define PMTK_SET_NMEA_OUTPUT_RMCONLY "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29" ///< turn on only the GPRMC sentence -#define PMTK_SET_NMEA_OUTPUT_VTGONLY "$PMTK314,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29" ///< turn on only the GPVTG -#define PMTK_SET_NMEA_OUTPUT_GGAONLY "$PMTK314,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29" ///< turn on just the GPGGA -#define PMTK_SET_NMEA_OUTPUT_GSAONLY "$PMTK314,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29" ///< turn on just the GPGSA -#define PMTK_SET_NMEA_OUTPUT_GSVONLY "$PMTK314,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0*29" ///< turn on just the GPGSV -#define PMTK_SET_NMEA_OUTPUT_RMCGGA "$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28" ///< turn on GPRMC and GPGGA -#define PMTK_SET_NMEA_OUTPUT_RMCGGAGSA "$PMTK314,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29" ///< turn on GPRMC, GPGGA and GPGSA -#define PMTK_SET_NMEA_OUTPUT_ALLDATA "$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28" ///< turn on ALL THE DATA -#define PMTK_SET_NMEA_OUTPUT_OFF "$PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28" ///< turn off output +#define PMTK_SET_NMEA_OUTPUT_GLLONLY \ + "$PMTK314,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29" ///< turn on only the + ///< GPGLL sentence +#define PMTK_SET_NMEA_OUTPUT_RMCONLY \ + "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29" ///< turn on only the + ///< GPRMC sentence +#define PMTK_SET_NMEA_OUTPUT_VTGONLY \ + "$PMTK314,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29" ///< turn on only the + ///< GPVTG +#define PMTK_SET_NMEA_OUTPUT_GGAONLY \ + "$PMTK314,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29" ///< turn on just the + ///< GPGGA +#define PMTK_SET_NMEA_OUTPUT_GSAONLY \ + "$PMTK314,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29" ///< turn on just the + ///< GPGSA +#define PMTK_SET_NMEA_OUTPUT_GSVONLY \ + "$PMTK314,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0*29" ///< turn on just the + ///< GPGSV +#define PMTK_SET_NMEA_OUTPUT_RMCGGA \ + "$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28" ///< turn on GPRMC and + ///< GPGGA +#define PMTK_SET_NMEA_OUTPUT_RMCGGAGSA \ + "$PMTK314,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29" ///< turn on GPRMC, GPGGA + ///< and GPGSA +#define PMTK_SET_NMEA_OUTPUT_ALLDATA \ + "$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28" ///< turn on ALL THE DATA +#define PMTK_SET_NMEA_OUTPUT_OFF \ + "$PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28" ///< turn off output +// to generate your own sentences, check out the MTK command datasheet and use a +// checksum calculator such as the awesome +// http://www.hhhh.org/wiml/proj/nmeaxor.html -// to generate your own sentences, check out the MTK command datasheet and use a checksum calculator -// such as the awesome http://www.hhhh.org/wiml/proj/nmeaxor.html +#define PMTK_LOCUS_STARTLOG "$PMTK185,0*22" ///< Start logging data +#define PMTK_LOCUS_STOPLOG "$PMTK185,1*23" ///< Stop logging data +#define PMTK_LOCUS_STARTSTOPACK \ + "$PMTK001,185,3*3C" ///< Acknowledge the start or stop command +#define PMTK_LOCUS_QUERY_STATUS "$PMTK183*38" ///< Query the logging status +#define PMTK_LOCUS_ERASE_FLASH "$PMTK184,1*22" ///< Erase the log flash data +#define LOCUS_OVERLAP \ + 0 ///< If flash is full, log will overwrite old data with new logs +#define LOCUS_FULLSTOP 1 ///< If flash is full, logging will stop -#define PMTK_LOCUS_STARTLOG "$PMTK185,0*22" ///< Start logging data -#define PMTK_LOCUS_STOPLOG "$PMTK185,1*23" ///< Stop logging data -#define PMTK_LOCUS_STARTSTOPACK "$PMTK001,185,3*3C" ///< Acknowledge the start or stop command -#define PMTK_LOCUS_QUERY_STATUS "$PMTK183*38" ///< Query the logging status -#define PMTK_LOCUS_ERASE_FLASH "$PMTK184,1*22" ///< Erase the log flash data -#define LOCUS_OVERLAP 0 ///< If flash is full, log will overwrite old data with new logs -#define LOCUS_FULLSTOP 1 ///< If flash is full, logging will stop +#define PMTK_ENABLE_SBAS \ + "$PMTK313,1*2E" ///< Enable search for SBAS satellite (only works with 1Hz + ///< output rate) +#define PMTK_ENABLE_WAAS "$PMTK301,2*2E" ///< Use WAAS for DGPS correction data -#define PMTK_ENABLE_SBAS "$PMTK313,1*2E" ///< Enable search for SBAS satellite (only works with 1Hz output rate) -#define PMTK_ENABLE_WAAS "$PMTK301,2*2E" ///< Use WAAS for DGPS correction data +#define PMTK_STANDBY \ + "$PMTK161,0*28" ///< standby command & boot successful message +#define PMTK_STANDBY_SUCCESS "$PMTK001,161,3*36" ///< Not needed currently +#define PMTK_AWAKE "$PMTK010,002*2D" ///< Wake up -#define PMTK_STANDBY "$PMTK161,0*28" ///< standby command & boot successful message -#define PMTK_STANDBY_SUCCESS "$PMTK001,161,3*36" ///< Not needed currently -#define PMTK_AWAKE "$PMTK010,002*2D" ///< Wake up +#define PMTK_Q_RELEASE "$PMTK605*31" ///< ask for the release and version -#define PMTK_Q_RELEASE "$PMTK605*31" ///< ask for the release and version +#define PGCMD_ANTENNA \ + "$PGCMD,33,1*6C" ///< request for updates on antenna status +#define PGCMD_NOANTENNA "$PGCMD,33,0*6D" ///< don't show antenna status messages - -#define PGCMD_ANTENNA "$PGCMD,33,1*6C" ///< request for updates on antenna status -#define PGCMD_NOANTENNA "$PGCMD,33,0*6D" ///< don't show antenna status messages - -#define MAXWAITSENTENCE 10 ///< how long to wait when we're looking for a response +#define MAXWAITSENTENCE \ + 10 ///< how long to wait when we're looking for a response /**************************************************************************/ /// type for resulting code from running check() typedef enum { - NMEA_BAD = 0, ///< passed none of the checks - NMEA_HAS_DOLLAR = 1, ///< has a dollar sign in the first position - NMEA_HAS_CHECKSUM = 2, ///< has a valid checksum at the end - NMEA_HAS_NAME = 4, ///< there is a token after the $ followed by a comma - NMEA_HAS_SOURCE = 10, ///< has a recognized source ID - NMEA_HAS_SENTENCE = 20, ///< has a recognized sentence ID - NMEA_HAS_SENTENCE_P = 40 ///< has a recognized parseable sentence ID -} nmea_check_t; + NMEA_BAD = 0, ///< passed none of the checks + NMEA_HAS_DOLLAR = 1, ///< has a dollar sign in the first position + NMEA_HAS_CHECKSUM = 2, ///< has a valid checksum at the end + NMEA_HAS_NAME = 4, ///< there is a token after the $ followed by a comma + NMEA_HAS_SOURCE = 10, ///< has a recognized source ID + NMEA_HAS_SENTENCE = 20, ///< has a recognized sentence ID + NMEA_HAS_SENTENCE_P = 40 ///< has a recognized parseable sentence ID +} nmea_check_t; /**************************************************************************/ /*! @brief The GPS class */ -class Adafruit_GPS : public Print{ - public: +class Adafruit_GPS : public Print { +public: bool begin(uint32_t baud_or_i2caddr); #if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL) Adafruit_GPS(SoftwareSerial *ser); // Constructor when using SoftwareSerial #endif Adafruit_GPS(HardwareSerial *ser); // Constructor when using HardwareSerial - Adafruit_GPS(TwoWire *theWire); // Constructor when using I2C + Adafruit_GPS(TwoWire *theWire); // Constructor when using I2C Adafruit_GPS(SPIClass *theSPI, int8_t cspin); // Constructor when using SPI char *lastNMEA(void); @@ -143,7 +177,7 @@ class Adafruit_GPS : public Print{ size_t write(uint8_t); size_t available(void); - boolean check(char *nmea); + boolean check(char *nmea); boolean parse(char *); void addChecksum(char *buff); float secondsSinceFix(); @@ -153,65 +187,78 @@ class Adafruit_GPS : public Print{ boolean wakeup(void); boolean standby(void); - int thisCheck = 0; ///< the results of the check on the current sentence - char thisSource[NMEA_MAX_SOURCE_ID] = {0}; ///< the first two letters of the current sentence, e.g. WI, GP - char thisSentence[NMEA_MAX_SENTENCE_ID] = {0}; ///< the next three letters of the current sentence, e.g. GLL, RMC - char lastSource[NMEA_MAX_SOURCE_ID] = {0}; ///< the results of the check on the most recent successfully parsed sentence - char lastSentence[NMEA_MAX_SENTENCE_ID] = {0}; ///< the next three letters of the most recent successfully parsed sentence, e.g. GLL, RMC + int thisCheck = 0; ///< the results of the check on the current sentence + char thisSource[NMEA_MAX_SOURCE_ID] = { + 0}; ///< the first two letters of the current sentence, e.g. WI, GP + char thisSentence[NMEA_MAX_SENTENCE_ID] = { + 0}; ///< the next three letters of the current sentence, e.g. GLL, RMC + char lastSource[NMEA_MAX_SOURCE_ID] = { + 0}; ///< the results of the check on the most recent successfully parsed + ///< sentence + char lastSentence[NMEA_MAX_SENTENCE_ID] = { + 0}; ///< the next three letters of the most recent successfully parsed + ///< sentence, e.g. GLL, RMC - uint8_t hour; ///< GMT hours - uint8_t minute; ///< GMT minutes - uint8_t seconds; ///< GMT seconds - uint16_t milliseconds; ///< GMT milliseconds - uint8_t year; ///< GMT year - uint8_t month; ///< GMT month - uint8_t day; ///< GMT day + uint8_t hour; ///< GMT hours + uint8_t minute; ///< GMT minutes + uint8_t seconds; ///< GMT seconds + uint16_t milliseconds; ///< GMT milliseconds + uint8_t year; ///< GMT year + uint8_t month; ///< GMT month + uint8_t day; ///< GMT day - float latitude; ///< Floating point latitude value in degrees/minutes as received from the GPS (DDMM.MMMM) - float longitude; ///< Floating point longitude value in degrees/minutes as received from the GPS (DDDMM.MMMM) + float latitude; ///< Floating point latitude value in degrees/minutes as + ///< received from the GPS (DDMM.MMMM) + float longitude; ///< Floating point longitude value in degrees/minutes as + ///< received from the GPS (DDDMM.MMMM) - /** Fixed point latitude and longitude value with degrees stored in units of 1/100000 degrees, - and minutes stored in units of 1/100000 degrees. See pull #13 for more details: + /** Fixed point latitude and longitude value with degrees stored in units of + 1/100000 degrees, and minutes stored in units of 1/100000 degrees. See pull + #13 for more details: https://github.com/adafruit/Adafruit-GPS-Library/pull/13 */ - int32_t latitude_fixed; ///< Fixed point latitude in decimal degrees - int32_t longitude_fixed; ///< Fixed point longitude in decimal degrees + int32_t latitude_fixed; ///< Fixed point latitude in decimal degrees + int32_t longitude_fixed; ///< Fixed point longitude in decimal degrees - float latitudeDegrees; ///< Latitude in decimal degrees - float longitudeDegrees; ///< Longitude in decimal degrees - float geoidheight; ///< Diff between geoid height and WGS84 height - float altitude; ///< Altitude in meters above MSL - float speed; ///< Current speed over ground in knots - float angle; ///< Course in degrees from true north - float magvariation; ///< Magnetic variation in degrees (vs. true north) - float HDOP; ///< Horizontal Dilution of Precision - relative accuracy of horizontal position - float VDOP; ///< Vertical Dilution of Precision - relative accuracy of vertical position - float PDOP; ///< Position Dilution of Precision - Complex maths derives a simple, single number for each kind of DOP - char lat; ///< N/S - char lon; ///< E/W - char mag; ///< Magnetic variation direction - boolean fix; ///< Have a fix? - uint8_t fixquality; ///< Fix quality (0, 1, 2 = Invalid, GPS, DGPS) - uint8_t fixquality_3d; ///< 3D fix quality (1, 3, 3 = Nofix, 2D fix, 3D fix) - uint8_t satellites; ///< Number of satellites in use + float latitudeDegrees; ///< Latitude in decimal degrees + float longitudeDegrees; ///< Longitude in decimal degrees + float geoidheight; ///< Diff between geoid height and WGS84 height + float altitude; ///< Altitude in meters above MSL + float speed; ///< Current speed over ground in knots + float angle; ///< Course in degrees from true north + float magvariation; ///< Magnetic variation in degrees (vs. true north) + float HDOP; ///< Horizontal Dilution of Precision - relative accuracy of + ///< horizontal position + float VDOP; ///< Vertical Dilution of Precision - relative accuracy of + ///< vertical position + float PDOP; ///< Position Dilution of Precision - Complex maths derives a + ///< simple, single number for each kind of DOP + char lat; ///< N/S + char lon; ///< E/W + char mag; ///< Magnetic variation direction + boolean fix; ///< Have a fix? + uint8_t fixquality; ///< Fix quality (0, 1, 2 = Invalid, GPS, DGPS) + uint8_t fixquality_3d; ///< 3D fix quality (1, 3, 3 = Nofix, 2D fix, 3D fix) + uint8_t satellites; ///< Number of satellites in use - boolean waitForSentence(const char *wait, uint8_t max = MAXWAITSENTENCE, boolean usingInterrupts = false); + boolean waitForSentence(const char *wait, uint8_t max = MAXWAITSENTENCE, + boolean usingInterrupts = false); boolean LOCUS_StartLogger(void); boolean LOCUS_StopLogger(void); boolean LOCUS_ReadStatus(void); - uint16_t LOCUS_serial; ///< Log serial number - uint16_t LOCUS_records; ///< Log number of data record - uint8_t LOCUS_type; ///< Log type, 0: Overlap, 1: FullStop - uint8_t LOCUS_mode; ///< Logging mode, 0x08 interval logger - uint8_t LOCUS_config; ///< Contents of configuration - uint8_t LOCUS_interval; ///< Interval setting - uint8_t LOCUS_distance; ///< Distance setting - uint8_t LOCUS_speed; ///< Speed setting - uint8_t LOCUS_status; ///< 0: Logging, 1: Stop logging - uint8_t LOCUS_percent; ///< Log life used percentage + uint16_t LOCUS_serial; ///< Log serial number + uint16_t LOCUS_records; ///< Log number of data record + uint8_t LOCUS_type; ///< Log type, 0: Overlap, 1: FullStop + uint8_t LOCUS_mode; ///< Logging mode, 0x08 interval logger + uint8_t LOCUS_config; ///< Contents of configuration + uint8_t LOCUS_interval; ///< Interval setting + uint8_t LOCUS_distance; ///< Distance setting + uint8_t LOCUS_speed; ///< Speed setting + uint8_t LOCUS_status; ///< 0: Logging, 1: Stop logging + uint8_t LOCUS_percent; ///< Log life used percentage - private: - const char * tokenOnList(char *token, const char **list); +private: + const char *tokenOnList(char *token, const char **list); void parseTime(char *); void parseLat(char *); boolean parseLatDir(char *); @@ -219,18 +266,24 @@ class Adafruit_GPS : public Print{ boolean parseLonDir(char *); boolean parseFix(char *); // used by check() for validity tests, room for future expansion - const char *sources[5] = {"II", "WI", "GP", "GN", "ZZZ"}; ///< valid source ids - const char *sentences_parsed[5] = {"GGA", "GLL", "GSA", "RMC", "ZZZ"}; ///< parseable sentence ids - const char *sentences_known[1] = {"ZZZ"}; ///< known, but not parseable sentence ids - - // Make all of these times far in the past by setting them near the middle of the - // millis() range. Timing assumes that sentences are parsed promptly. - uint32_t lastUpdate = 2000000000L; ///< millis() when last full sentence successfully parsed - uint32_t lastFix = 2000000000L; ///< millis() when last fix received - uint32_t lastTime = 2000000000L; ///< millis() when last time received - uint32_t lastDate = 2000000000L; ///< millis() when last date received - uint32_t recvdTime = 2000000000L; ///< millis() when last full sentence received - uint32_t sentTime = 2000000000L; ///< millis() when first character of last full sentence received + const char *sources[5] = {"II", "WI", "GP", "GN", + "ZZZ"}; ///< valid source ids + const char *sentences_parsed[5] = {"GGA", "GLL", "GSA", "RMC", + "ZZZ"}; ///< parseable sentence ids + const char *sentences_known[1] = { + "ZZZ"}; ///< known, but not parseable sentence ids + + // Make all of these times far in the past by setting them near the middle of + // the millis() range. Timing assumes that sentences are parsed promptly. + uint32_t lastUpdate = + 2000000000L; ///< millis() when last full sentence successfully parsed + uint32_t lastFix = 2000000000L; ///< millis() when last fix received + uint32_t lastTime = 2000000000L; ///< millis() when last time received + uint32_t lastDate = 2000000000L; ///< millis() when last date received + uint32_t recvdTime = + 2000000000L; ///< millis() when last full sentence received + uint32_t sentTime = 2000000000L; ///< millis() when first character of last + ///< full sentence received boolean paused; uint8_t parseResponse(char *response); @@ -241,20 +294,23 @@ class Adafruit_GPS : public Print{ TwoWire *gpsI2C; SPIClass *gpsSPI; int8_t gpsSPI_cs = -1; - SPISettings gpsSPI_settings = SPISettings(1000000, MSBFIRST, SPI_MODE0); // default - char _spibuffer[GPS_MAX_SPI_TRANSFER]; // for when we write data, we need to read it too! + SPISettings gpsSPI_settings = + SPISettings(1000000, MSBFIRST, SPI_MODE0); // default + char _spibuffer[GPS_MAX_SPI_TRANSFER]; // for when we write data, we need to + // read it too! uint8_t _i2caddr; char _i2cbuffer[GPS_MAX_I2C_TRANSFER]; int8_t _buff_max = -1, _buff_idx = 0; char last_char = 0; - - volatile char line1[MAXLINELENGTH]; ///< We double buffer: read one line in and leave one for the main program + + volatile char line1[MAXLINELENGTH]; ///< We double buffer: read one line in + ///< and leave one for the main program volatile char line2[MAXLINELENGTH]; ///< Second buffer - volatile uint8_t lineidx=0; ///< our index into filling the current line - volatile char *currentline; ///< Pointer to current line buffer - volatile char *lastline; ///< Pointer to previous line buffer - volatile boolean recvdflag; ///< Received flag - volatile boolean inStandbyMode; ///< In standby flag + volatile uint8_t lineidx = 0; ///< our index into filling the current line + volatile char *currentline; ///< Pointer to current line buffer + volatile char *lastline; ///< Pointer to previous line buffer + volatile boolean recvdflag; ///< Received flag + volatile boolean inStandbyMode; ///< In standby flag }; /**************************************************************************/ diff --git a/examples/GPS_SoftwareSerial_EchoTest/.due.test.skip b/examples/GPS_SoftwareSerial_EchoTest/.leonardo.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_EchoTest/.due.test.skip rename to examples/GPS_SoftwareSerial_EchoTest/.leonardo.test.only diff --git a/examples/GPS_SoftwareSerial_EchoTest/.esp32.test.skip b/examples/GPS_SoftwareSerial_EchoTest/.mega2560.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_EchoTest/.esp32.test.skip rename to examples/GPS_SoftwareSerial_EchoTest/.mega2560.test.only diff --git a/examples/GPS_SoftwareSerial_EchoTest/.m4.test.skip b/examples/GPS_SoftwareSerial_EchoTest/.uno.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_EchoTest/.m4.test.skip rename to examples/GPS_SoftwareSerial_EchoTest/.uno.test.only diff --git a/examples/GPS_SoftwareSerial_EchoTest/.zero.test.skip b/examples/GPS_SoftwareSerial_LOCUS_DumpBasic/.leonardo.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_EchoTest/.zero.test.skip rename to examples/GPS_SoftwareSerial_LOCUS_DumpBasic/.leonardo.test.only diff --git a/examples/GPS_SoftwareSerial_LOCUS_DumpBasic/.due.test.skip b/examples/GPS_SoftwareSerial_LOCUS_DumpBasic/.mega2560.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_DumpBasic/.due.test.skip rename to examples/GPS_SoftwareSerial_LOCUS_DumpBasic/.mega2560.test.only diff --git a/examples/GPS_SoftwareSerial_LOCUS_DumpBasic/.esp32.test.skip b/examples/GPS_SoftwareSerial_LOCUS_DumpBasic/.uno.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_DumpBasic/.esp32.test.skip rename to examples/GPS_SoftwareSerial_LOCUS_DumpBasic/.uno.test.only diff --git a/examples/GPS_SoftwareSerial_LOCUS_DumpBasic/.m4.test.skip b/examples/GPS_SoftwareSerial_LOCUS_Erase/.leonardo.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_DumpBasic/.m4.test.skip rename to examples/GPS_SoftwareSerial_LOCUS_Erase/.leonardo.test.only diff --git a/examples/GPS_SoftwareSerial_LOCUS_DumpBasic/.zero.test.skip b/examples/GPS_SoftwareSerial_LOCUS_Erase/.mega2560.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_DumpBasic/.zero.test.skip rename to examples/GPS_SoftwareSerial_LOCUS_Erase/.mega2560.test.only diff --git a/examples/GPS_SoftwareSerial_LOCUS_Erase/.due.test.skip b/examples/GPS_SoftwareSerial_LOCUS_Erase/.uno.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_Erase/.due.test.skip rename to examples/GPS_SoftwareSerial_LOCUS_Erase/.uno.test.only diff --git a/examples/GPS_SoftwareSerial_LOCUS_Erase/.esp32.test.skip b/examples/GPS_SoftwareSerial_LOCUS_Start/.leonardo.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_Erase/.esp32.test.skip rename to examples/GPS_SoftwareSerial_LOCUS_Start/.leonardo.test.only diff --git a/examples/GPS_SoftwareSerial_LOCUS_Erase/.m4.test.skip b/examples/GPS_SoftwareSerial_LOCUS_Start/.mega2560.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_Erase/.m4.test.skip rename to examples/GPS_SoftwareSerial_LOCUS_Start/.mega2560.test.only diff --git a/examples/GPS_SoftwareSerial_LOCUS_Erase/.zero.test.skip b/examples/GPS_SoftwareSerial_LOCUS_Start/.uno.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_Erase/.zero.test.skip rename to examples/GPS_SoftwareSerial_LOCUS_Start/.uno.test.only diff --git a/examples/GPS_SoftwareSerial_LOCUS_Start/.due.test.skip b/examples/GPS_SoftwareSerial_LOCUS_Status/.leonardo.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_Start/.due.test.skip rename to examples/GPS_SoftwareSerial_LOCUS_Status/.leonardo.test.only diff --git a/examples/GPS_SoftwareSerial_LOCUS_Start/.esp32.test.skip b/examples/GPS_SoftwareSerial_LOCUS_Status/.mega2560.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_Start/.esp32.test.skip rename to examples/GPS_SoftwareSerial_LOCUS_Status/.mega2560.test.only diff --git a/examples/GPS_SoftwareSerial_LOCUS_Start/.m4.test.skip b/examples/GPS_SoftwareSerial_LOCUS_Status/.uno.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_Start/.m4.test.skip rename to examples/GPS_SoftwareSerial_LOCUS_Status/.uno.test.only diff --git a/examples/GPS_SoftwareSerial_Parsing/.esp32.test.skip b/examples/GPS_SoftwareSerial_Parsing/.esp32.test.skip deleted file mode 100644 index e69de29..0000000 diff --git a/examples/GPS_SoftwareSerial_LOCUS_Start/.zero.test.skip b/examples/GPS_SoftwareSerial_Parsing/.leonardo.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_Start/.zero.test.skip rename to examples/GPS_SoftwareSerial_Parsing/.leonardo.test.only diff --git a/examples/GPS_SoftwareSerial_Parsing/.m4.test.skip b/examples/GPS_SoftwareSerial_Parsing/.m4.test.skip deleted file mode 100644 index e69de29..0000000 diff --git a/examples/GPS_SoftwareSerial_LOCUS_Status/.due.test.skip b/examples/GPS_SoftwareSerial_Parsing/.mega2560.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_Status/.due.test.skip rename to examples/GPS_SoftwareSerial_Parsing/.mega2560.test.only diff --git a/examples/GPS_SoftwareSerial_LOCUS_Status/.esp32.test.skip b/examples/GPS_SoftwareSerial_Parsing/.uno.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_Status/.esp32.test.skip rename to examples/GPS_SoftwareSerial_Parsing/.uno.test.only diff --git a/examples/GPS_SoftwareSerial_Parsing/.zero.test.skip b/examples/GPS_SoftwareSerial_Parsing/.zero.test.skip deleted file mode 100644 index e69de29..0000000 diff --git a/examples/shield_sdlog/.due.test.skip b/examples/shield_sdlog/.due.test.skip deleted file mode 100644 index e69de29..0000000 diff --git a/examples/shield_sdlog/.esp32.test.skip b/examples/shield_sdlog/.esp32.test.skip deleted file mode 100644 index e69de29..0000000 diff --git a/examples/shield_sdlog/.esp8266.test.skip b/examples/shield_sdlog/.esp8266.test.skip deleted file mode 100644 index e69de29..0000000 diff --git a/examples/GPS_SoftwareSerial_LOCUS_Status/.m4.test.skip b/examples/shield_sdlog/.leonardo.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_Status/.m4.test.skip rename to examples/shield_sdlog/.leonardo.test.only diff --git a/examples/shield_sdlog/.m4.test.skip b/examples/shield_sdlog/.m4.test.skip deleted file mode 100644 index e69de29..0000000 diff --git a/examples/GPS_SoftwareSerial_LOCUS_Status/.zero.test.skip b/examples/shield_sdlog/.mega2560.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_LOCUS_Status/.zero.test.skip rename to examples/shield_sdlog/.mega2560.test.only diff --git a/examples/GPS_SoftwareSerial_Parsing/.due.test.skip b/examples/shield_sdlog/.uno.test.only similarity index 100% rename from examples/GPS_SoftwareSerial_Parsing/.due.test.skip rename to examples/shield_sdlog/.uno.test.only diff --git a/examples/shield_sdlog/.zero.test.skip b/examples/shield_sdlog/.zero.test.skip deleted file mode 100644 index e69de29..0000000 diff --git a/library.properties b/library.properties index 7a5957b..62f1811 100644 --- a/library.properties +++ b/library.properties @@ -7,3 +7,4 @@ paragraph=An interrupt-based GPS library for no-parsing-required use category=Sensors url=https://github.com/adafruit/Adafruit_GPS architectures=* +depends=SD \ No newline at end of file