1 /***********************************
2 This is our GPS library
4 Adafruit invests time and resources providing this open source code,
5 please support Adafruit and open-source hardware by purchasing
6 products from Adafruit!
8 Written by Limor Fried/Ladyada for Adafruit Industries.
9 BSD license, check license.txt for more information
10 All text above must be included in any redistribution
11 ****************************************/
13 #include <Adafruit_GPS.h>
15 // how long are max NMEA lines to parse?
16 #define MAXLINELENGTH 120
18 // we double buffer: read one line in and leave one for the main program
19 volatile char line1[MAXLINELENGTH];
20 volatile char line2[MAXLINELENGTH];
21 // our index into filling the current line
22 volatile uint8_t lineidx=0;
23 // pointers to the double buffers
24 volatile char *currentline;
25 volatile char *lastline;
26 volatile boolean recvdflag;
27 volatile boolean inStandbyMode;
30 boolean Adafruit_GPS::parse(char *nmea) {
33 // first look if we even have one
34 if (nmea[strlen(nmea)-4] == '*') {
35 uint16_t sum = parseHex(nmea[strlen(nmea)-3]) * 16;
36 sum += parseHex(nmea[strlen(nmea)-2]);
39 for (uint8_t i=1; i < (strlen(nmea)-4); i++) {
48 // look for a few common sentences
49 if (strstr(nmea, "$GPGGA")) {
54 float timef = atof(p);
55 uint32_t time = timef;
57 minute = (time % 10000) / 100;
58 seconds = (time % 100);
60 milliseconds = fmod(timef, 1.0) * 1000;
67 if (p[0] == 'N') lat = 'N';
68 else if (p[0] == 'S') lat = 'S';
69 else if (p[0] == ',') lat = 0;
72 // parse out longitude
77 if (p[0] == 'W') lon = 'W';
78 else if (p[0] == 'E') lon = 'E';
79 else if (p[0] == ',') lon = 0;
95 geoidheight = atof(p);
98 if (strstr(nmea, "$GPRMC")) {
103 p = strchr(p, ',')+1;
104 float timef = atof(p);
105 uint32_t time = timef;
107 minute = (time % 10000) / 100;
108 seconds = (time % 100);
110 milliseconds = fmod(timef, 1.0) * 1000;
112 p = strchr(p, ',')+1;
113 // Serial.println(p);
116 else if (p[0] == 'V')
121 // parse out latitude
122 p = strchr(p, ',')+1;
125 p = strchr(p, ',')+1;
126 if (p[0] == 'N') lat = 'N';
127 else if (p[0] == 'S') lat = 'S';
128 else if (p[0] == ',') lat = 0;
131 // parse out longitude
132 p = strchr(p, ',')+1;
135 p = strchr(p, ',')+1;
136 if (p[0] == 'W') lon = 'W';
137 else if (p[0] == 'E') lon = 'E';
138 else if (p[0] == ',') lon = 0;
142 p = strchr(p, ',')+1;
146 p = strchr(p, ',')+1;
149 p = strchr(p, ',')+1;
150 uint32_t fulldate = atof(p);
151 day = fulldate / 10000;
152 month = (fulldate % 10000) / 100;
153 year = (fulldate % 100);
155 // we dont parse the remaining, yet!
162 char Adafruit_GPS::read(void) {
165 if (paused) return c;
168 if(!gpsSwSerial->available()) return c;
169 c = gpsSwSerial->read();
171 if(!gpsHwSerial->available()) return c;
172 c = gpsHwSerial->read();
178 currentline[lineidx] = 0;
182 currentline[lineidx] = 0;
184 if (currentline == line1) {
192 //Serial.println("----");
193 //Serial.println((char *)lastline);
194 //Serial.println("----");
199 currentline[lineidx++] = c;
200 if (lineidx >= MAXLINELENGTH)
201 lineidx = MAXLINELENGTH-1;
206 // Constructor when using SoftwareSerial or NewSoftSerial
208 Adafruit_GPS::Adafruit_GPS(SoftwareSerial *ser)
210 Adafruit_GPS::Adafruit_GPS(NewSoftSerial *ser)
213 common_init(); // Set everything to common state, then...
214 gpsSwSerial = ser; // ...override gpsSwSerial with value passed.
217 // Constructor when using HardwareSerial
218 Adafruit_GPS::Adafruit_GPS(HardwareSerial *ser) {
219 common_init(); // Set everything to common state, then...
220 gpsHwSerial = ser; // ...override gpsHwSerial with value passed.
223 // Initialization code used by all constructor types
224 void Adafruit_GPS::common_init(void) {
225 gpsSwSerial = NULL; // Set both to NULL, then override correct
226 gpsHwSerial = NULL; // port pointer in corresponding constructor
233 hour = minute = seconds = year = month = day =
234 fixquality = satellites = 0; // uint8_t
235 lat = lon = mag = 0; // char
236 fix = false; // boolean
237 milliseconds = 0; // uint16_t
238 latitude = longitude = geoidheight = altitude =
239 speed = angle = magvariation = HDOP = 0.0; // float
242 void Adafruit_GPS::begin(uint16_t baud)
244 if(gpsSwSerial) gpsSwSerial->begin(baud);
245 else gpsHwSerial->begin(baud);
250 void Adafruit_GPS::sendCommand(char *str) {
251 if(gpsSwSerial) gpsSwSerial->println(str);
252 else gpsHwSerial->println(str);
255 boolean Adafruit_GPS::newNMEAreceived(void) {
259 void Adafruit_GPS::pause(boolean p) {
263 char *Adafruit_GPS::lastNMEA(void) {
265 return (char *)lastline;
268 // read a Hex value and return the decimal equivalent
269 uint8_t Adafruit_GPS::parseHex(char c) {
280 boolean Adafruit_GPS::waitForSentence(char *wait4me, uint8_t max) {
285 if (newNMEAreceived()) {
286 char *nmea = lastNMEA();
287 strncpy(str, nmea, 20);
291 if (strstr(str, wait4me))
299 boolean Adafruit_GPS::LOCUS_StartLogger(void) {
300 sendCommand(PMTK_LOCUS_STARTLOG);
302 return waitForSentence(PMTK_LOCUS_LOGSTARTED);
305 boolean Adafruit_GPS::LOCUS_ReadStatus(void) {
306 sendCommand(PMTK_LOCUS_QUERY_STATUS);
308 if (! waitForSentence("$PMTKLOG"))
311 char *response = lastNMEA();
315 for (i=0; i<10; i++) parsed[i] = -1;
317 response = strchr(response, ',');
318 for (i=0; i<10; i++) {
319 if (!response || (response[0] == 0) || (response[0] == '*'))
323 while ((response[0] != ',') &&
324 (response[0] != '*') && (response[0] != 0)) {
326 char c = response[0];
328 parsed[i] += c - '0';
334 LOCUS_serial = parsed[0];
335 LOCUS_type = parsed[1];
336 if (isAlpha(parsed[2])) {
337 parsed[2] = parsed[2] - 'a' + 10;
339 LOCUS_mode = parsed[2];
340 LOCUS_config = parsed[3];
341 LOCUS_interval = parsed[4];
342 LOCUS_distance = parsed[5];
343 LOCUS_speed = parsed[6];
344 LOCUS_status = !parsed[7];
345 LOCUS_records = parsed[8];
346 LOCUS_percent = parsed[9];
351 // Standby Mode Switches
352 boolean Adafruit_GPS::standby(void) {
354 return false; // Returns false if already in standby mode, so that you do not wake it up by sending commands to GPS
357 inStandbyMode = true;
358 sendCommand(PMTK_STANDBY);
359 //return waitForSentence(PMTK_STANDBY_SUCCESS); // don't seem to be fast enough to catch the message, or something else just is not working
364 boolean Adafruit_GPS::wakeup(void) {
366 inStandbyMode = false;
367 sendCommand(""); // send byte to wake it up
368 return waitForSentence(PMTK_AWAKE);
371 return false; // Returns false if not in standby mode, nothing to wakeup