diff --git a/Adafruit_GPS.cpp b/Adafruit_GPS.cpp index acf5f30..3689f33 100644 --- a/Adafruit_GPS.cpp +++ b/Adafruit_GPS.cpp @@ -202,11 +202,11 @@ char Adafruit_GPS::read(void) { // Constructor when using SoftwareSerial or NewSoftSerial #if ARDUINO >= 100 -Adafruit_GPS::Adafruit_GPS(SoftwareSerial *ser) { +Adafruit_GPS::Adafruit_GPS(SoftwareSerial *ser) #else - Adafruit_GPS::Adafruit_GPS(NewSoftSerial *ser) { + Adafruit_GPS::Adafruit_GPS(NewSoftSerial *ser) #endif - +{ common_init(); // Set everything to common state, then... gpsSwSerial = ser; // ...override swSerial with value passed. @@ -230,38 +230,6 @@ void Adafruit_GPS::begin(uint16_t baud) 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; @@ -301,3 +269,76 @@ uint8_t Adafruit_GPS::parseHex(char c) { if (c <= 'F') return (c - 'A')+10; } + + +boolean Adafruit_GPS::waitForSentence(char *wait4me, uint8_t max) { + char str[20]; + + uint8_t i=0; + while (i < max) { + if (newNMEAreceived()) { + char *nmea = lastNMEA(); + strncpy(str, nmea, 20); + str[19] = 0; + i++; + + if (strstr(str, wait4me)) + return true; + } + } + + return false; +} + +boolean Adafruit_GPS::LOCUS_StartLogger(void) { + sendCommand(PMTK_LOCUS_STARTLOG); + recvdflag = false; + return waitForSentence(PMTK_LOCUS_LOGSTARTED); +} + + +boolean Adafruit_GPS::LOCUS_ReadStatus(void) { + sendCommand(PMTK_LOCUS_QUERY_STATUS); + + if (! waitForSentence("$PMTKLOG")) + return false; + + char *response = lastNMEA(); + uint16_t parsed[10]; + uint8_t i; + + for (i=0; i<10; i++) parsed[i] = -1; + + response = strchr(response, ','); + 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] *= 10; + char c = response[0]; + if (isDigit(c)) + parsed[i] += c - '0'; + else + parsed[i] = c; + response++; + } + } + LOCUS_serial = parsed[0]; + LOCUS_type = parsed[1]; + if (isAlpha(parsed[2])) { + parsed[2] = parsed[2] - 'a' + 10; + } + LOCUS_mode = parsed[2]; + LOCUS_config = parsed[3]; + LOCUS_interval = parsed[4]; + LOCUS_distance = parsed[5]; + LOCUS_speed = parsed[6]; + LOCUS_status = !parsed[7]; + LOCUS_records = parsed[8]; + LOCUS_percent = parsed[9]; + + return true; +} diff --git a/Adafruit_GPS.h b/Adafruit_GPS.h index f040878..7f63035 100644 --- a/Adafruit_GPS.h +++ b/Adafruit_GPS.h @@ -35,9 +35,15 @@ All text above must be included in any redistribution // 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" +#define PMTK_LOCUS_LOGSTARTED "$PMTK001,185,3*3C" #define PMTK_LOCUS_QUERY_STATUS "$PMTK183*38" +#define LOCUS_OVERLAP 0 +#define LOCUS_FULLSTOP 1 +// how long to wait when we're looking for a response +#define MAXWAITSENTENCE 5 #if ARDUINO >= 100 #include "Arduino.h" @@ -80,6 +86,12 @@ class Adafruit_GPS { boolean fix; uint8_t fixquality, satellites; + boolean waitForSentence(char *wait, uint8_t max = MAXWAITSENTENCE); + boolean LOCUS_StartLogger(void); + boolean LOCUS_ReadStatus(void); + + uint16_t LOCUS_serial, LOCUS_records; + uint8_t LOCUS_type, LOCUS_mode, LOCUS_config, LOCUS_interval, LOCUS_distance, LOCUS_speed, LOCUS_status, LOCUS_percent; private: boolean paused; diff --git a/examples/locus_start/locus_start.pde b/examples/locus_start/locus_start.pde new file mode 100644 index 0000000..a550c1f --- /dev/null +++ b/examples/locus_start/locus_start.pde @@ -0,0 +1,101 @@ +// Test code for Adafruit GPS modules using MTK3329/MTK3339 driver +// +// This code turns on the LOCUS built-in datalogger. The datalogger +// turns off when power is lost, so you MUST turn it on every time +// you want to use it! +// +// Tested and works great with the Adafruit Ultimate GPS module +// using MTK33x9 chipset +// ------> http://www.adafruit.com/products/746 +// Pick one up today at the Adafruit electronics shop +// and help support open source hardware & software! -ada + +#include + +// these are for Arduino 1.0 +#include +SoftwareSerial mySerial(3, 2); + +// if using Arduino v23 or earlier, uncomment these +// two lines and comment out the above. You will +// need to install NewSoftSerial +// #include +// NewSoftSerial mySerial(3, 2); + +// Connect the GPS Power pin to 5V +// Connect the GPS Ground pin to ground +// Connect the GPS TX (transmit) pin to Digital 3 +// Connect the GPS RX (receive) pin to Digital 2 +Adafruit_GPS GPS(&mySerial); + +// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console +// Set to 'true' if you want to debug and listen to the raw GPS sentences +#define GPSECHO true + +// this keeps track of whether we're using the interrupt +// off by default! +boolean usingInterrupt = false; + +void setup() +{ + // connect at 115200 so we can read the GPS fast enuf and + // also spit it out + Serial.begin(115200); + Serial.println("Adafruit GPS logging start test!"); + + // 9600 NMEA is the default baud rate for MTK - some use 4800 + GPS.begin(9600); + + // You can adjust which sentences to have the module emit, below + // Default is RMC + GGA + GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); + // Default is 1 Hz update rate + GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); + + // the nice thing about this code is you can have a timer0 interrupt go off + // every 1 millisecond, and read data from the GPS for you. that makes the + // loop code a heck of a lot easier! + useInterrupt(true); + + Serial.print("STARTING LOGGING...."); + if (GPS.LOCUS_StartLogger()) + Serial.println(" STARTED!"); + else + Serial.println(" no response :("); + delay(1000); +} + + + +void loop() // run over and over again +{ + // do nothing! all reading and printing is done in the interrupt +} + +/******************************************************************/ +// Interrupt is called once a millisecond, looks for any new GPS data, and stores it +SIGNAL(TIMER0_COMPA_vect) { + char c = GPS.read(); + // if you want to debug, this is a good time to do it! + if (GPSECHO) + if (c) UDR0 = c; + // writing direct to UDR0 is much much faster than Serial.print + // but only one character can be written at a time. +} + +void useInterrupt(boolean v) { + if (v) { + // Timer0 is already used for millis() - we'll just interrupt somewhere + // in the middle and call the "Compare A" function above + OCR0A = 0xAF; + TIMSK0 |= _BV(OCIE0A); + usingInterrupt = true; + } else { + // do not call the interrupt function COMPA anymore + TIMSK0 &= ~_BV(OCIE0A); + usingInterrupt = false; + } +} + + + diff --git a/examples/locus_status/locus_status.pde b/examples/locus_status/locus_status.pde new file mode 100644 index 0000000..4f45d2f --- /dev/null +++ b/examples/locus_status/locus_status.pde @@ -0,0 +1,134 @@ +// Test code for Adafruit GPS modules using MTK3329/MTK3339 driver +// +// This code turns on the LOCUS built-in datalogger. The datalogger +// turns off when power is lost, so you MUST turn it on every time +// you want to use it! +// +// Tested and works great with the Adafruit Ultimate GPS module +// using MTK33x9 chipset +// ------> http://www.adafruit.com/products/746 +// Pick one up today at the Adafruit electronics shop +// and help support open source hardware & software! -ada + +#include + +// these are for Arduino 1.0 +#include +SoftwareSerial mySerial(3, 2); + +// if using Arduino v23 or earlier, uncomment these +// two lines and comment out the above. You will +// need to install NewSoftSerial +// #include +// NewSoftSerial mySerial(3, 2); + +// Connect the GPS Power pin to 5V +// Connect the GPS Ground pin to ground +// Connect the GPS TX (transmit) pin to Digital 3 +// Connect the GPS RX (receive) pin to Digital 2 +Adafruit_GPS GPS(&mySerial); + +// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console +// Set to 'true' if you want to debug and listen to the raw GPS sentences +#define GPSECHO false + +// this keeps track of whether we're using the interrupt +// off by default! +boolean usingInterrupt = false; + +void setup() +{ + // connect at 115200 so we can read the GPS fast enuf and + // also spit it out + Serial.begin(115200); + Serial.println("Adafruit GPS logging start test!"); + + // 9600 NMEA is the default baud rate for MTK - some use 4800 + GPS.begin(9600); + + // You can adjust which sentences to have the module emit, below + // Default is RMC + GGA + GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); + // Default is 1 Hz update rate + GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); + + // the nice thing about this code is you can have a timer0 interrupt go off + // every 1 millisecond, and read data from the GPS for you. that makes the + // loop code a heck of a lot easier! + useInterrupt(true); + + while (true) { + Serial.print("Starting logging...."); + if (GPS.LOCUS_StartLogger()) { + Serial.println(" STARTED!"); + break; + } else { + Serial.println(" no response :("); + } + } +} + + + +void loop() // run over and over again +{ + delay(1000); + + if (GPS.LOCUS_ReadStatus()) { + Serial.print("\n\nLog #"); + Serial.print(GPS.LOCUS_serial, DEC); + if (GPS.LOCUS_type == LOCUS_OVERLAP) + Serial.print(", Overlap, "); + else if (GPS.LOCUS_type == LOCUS_FULLSTOP) + Serial.print(", Full Stop, Logging"); + + if (GPS.LOCUS_mode & 0x1) Serial.print(" AlwaysLocate"); + if (GPS.LOCUS_mode & 0x2) Serial.print(" FixOnly"); + if (GPS.LOCUS_mode & 0x4) Serial.print(" Normal"); + if (GPS.LOCUS_mode & 0x8) Serial.print(" Interval"); + if (GPS.LOCUS_mode & 0x10) Serial.print(" Distance"); + if (GPS.LOCUS_mode & 0x20) Serial.print(" Speed"); + + Serial.print(", Content "); Serial.print(GPS.LOCUS_config); + Serial.print(", Interval "); Serial.print(GPS.LOCUS_interval); + Serial.print(" sec, Distance "); Serial.print(GPS.LOCUS_distance); + Serial.print(" m, Speed "); Serial.print(GPS.LOCUS_speed); + Serial.print(" m/s, Status "); + if (GPS.LOCUS_status) + Serial.print("LOGGING, "); + else + Serial.print("OFF, "); + Serial.print(GPS.LOCUS_records); Serial.print(" Records, "); + Serial.print(GPS.LOCUS_percent); Serial.print("% Used "); + + } +} + +/******************************************************************/ +// Interrupt is called once a millisecond, looks for any new GPS data, and stores it +SIGNAL(TIMER0_COMPA_vect) { + char c = GPS.read(); + // if you want to debug, this is a good time to do it! + if (GPSECHO) + if (c) UDR0 = c; + // writing direct to UDR0 is much much faster than Serial.print + // but only one character can be written at a time. + +} + +void useInterrupt(boolean v) { + if (v) { + // Timer0 is already used for millis() - we'll just interrupt somewhere + // in the middle and call the "Compare A" function above + OCR0A = 0xAF; + TIMSK0 |= _BV(OCIE0A); + usingInterrupt = true; + } else { + // do not call the interrupt function COMPA anymore + TIMSK0 &= ~_BV(OCIE0A); + usingInterrupt = false; + } +} + + +