From 1319d079bf2e34596903727a04bae6e60d053264 Mon Sep 17 00:00:00 2001 From: driverblock Date: Mon, 24 Mar 2014 16:09:24 -0400 Subject: [PATCH] Add support for Arduino Due Conditional compilation for Arduino Due. Due support is hardcoded for Serial1 Added due_parsing and due_shield_sdlog examples --- Adafruit_GPS.cpp | 40 +++- Adafruit_GPS.h | 36 ++-- examples/due_parsing/due_parsing.ino | 178 ++++++++++++++++++ .../due_shield_sdlog/due_shield_sdlog.ino | 174 +++++++++++++++++ 4 files changed, 405 insertions(+), 23 deletions(-) create mode 100644 examples/due_parsing/due_parsing.ino create mode 100644 examples/due_shield_sdlog/due_shield_sdlog.ino diff --git a/Adafruit_GPS.cpp b/Adafruit_GPS.cpp index 65b8b1e..7e07449 100644 --- a/Adafruit_GPS.cpp +++ b/Adafruit_GPS.cpp @@ -164,13 +164,23 @@ char Adafruit_GPS::read(void) { if (paused) return c; +#ifdef __AVR__ if(gpsSwSerial) { if(!gpsSwSerial->available()) return c; c = gpsSwSerial->read(); - } else { + } + else + { if(!gpsHwSerial->available()) return c; c = gpsHwSerial->read(); } +#else + // if(!gpsHwSerial->available()) return c; + // c = gpsHwSerial->read(); + if(!Serial1.available()) return c; + c = Serial1.read(); +#endif + //Serial.print(c); @@ -203,6 +213,7 @@ char Adafruit_GPS::read(void) { return c; } +#ifdef __AVR__ // Constructor when using SoftwareSerial or NewSoftSerial #if ARDUINO >= 100 Adafruit_GPS::Adafruit_GPS(SoftwareSerial *ser) @@ -213,8 +224,8 @@ Adafruit_GPS::Adafruit_GPS(NewSoftSerial *ser) common_init(); // Set everything to common state, then... gpsSwSerial = ser; // ...override gpsSwSerial with value passed. } +#endif -// Constructor when using HardwareSerial Adafruit_GPS::Adafruit_GPS(HardwareSerial *ser) { common_init(); // Set everything to common state, then... gpsHwSerial = ser; // ...override gpsHwSerial with value passed. @@ -222,8 +233,6 @@ Adafruit_GPS::Adafruit_GPS(HardwareSerial *ser) { // Initialization code used by all constructor types void Adafruit_GPS::common_init(void) { - gpsSwSerial = NULL; // Set both to NULL, then override correct - gpsHwSerial = NULL; // port pointer in corresponding constructor recvdflag = false; paused = false; lineidx = 0; @@ -241,15 +250,30 @@ void Adafruit_GPS::common_init(void) { void Adafruit_GPS::begin(uint16_t baud) { - if(gpsSwSerial) gpsSwSerial->begin(baud); - else gpsHwSerial->begin(baud); +#ifdef __AVR__ + if(gpsSwSerial) + gpsSwSerial->begin(baud); + else + gpsHwSerial->begin(baud); +#else + // gpsHwSerial->begin(baud); + Serial1.begin(baud); +#endif delay(10); } void Adafruit_GPS::sendCommand(char *str) { - if(gpsSwSerial) gpsSwSerial->println(str); - else gpsHwSerial->println(str); +#ifdef __AVR__ + if(gpsSwSerial) + gpsSwSerial->println(str); + else + gpsHwSerial->println(str); +#else + // gpsHwSerial->println(str); + Serial1.println(str); +#endif + } boolean Adafruit_GPS::newNMEAreceived(void) { diff --git a/Adafruit_GPS.h b/Adafruit_GPS.h index 4474dc6..231f009 100644 --- a/Adafruit_GPS.h +++ b/Adafruit_GPS.h @@ -20,10 +20,12 @@ All text above must be included in any redistribution #ifndef _ADAFRUIT_GPS_H #define _ADAFRUIT_GPS_H -#if ARDUINO >= 100 - #include -#else - #include +#ifdef __AVR__ + #if ARDUINO >= 100 + #include + #else + #include + #endif #endif // different commands to set the update rate from once a second (1 Hz) to 10 times a second (10Hz) @@ -64,14 +66,14 @@ All text above must be included in any redistribution // request for updates on antenna status #define PGCMD_ANTENNA "$PGCMD,33,1*6C" -#define PGCMD_NOANTENNA "$PGCMD,33,0*6D" +#define PGCMD_NOANTENNA "$PGCMD,33,0*6C" // how long to wait when we're looking for a response #define MAXWAITSENTENCE 5 #if ARDUINO >= 100 #include "Arduino.h" -#if !defined(__AVR_ATmega32U4__) +#if defined (__AVR__) && !defined(__AVR_ATmega32U4__) #include "SoftwareSerial.h" #endif #else @@ -84,10 +86,12 @@ class Adafruit_GPS { public: void begin(uint16_t baud); -#if ARDUINO >= 100 - Adafruit_GPS(SoftwareSerial *ser); // Constructor when using SoftwareSerial -#else - Adafruit_GPS(NewSoftSerial *ser); // Constructor when using NewSoftSerial +#ifdef __AVR__ + #if ARDUINO >= 100 + Adafruit_GPS(SoftwareSerial *ser); // Constructor when using SoftwareSerial + #else + Adafruit_GPS(NewSoftSerial *ser); // Constructor when using NewSoftSerial + #endif #endif Adafruit_GPS(HardwareSerial *ser); // Constructor when using HardwareSerial @@ -105,7 +109,7 @@ class Adafruit_GPS { void interruptReads(boolean r); boolean wakeup(void); - boolean standby(void); + boolean standby(void); uint8_t hour, minute, seconds, year, month, day; uint16_t milliseconds; @@ -125,10 +129,12 @@ class Adafruit_GPS { boolean paused; uint8_t parseResponse(char *response); -#if ARDUINO >= 100 - SoftwareSerial *gpsSwSerial; -#else - NewSoftSerial *gpsSwSerial; +#ifdef __AVR__ + #if ARDUINO >= 100 + SoftwareSerial *gpsSwSerial; + #else + NewSoftSerial *gpsSwSerial; + #endif #endif HardwareSerial *gpsHwSerial; }; diff --git a/examples/due_parsing/due_parsing.ino b/examples/due_parsing/due_parsing.ino new file mode 100644 index 0000000..a1e9ea5 --- /dev/null +++ b/examples/due_parsing/due_parsing.ino @@ -0,0 +1,178 @@ +// Test code for Adafruit GPS modules using MTK3329/MTK3339 driver +// +// This code shows how to listen to the GPS module in an interrupt +// which allows the program to have more 'freedom' - just parse +// when a new NMEA sentence is available! Then access data when +// desired. +// +// 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 + +#ifdef __AVR__ + #include +#endif + +// If you're using a GPS module: +// Connect the GPS Power pin to 5V +// Connect the GPS Ground pin to ground +// If using software serial (sketch example default): +// Connect the GPS TX (transmit) pin to Digital 3 +// Connect the GPS RX (receive) pin to Digital 2 +// If using hardware serial (e.g. Arduino Mega): +// Connect the GPS TX (transmit) pin to Arduino RX1, RX2 or RX3 +// Connect the GPS RX (receive) pin to matching TX1, TX2 or TX3 + +// If you're using the Adafruit GPS shield, change +// SoftwareSerial mySerial(3, 2); -> SoftwareSerial mySerial(8, 7); +// and make sure the switch is set to SoftSerial + +// If using software serial, keep this line enabled +// (you can change the pin numbers to match your wiring): +//SoftwareSerial mySerial(3, 2); + +// If using hardware serial (e.g. Arduino Mega, Leonardo, Due), comment +// out the above line and enable this line instead: +#define mySerial Serial1 + +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 useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy + +void setup() +{ + + // connect at 115200 so we can read the GPS fast enough and echo without dropping chars + // also spit it out + Serial.begin(115200); + Serial.println("Adafruit GPS library basic test!"); + + // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800 + GPS.begin(9600); + mySerial.begin(9600); + + // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude + GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); + // uncomment this line to turn on only the "minimum recommended" data + //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY); + // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since + // the parser doesn't care about other sentences at this time + + // Set the update rate + GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate + // For the parsing code to work nicely and have time to sort thru the data, and + // print it out we don't suggest using anything higher than 1 Hz + + // Request updates on antenna status, comment out to keep quiet + GPS.sendCommand(PGCMD_ANTENNA); + + // 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! + +#ifdef __arm__ + usingInterrupt = false; //NOTE - we don't want to use interrupts on the Due +#else + useInterrupt(true); +#endif + + delay(1000); + // Ask for firmware version + mySerial.println(PMTK_Q_RELEASE); +} + +#ifdef __AVR__ +// 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! +#ifdef UDR0 + 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. +#endif +} + +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; + } +} +#endif //#ifdef__AVR__ + +uint32_t timer = millis(); +void loop() // run over and over again +{ + // in case you are not using the interrupt above, you'll + // need to 'hand query' the GPS, not suggested :( + if (! usingInterrupt) { + // read data from the GPS in the 'main loop' + char c = GPS.read(); + // if you want to debug, this is a good time to do it! + if (GPSECHO) + if (c) Serial.print(c); + } + + // if a sentence is received, we can check the checksum, parse it... + if (GPS.newNMEAreceived()) { + // a tricky thing here is if we print the NMEA sentence, or data + // we end up not listening and catching other sentences! + // so be very wary if using OUTPUT_ALLDATA and trytng to print out data + //Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false + + if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false + return; // we can fail to parse a sentence in which case we should just wait for another + } + + // if millis() or timer wraps around, we'll just reset it + if (timer > millis()) timer = millis(); + + // approximately every 2 seconds or so, print out the current stats + if (millis() - timer > 2000) { + timer = millis(); // reset the timer + + Serial.print("\nTime: "); + Serial.print(GPS.hour, DEC); Serial.print(':'); + Serial.print(GPS.minute, DEC); Serial.print(':'); + Serial.print(GPS.seconds, DEC); Serial.print('.'); + Serial.println(GPS.milliseconds); + Serial.print("Date: "); + Serial.print(GPS.day, DEC); Serial.print('/'); + Serial.print(GPS.month, DEC); Serial.print("/20"); + Serial.println(GPS.year, DEC); + Serial.print("Fix: "); Serial.print((int)GPS.fix); + Serial.print(" quality: "); Serial.println((int)GPS.fixquality); + if (GPS.fix) { + Serial.print("Location: "); + Serial.print(GPS.latitude, 4); Serial.print(GPS.lat); + Serial.print(", "); + Serial.print(GPS.longitude, 4); Serial.println(GPS.lon); + + Serial.print("Speed (knots): "); Serial.println(GPS.speed); + Serial.print("Angle: "); Serial.println(GPS.angle); + Serial.print("Altitude: "); Serial.println(GPS.altitude); + Serial.print("Satellites: "); Serial.println((int)GPS.satellites); + } + } +} diff --git a/examples/due_shield_sdlog/due_shield_sdlog.ino b/examples/due_shield_sdlog/due_shield_sdlog.ino new file mode 100644 index 0000000..9b32e27 --- /dev/null +++ b/examples/due_shield_sdlog/due_shield_sdlog.ino @@ -0,0 +1,174 @@ + +#include + +#ifdef __AVR__ + #include + #include +#endif + +#include +#include + + +// Ladyada's logger modified by Bill Greiman to use the SdFat library +// +// This code shows how to listen to the GPS module in an interrupt +// which allows the program to have more 'freedom' - just parse +// when a new NMEA sentence is available! Then access data when +// desired. +// +// Tested and works great with the Adafruit Ultimate GPS Shield +// using MTK33x9 chipset +// ------> http://www.adafruit.com/products/ +// Pick one up today at the Adafruit electronics shop +// and help support open source hardware & software! -ada + +#ifdef __AVR__ +SoftwareSerial mySerial(8, 7); +#else +#define mySerial Serial1 +#endif + +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 +/* set to true to only log to SD when GPS has a fix, for debugging, keep it false */ +#define LOG_FIXONLY false + +// Set the pins used +#define chipSelect 10 +#define ledPin 13 + +File logfile; + +// read a Hex value and return the decimal equivalent +uint8_t 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; +} + +// blink out an error code +void error(uint8_t errno) { +/* + if (SD.errorCode()) { + putstring("SD error: "); + Serial.print(card.errorCode(), HEX); + Serial.print(','); + Serial.println(card.errorData(), HEX); + } + */ + while(1) { + uint8_t i; + for (i=0; i