esp32_Adafruit_GPS/Adafruit_GPS.cpp

304 lines
6.4 KiB
C++
Raw Normal View History

2012-03-27 22:56:07 +01:00
/***********************************
This is a our GPS library
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, check license.txt for more information
All text above must be included in any redistribution
****************************************/
#include <Adafruit_GPS.h>
// how long are max NMEA lines to parse?
#define MAXLINELENGTH 120
2012-03-27 22:56:07 +01:00
// we double buffer: read one line in and leave one for the main program
volatile char line1[MAXLINELENGTH];
volatile char line2[MAXLINELENGTH];
// our index into filling the current line
volatile uint8_t lineidx=0;
// pointers to the double buffers
volatile char *currentline;
volatile char *lastline;
volatile boolean recvdflag;
boolean Adafruit_GPS::parse(char *nmea) {
// do checksum check
2012-03-27 22:56:07 +01:00
// first look if we even have one
if (nmea[strlen(nmea)-4] == '*') {
uint16_t sum = parseHex(nmea[strlen(nmea)-3]) * 16;
sum += parseHex(nmea[strlen(nmea)-2]);
// check checksum
for (uint8_t i=1; i < (strlen(nmea)-4); i++) {
sum ^= nmea[i];
}
if (sum != 0) {
// bad checksum :(
//return false;
}
}
2012-03-27 22:56:07 +01:00
// look for a few common sentences
2012-03-27 22:56:07 +01:00
if (strstr(nmea, "$GPGGA")) {
// found GGA
char *p = nmea;
// get time
p = strchr(p, ',')+1;
float timef = atof(p);
uint32_t time = timef;
hour = time / 10000;
minute = (time % 10000) / 100;
seconds = (time % 100);
milliseconds = fmod(timef, 1.0) * 1000;
// parse out latitude
p = strchr(p, ',')+1;
latitude = atof(p);
p = strchr(p, ',')+1;
if (p[0] == 'N') lat = 'N';
else if (p[0] == 'S') lat = 'S';
else if (p[0] == ',') lat = 0;
else return false;
// parse out longitude
p = strchr(p, ',')+1;
longitude = atof(p);
p = strchr(p, ',')+1;
if (p[0] == 'W') lon = 'W';
else if (p[0] == 'E') lon = 'E';
else if (p[0] == ',') lon = 0;
else return false;
p = strchr(p, ',')+1;
fixquality = atoi(p);
p = strchr(p, ',')+1;
satellites = atoi(p);
p = strchr(p, ',')+1;
HDOP = atof(p);
p = strchr(p, ',')+1;
altitude = atof(p);
p = strchr(p, ',')+1;
p = strchr(p, ',')+1;
geoidheight = atof(p);
return true;
}
if (strstr(nmea, "$GPRMC")) {
// found RMC
2012-03-27 22:56:07 +01:00
char *p = nmea;
// get time
p = strchr(p, ',')+1;
float timef = atof(p);
uint32_t time = timef;
hour = time / 10000;
minute = (time % 10000) / 100;
seconds = (time % 100);
milliseconds = fmod(timef, 1.0) * 1000;
p = strchr(p, ',')+1;
// Serial.println(p);
2012-03-27 22:56:07 +01:00
if (p[0] == 'A')
fix = true;
else if (p[0] == 'V')
fix = false;
else
return false;
// parse out latitude
p = strchr(p, ',')+1;
latitude = atof(p);
p = strchr(p, ',')+1;
if (p[0] == 'N') lat = 'N';
else if (p[0] == 'S') lat = 'S';
else if (p[0] == ',') lat = 0;
else return false;
// parse out longitude
p = strchr(p, ',')+1;
longitude = atof(p);
p = strchr(p, ',')+1;
if (p[0] == 'W') lon = 'W';
else if (p[0] == 'E') lon = 'E';
else if (p[0] == ',') lon = 0;
else return false;
// speed
p = strchr(p, ',')+1;
speed = atof(p);
// angle
p = strchr(p, ',')+1;
angle = atof(p);
p = strchr(p, ',')+1;
uint32_t fulldate = atof(p);
day = fulldate / 10000;
month = (fulldate % 10000) / 100;
year = (fulldate % 100);
// we dont parse the remaining, yet!
return true;
}
return false;
}
char Adafruit_GPS::read(void) {
char c = 0;
2012-03-27 22:56:07 +01:00
if (paused)
return c;
2012-03-27 22:56:07 +01:00
if (gpsSwSerial->available()) {
c = gpsSwSerial->read();
2012-03-27 22:56:07 +01:00
//Serial.print(c);
if (c == '$') {
currentline[lineidx] = 0;
lineidx = 0;
}
if (c == '\n') {
currentline[lineidx] = 0;
if (currentline == line1) {
currentline = line2;
lastline = line1;
} else {
currentline = line1;
lastline = line2;
}
//Serial.println("----");
//Serial.println((char *)lastline);
//Serial.println("----");
2012-03-27 22:56:07 +01:00
lineidx = 0;
recvdflag = true;
2012-03-27 22:56:07 +01:00
}
2012-03-27 22:56:07 +01:00
currentline[lineidx++] = c;
if (lineidx >= MAXLINELENGTH)
lineidx = MAXLINELENGTH-1;
}
return c;
2012-03-27 22:56:07 +01:00
}
// Constructor when using SoftwareSerial or NewSoftSerial
#if ARDUINO >= 100
Adafruit_GPS::Adafruit_GPS(SoftwareSerial *ser) {
#else
Adafruit_GPS::Adafruit_GPS(NewSoftSerial *ser) {
#endif
2012-03-27 22:56:07 +01:00
common_init(); // Set everything to common state, then...
gpsSwSerial = ser; // ...override swSerial with value passed.
2012-03-27 22:56:07 +01:00
recvdflag = false;
paused = false;
lineidx = 0;
currentline = line1;
lastline = line2;
2012-03-27 23:20:41 +01:00
hour = minute = seconds = year = month = day = milliseconds = 0;
latitude = longitude = geoidheight = altitude = 0;
speed = angle = magvariation = HDOP = 0;
lat = lon = mag = 0;
fix = false;
fixquality = satellites = 0;
2012-03-27 22:56:07 +01:00
}
void Adafruit_GPS::begin(uint16_t baud)
{
2012-03-27 22:56:07 +01:00
gpsSwSerial->begin(baud);
}
static uint16_t parsed[25];
uint8_t Adafruit_GPS::parseResponse(char *response) {
uint8_t i;
for (i=0; i<25; i++) parsed[i] = -1;
response = strstr(response, ",");
for (i=0; i<25; i++) {
if (!response || (response[0] == 0) || (response[0] == '*'))
return i;
response++;
parsed[i]=0;
while ((response[0] != ',') && (response[0] != '*') && (response[0] != 0)) {
parsed[i] *= 10;
char c = response[0];
//Serial.print("("); Serial.write(c); Serial.print(")");
if (isDigit(c))
parsed[i] += c - '0';
else
parsed[i] = c;
response++;
}
//Serial.print(i); Serial.print(" ");
//Serial.println(parsed[i]);
//Serial.println(response);
}
return i;
}
// Initialization code used by all constructor types
void Adafruit_GPS::common_init(void) {
gpsSwSerial = NULL;
gpsHwSerial = NULL;
}
void Adafruit_GPS::sendCommand(char *str) {
gpsSwSerial->println(str);
}
boolean Adafruit_GPS::newNMEAreceived(void) {
return recvdflag;
}
void Adafruit_GPS::pause(boolean p) {
paused = p;
}
char *Adafruit_GPS::lastNMEA(void) {
recvdflag = false;
return (char *)lastline;
}
// 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;
}