Merge pull request #109 from adafruit/actions

Add Actions and remove travis
This commit is contained in:
Matt Goodrich 2020-01-17 21:33:03 -05:00 committed by GitHub
commit 309b27c464
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 540 additions and 473 deletions

32
.github/workflows/githubci.yml vendored Normal file
View File

@ -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

View File

@ -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)

View File

@ -30,116 +30,118 @@
#include <Adafruit_GPS.h>
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,67 +150,68 @@ 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;
}
@ -224,38 +227,48 @@ boolean Adafruit_GPS::parse(char *nmea) {
/**************************************************************************/
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 *
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
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));
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;
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);
snc = tokenOnList(p, sentences_known);
if (snc) {
strcpy(thisSentence, snc);
thisCheck += NMEA_HAS_SENTENCE;
return false;
}
@ -271,11 +284,13 @@ 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) {
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
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
@ -292,14 +307,14 @@ const char * Adafruit_GPS::tokenOnList(char *token, const char **list) {
@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);
}
/**************************************************************************/
@ -315,7 +330,7 @@ void Adafruit_GPS::parseTime(char *p) {
minute = (time % 10000) / 100;
seconds = (time % 100);
p = strchr(p, '.')+1;
p = strchr(p, '.') + 1;
milliseconds = atoi(p);
lastTime = sentTime;
}
@ -330,8 +345,7 @@ void Adafruit_GPS::parseLat(char *p) {
int32_t degree;
long minutes;
char degreebuff[10];
if (',' != *p)
{
if (',' != *p) {
strncpy(degreebuff, p, 2);
p += 2;
degreebuff[2] = '\0';
@ -343,8 +357,8 @@ void Adafruit_GPS::parseLat(char *p) {
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);
latitudeDegrees = (latitude - 100 * int(latitude / 100)) / 60.0;
latitudeDegrees += int(latitude / 100);
}
}
@ -380,8 +394,7 @@ void Adafruit_GPS::parseLon(char *p) {
int32_t degree;
long minutes;
char degreebuff[10];
if (',' != *p)
{
if (',' != *p) {
strncpy(degreebuff, p, 3);
p += 3;
degreebuff[3] = '\0';
@ -393,8 +406,8 @@ void Adafruit_GPS::parseLon(char *p) {
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);
longitudeDegrees = (longitude - 100 * int(longitude / 100)) / 60.0;
longitudeDegrees += int(longitude / 100);
}
}
@ -406,8 +419,7 @@ void Adafruit_GPS::parseLon(char *p) {
*/
/**************************************************************************/
boolean Adafruit_GPS::parseLonDir(char *p) {
if (',' != *p)
{
if (',' != *p) {
if (p[0] == 'W') {
lon = 'W';
longitudeDegrees *= -1.0;
@ -431,11 +443,10 @@ boolean Adafruit_GPS::parseLonDir(char *p) {
*/
/**************************************************************************/
boolean Adafruit_GPS::parseFix(char *p) {
if (p[0] == 'A'){
if (p[0] == 'A') {
fix = true;
lastFix = sentTime;
}
else if (p[0] == 'V')
} else if (p[0] == 'V')
fix = false;
else
return false;
@ -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
*/
@ -550,10 +559,11 @@ char Adafruit_GPS::read(void) {
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,11 +580,12 @@ char Adafruit_GPS::read(void) {
_buff_idx++;
} else {
// refill the buffer!
if (gpsI2C->requestFrom(0x10, GPS_MAX_I2C_TRANSFER, true) == GPS_MAX_I2C_TRANSFER) {
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++) {
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
@ -606,14 +617,16 @@ char Adafruit_GPS::read(void) {
}
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,9 +639,9 @@ 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
@ -637,7 +650,8 @@ char Adafruit_GPS::read(void) {
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.
}
@ -690,7 +703,6 @@ Adafruit_GPS::Adafruit_GPS(SPIClass *theSPI, int8_t cspin) {
gpsSPI_cs = cspin;
}
/**************************************************************************/
/*!
@brief Initialization code used by all constructor types
@ -709,13 +721,13 @@ void Adafruit_GPS::common_init(void) {
currentline = line1;
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
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,7 +809,8 @@ 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
@ -816,7 +822,7 @@ uint8_t Adafruit_GPS::parseHex(char c) {
if (c < 'A')
return 0;
if (c <= 'F')
return (c - 'A')+10;
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();
@ -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;
}
}
@ -953,8 +962,7 @@ boolean Adafruit_GPS::wakeup(void) {
inStandbyMode = false;
sendCommand(""); // send byte to wake it up
return waitForSentence(PMTK_AWAKE);
}
else {
} 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;

View File

@ -26,36 +26,46 @@
#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 <SoftwareSerial.h>
#include <SoftwareSerial.h>
#endif
#include <Wire.h>
#include <SPI.h>
#include <Wire.h>
/**************************************************************************/
/**
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.
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_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!
@ -64,43 +74,67 @@
#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_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_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_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 \
"$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 PGCMD_ANTENNA "$PGCMD,33,1*6C" ///< request for updates on antenna status
#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()
@ -118,8 +152,8 @@ typedef enum {
/*!
@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)
@ -154,10 +188,16 @@ class Adafruit_GPS : public Print{
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
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
@ -167,11 +207,14 @@ class Adafruit_GPS : public Print{
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
@ -183,9 +226,12 @@ class Adafruit_GPS : public Print{
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
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
@ -194,7 +240,8 @@ class Adafruit_GPS : public Print{
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);
@ -210,8 +257,8 @@ class Adafruit_GPS : public Print{
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
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
// 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
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,16 +294,19 @@ 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 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

View File

@ -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