Port of Arduino TinyGPS library to mbed. Added extra methods to flag receipt/parsing of particular sentences.

Dependents:   Atlas gps_com QuadCopter Quadcopter_mk2 ... more

Port of TinyGPS (from Arduino) to mbed.

Errata: it's been pointed out to me that this version calls an undeclared millis() function. To get this code working in your project, you'll want to set up a Timer object and then call timer.read_ms() ala:

example to replace millis() calls

Timer timer;
...
timer.start();
timer.reset();
...
//x = millis();
x = timer.read_ms();
...
Committer:
shimniok
Date:
Thu Apr 28 15:24:13 2011 +0000
Revision:
1:f522b8bdf987
Parent:
0:8a347288f82c
Removed prototyping code that broke gps data validation

Who changed what in which revision?

UserRevisionLine numberNew contents of line
shimniok 0:8a347288f82c 1 /*
shimniok 0:8a347288f82c 2 TinyGPS - a small GPS library for Arduino providing basic NMEA parsing
shimniok 0:8a347288f82c 3 Copyright (C) 2008-9 Mikal Hart
shimniok 0:8a347288f82c 4 All rights reserved.
shimniok 0:8a347288f82c 5
shimniok 0:8a347288f82c 6 This library is free software; you can redistribute it and/or
shimniok 0:8a347288f82c 7 modify it under the terms of the GNU Lesser General Public
shimniok 0:8a347288f82c 8 License as published by the Free Software Foundation; either
shimniok 0:8a347288f82c 9 version 2.1 of the License, or (at your option) any later version.
shimniok 0:8a347288f82c 10
shimniok 0:8a347288f82c 11 This library is distributed in the hope that it will be useful,
shimniok 0:8a347288f82c 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
shimniok 0:8a347288f82c 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
shimniok 0:8a347288f82c 14 Lesser General Public License for more details.
shimniok 0:8a347288f82c 15
shimniok 0:8a347288f82c 16 You should have received a copy of the GNU Lesser General Public
shimniok 0:8a347288f82c 17 License along with this library; if not, write to the Free Software
shimniok 0:8a347288f82c 18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
shimniok 0:8a347288f82c 19
shimniok 0:8a347288f82c 20 Ported to mbed by Michael Shimniok
shimniok 0:8a347288f82c 21 */
shimniok 0:8a347288f82c 22
shimniok 0:8a347288f82c 23 #include "mbed.h"
shimniok 0:8a347288f82c 24 #include "types.h"
shimniok 0:8a347288f82c 25
shimniok 0:8a347288f82c 26 #ifndef TinyGPS_h
shimniok 0:8a347288f82c 27 #define TinyGPS_h
shimniok 0:8a347288f82c 28
shimniok 0:8a347288f82c 29 #define _GPS_VERSION 9 // software version of this library
shimniok 0:8a347288f82c 30 #define _GPS_MPH_PER_KNOT 1.15077945
shimniok 0:8a347288f82c 31 #define _GPS_MPS_PER_KNOT 0.51444444
shimniok 0:8a347288f82c 32 #define _GPS_KMPH_PER_KNOT 1.852
shimniok 0:8a347288f82c 33 #define _GPS_MILES_PER_METER 0.00062137112
shimniok 0:8a347288f82c 34 #define _GPS_KM_PER_METER 0.001
shimniok 0:8a347288f82c 35 //#define _GPS_NO_STATS
shimniok 0:8a347288f82c 36
shimniok 0:8a347288f82c 37 class TinyGPS
shimniok 0:8a347288f82c 38 {
shimniok 0:8a347288f82c 39 public:
shimniok 0:8a347288f82c 40
shimniok 0:8a347288f82c 41 /** Create a new GPS parsing object for parsing NMEA sentences
shimniok 0:8a347288f82c 42 */
shimniok 0:8a347288f82c 43 TinyGPS();
shimniok 0:8a347288f82c 44
shimniok 0:8a347288f82c 45 /** Parse a single character received from GPS
shimniok 0:8a347288f82c 46 *
shimniok 0:8a347288f82c 47 * @param c is the character received from the GPS
shimniok 0:8a347288f82c 48 * @returns true if processing ok
shimniok 0:8a347288f82c 49 */
shimniok 0:8a347288f82c 50 bool encode(char c);
shimniok 0:8a347288f82c 51
shimniok 0:8a347288f82c 52 /** Shorthand operator for encode()
shimniok 0:8a347288f82c 53 */
shimniok 0:8a347288f82c 54 TinyGPS &operator << (char c) {encode(c); return *this;}
shimniok 0:8a347288f82c 55
shimniok 0:8a347288f82c 56 /** Return lat/long in hundred thousandths of a degree and age of fix in milliseconds
shimniok 0:8a347288f82c 57 * @returns latitude is the latitude of the most recent fix that was parsed
shimniok 0:8a347288f82c 58 * @returns longitude is the longitude of the most recent fix that was parsed
shimniok 0:8a347288f82c 59 * @returns fix_age is the age of the fix (if available from the NMEA sentences being parsed)
shimniok 0:8a347288f82c 60 */
shimniok 0:8a347288f82c 61 inline void get_position(long *latitude, long *longitude, unsigned long *fix_age = 0)
shimniok 0:8a347288f82c 62 {
shimniok 0:8a347288f82c 63 if (latitude) *latitude = _latitude;
shimniok 0:8a347288f82c 64 if (longitude) *longitude = _longitude;
shimniok 0:8a347288f82c 65 if (fix_age) *fix_age = _last_position_fix == GPS_INVALID_FIX_TIME ?
shimniok 0:8a347288f82c 66 GPS_INVALID_AGE : millis() - _last_position_fix;
shimniok 0:8a347288f82c 67 }
shimniok 0:8a347288f82c 68
shimniok 0:8a347288f82c 69 /** Return the date and time from the parsed NMEA sentences
shimniok 0:8a347288f82c 70 *
shimniok 0:8a347288f82c 71 * @returns date as an integer value
shimniok 0:8a347288f82c 72 * @returns time as an integer value
shimniok 0:8a347288f82c 73 * @returns fix_age in milliseconds if available
shimniok 0:8a347288f82c 74 */
shimniok 0:8a347288f82c 75 inline void get_datetime(unsigned long *date, unsigned long *time, unsigned long *fix_age = 0)
shimniok 0:8a347288f82c 76 {
shimniok 0:8a347288f82c 77 if (date) *date = _date;
shimniok 0:8a347288f82c 78 if (time) *time = _time;
shimniok 0:8a347288f82c 79 if (fix_age) *fix_age = _last_time_fix == GPS_INVALID_FIX_TIME ?
shimniok 0:8a347288f82c 80 GPS_INVALID_AGE : millis() - _last_time_fix;
shimniok 0:8a347288f82c 81 }
shimniok 0:8a347288f82c 82
shimniok 0:8a347288f82c 83 /** signed altitude in centimeters (from GPGGA sentence)
shimniok 0:8a347288f82c 84 * @returns altitude in centimeters, integer
shimniok 0:8a347288f82c 85 */
shimniok 0:8a347288f82c 86 inline long altitude() { return _altitude; }
shimniok 0:8a347288f82c 87
shimniok 0:8a347288f82c 88 /** course in last full GPRMC sentence in 100th of a degree
shimniok 0:8a347288f82c 89 * @returns course as an integer, 100ths of a degree
shimniok 0:8a347288f82c 90 */
shimniok 0:8a347288f82c 91 inline unsigned long course() { return _course; }
shimniok 0:8a347288f82c 92
shimniok 0:8a347288f82c 93 /** speed in last full GPRMC sentence in 100ths of a knot
shimniok 0:8a347288f82c 94 * @returns speed in 100ths of a knot
shimniok 0:8a347288f82c 95 */
shimniok 0:8a347288f82c 96 unsigned long speed() { return _speed; }
shimniok 0:8a347288f82c 97
shimniok 0:8a347288f82c 98 /* horizontal dilution of position in last full GPGGA sentence in 100ths
shimniok 0:8a347288f82c 99 * @returns hdop in 100ths
shimniok 0:8a347288f82c 100 */
shimniok 0:8a347288f82c 101 unsigned long hdop() { return _hdop; }
shimniok 0:8a347288f82c 102
shimniok 0:8a347288f82c 103 /** number of satellites tracked in last full GPGGA sentence
shimniok 0:8a347288f82c 104 * @returns number of satellites tracked
shimniok 0:8a347288f82c 105 */
shimniok 0:8a347288f82c 106 unsigned long sat_count() { return _sat_count; }
shimniok 0:8a347288f82c 107
shimniok 0:8a347288f82c 108 #ifndef _GPS_NO_STATS
shimniok 0:8a347288f82c 109 void stats(unsigned long *chars, unsigned short *good_sentences, unsigned short *failed_cs);
shimniok 0:8a347288f82c 110 #endif
shimniok 0:8a347288f82c 111
shimniok 0:8a347288f82c 112 /** returns position as double precision
shimniok 0:8a347288f82c 113 *
shimniok 0:8a347288f82c 114 * @returns latitude as double precision
shimniok 0:8a347288f82c 115 * @returns longitude as double precision
shimniok 0:8a347288f82c 116 * @returns fix age in milliseconds if available
shimniok 0:8a347288f82c 117 */
shimniok 0:8a347288f82c 118 inline void f_get_position(double *latitude, double *longitude, unsigned long *fix_age = 0)
shimniok 0:8a347288f82c 119 {
shimniok 0:8a347288f82c 120 long lat, lon;
shimniok 0:8a347288f82c 121 get_position(&lat, &lon, fix_age);
shimniok 0:8a347288f82c 122 *latitude = lat / 100000.0;
shimniok 0:8a347288f82c 123 *longitude = lon / 100000.0;
shimniok 0:8a347288f82c 124 }
shimniok 0:8a347288f82c 125
shimniok 0:8a347288f82c 126 /** Convert date and time of last parsed sentence to integers
shimniok 0:8a347288f82c 127 *
shimniok 0:8a347288f82c 128 * @returns year
shimniok 0:8a347288f82c 129 * @returns month
shimniok 0:8a347288f82c 130 * @returns day of month
shimniok 0:8a347288f82c 131 * @returns hour
shimniok 0:8a347288f82c 132 * @returns minute
shimniok 0:8a347288f82c 133 * @returns second
shimniok 0:8a347288f82c 134 * @returns hundreths
shimniok 0:8a347288f82c 135 * @returns fix_age in milliseconds if available
shimniok 0:8a347288f82c 136 */
shimniok 0:8a347288f82c 137 inline void crack_datetime(int *year, byte *month, byte *day,
shimniok 0:8a347288f82c 138 byte *hour, byte *minute, byte *second, byte *hundredths = 0, unsigned long *fix_age = 0)
shimniok 0:8a347288f82c 139 {
shimniok 0:8a347288f82c 140 unsigned long date, time;
shimniok 0:8a347288f82c 141 get_datetime(&date, &time, fix_age);
shimniok 0:8a347288f82c 142 if (year)
shimniok 0:8a347288f82c 143 {
shimniok 0:8a347288f82c 144 *year = date % 100;
shimniok 0:8a347288f82c 145 *year += *year > 80 ? 1900 : 2000;
shimniok 0:8a347288f82c 146 }
shimniok 0:8a347288f82c 147 if (month) *month = (date / 100) % 100;
shimniok 0:8a347288f82c 148 if (day) *day = date / 10000;
shimniok 0:8a347288f82c 149 if (hour) *hour = time / 1000000;
shimniok 0:8a347288f82c 150 if (minute) *minute = (time / 10000) % 100;
shimniok 0:8a347288f82c 151 if (second) *second = (time / 100) % 100;
shimniok 0:8a347288f82c 152 if (hundredths) *hundredths = time % 100;
shimniok 0:8a347288f82c 153 }
shimniok 0:8a347288f82c 154
shimniok 0:8a347288f82c 155 /** returns altitude as a float
shimniok 0:8a347288f82c 156 */
shimniok 0:8a347288f82c 157 inline double f_altitude() { return altitude() / 100.0; }
shimniok 0:8a347288f82c 158
shimniok 0:8a347288f82c 159 /** returns course as a float
shimniok 0:8a347288f82c 160 */
shimniok 0:8a347288f82c 161 inline double f_course() { return course() / 100.0; }
shimniok 0:8a347288f82c 162
shimniok 0:8a347288f82c 163 /** returns speed in knots as a float
shimniok 0:8a347288f82c 164 */
shimniok 0:8a347288f82c 165 inline double f_speed_knots() { return speed() / 100.0; }
shimniok 0:8a347288f82c 166
shimniok 0:8a347288f82c 167 /** returns speed in mph as a float
shimniok 0:8a347288f82c 168 */
shimniok 0:8a347288f82c 169 inline double f_speed_mph() { return _GPS_MPH_PER_KNOT * f_speed_knots(); }
shimniok 0:8a347288f82c 170
shimniok 0:8a347288f82c 171 /** returns speed in meters per second as a float
shimniok 0:8a347288f82c 172 */
shimniok 0:8a347288f82c 173 inline double f_speed_mps() { return _GPS_MPS_PER_KNOT * f_speed_knots(); }
shimniok 0:8a347288f82c 174
shimniok 0:8a347288f82c 175 /** returns speed in km per hour as a float
shimniok 0:8a347288f82c 176 */
shimniok 0:8a347288f82c 177 inline double f_speed_kmph() { return _GPS_KMPH_PER_KNOT * f_speed_knots(); }
shimniok 0:8a347288f82c 178
shimniok 0:8a347288f82c 179 /** returns hdop as a float
shimniok 0:8a347288f82c 180 */
shimniok 0:8a347288f82c 181 inline double f_hdop() { return hdop() / 100.0; }
shimniok 0:8a347288f82c 182
shimniok 0:8a347288f82c 183 /** @returns library version
shimniok 0:8a347288f82c 184 */
shimniok 0:8a347288f82c 185 static int library_version() { return _GPS_VERSION; }
shimniok 0:8a347288f82c 186
shimniok 0:8a347288f82c 187 /** determine if RMC sentence parsed since last reset_ready()
shimniok 0:8a347288f82c 188 */
shimniok 0:8a347288f82c 189 inline bool rmc_ready() { return _rmc_ready; }
shimniok 0:8a347288f82c 190
shimniok 0:8a347288f82c 191 /** determine if GGA sentence parsed since last reset_ready()
shimniok 0:8a347288f82c 192 */
shimniok 0:8a347288f82c 193 inline bool gga_ready() { return _gga_ready; }
shimniok 0:8a347288f82c 194
shimniok 0:8a347288f82c 195 /** determine if GSV sentence parsed since last reset_ready()
shimniok 0:8a347288f82c 196 */
shimniok 0:8a347288f82c 197 inline bool gsv_ready() { return _gsv_ready; }
shimniok 0:8a347288f82c 198
shimniok 0:8a347288f82c 199 /** Reset the ready flags for all the parsed sentences
shimniok 0:8a347288f82c 200 */
shimniok 0:8a347288f82c 201 inline void reset_ready() { _gsv_ready = _rmc_ready = _gga_ready = false; }
shimniok 0:8a347288f82c 202
shimniok 0:8a347288f82c 203 enum {GPS_INVALID_AGE = 0xFFFFFFFF, GPS_INVALID_ANGLE = 999999999, GPS_INVALID_ALTITUDE = 999999999, GPS_INVALID_DATE = 0,
shimniok 0:8a347288f82c 204 GPS_INVALID_TIME = 0xFFFFFFFF, GPS_INVALID_SPEED = 999999999, GPS_INVALID_FIX_TIME = 0xFFFFFFFF};
shimniok 0:8a347288f82c 205
shimniok 0:8a347288f82c 206 private:
shimniok 0:8a347288f82c 207 enum {_GPS_SENTENCE_GPGGA, _GPS_SENTENCE_GPRMC, _GPS_SENTENCE_GPGSV, _GPS_SENTENCE_OTHER};
shimniok 0:8a347288f82c 208
shimniok 0:8a347288f82c 209 // properties
shimniok 0:8a347288f82c 210 unsigned long _time, _new_time;
shimniok 0:8a347288f82c 211 unsigned long _date, _new_date;
shimniok 0:8a347288f82c 212 long _latitude, _new_latitude;
shimniok 0:8a347288f82c 213 long _longitude, _new_longitude;
shimniok 0:8a347288f82c 214 long _altitude, _new_altitude;
shimniok 0:8a347288f82c 215 unsigned long _speed, _new_speed;
shimniok 0:8a347288f82c 216 unsigned long _course, _new_course;
shimniok 0:8a347288f82c 217 unsigned long _hdop, _new_hdop;
shimniok 0:8a347288f82c 218 unsigned int _sat_count, _new_sat_count;
shimniok 0:8a347288f82c 219 unsigned long _last_time_fix, _new_time_fix;
shimniok 0:8a347288f82c 220 unsigned long _last_position_fix, _new_position_fix;
shimniok 0:8a347288f82c 221
shimniok 0:8a347288f82c 222 // parsing state variables
shimniok 0:8a347288f82c 223 byte _parity;
shimniok 0:8a347288f82c 224 bool _is_checksum_term;
shimniok 0:8a347288f82c 225 char _term[15];
shimniok 0:8a347288f82c 226 byte _sentence_type;
shimniok 0:8a347288f82c 227 byte _term_number;
shimniok 0:8a347288f82c 228 byte _term_offset;
shimniok 0:8a347288f82c 229 bool _gps_data_good;
shimniok 0:8a347288f82c 230 bool _rmc_ready;
shimniok 0:8a347288f82c 231 bool _gga_ready;
shimniok 0:8a347288f82c 232 bool _gsv_ready;
shimniok 0:8a347288f82c 233
shimniok 0:8a347288f82c 234 #ifndef _GPS_NO_STATS
shimniok 0:8a347288f82c 235 // statistics
shimniok 0:8a347288f82c 236 unsigned long _encoded_characters;
shimniok 0:8a347288f82c 237 unsigned short _good_sentences;
shimniok 0:8a347288f82c 238 unsigned short _failed_checksum;
shimniok 0:8a347288f82c 239 unsigned short _passed_checksum;
shimniok 0:8a347288f82c 240 #endif
shimniok 0:8a347288f82c 241
shimniok 0:8a347288f82c 242 // internal utilities
shimniok 0:8a347288f82c 243 int from_hex(char a);
shimniok 0:8a347288f82c 244 unsigned long parse_decimal();
shimniok 0:8a347288f82c 245 unsigned long parse_degrees();
shimniok 0:8a347288f82c 246 bool term_complete();
shimniok 0:8a347288f82c 247 bool gpsisdigit(char c) { return c >= '0' && c <= '9'; }
shimniok 0:8a347288f82c 248 long gpsatol(const char *str);
shimniok 0:8a347288f82c 249 int gpsstrcmp(const char *str1, const char *str2);
shimniok 0:8a347288f82c 250 };
shimniok 0:8a347288f82c 251
shimniok 0:8a347288f82c 252 // Arduino 0012 workaround
shimniok 0:8a347288f82c 253 #undef int
shimniok 0:8a347288f82c 254 #undef char
shimniok 0:8a347288f82c 255 #undef long
shimniok 0:8a347288f82c 256 #undef byte
shimniok 0:8a347288f82c 257 #undef double
shimniok 0:8a347288f82c 258 #undef abs
shimniok 0:8a347288f82c 259 #undef round
shimniok 0:8a347288f82c 260
shimniok 0:8a347288f82c 261 #endif