-
Notifications
You must be signed in to change notification settings - Fork 2
/
TinyGPS.h
219 lines (182 loc) · 6.61 KB
/
TinyGPS.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/*
TinyGPS - a small GPS library for Arduino providing basic NMEA parsing
Based on work by and "distance_to" courtesy of Maarten Lamers.
Copyright (C) 2008-2011 Mikal Hart
All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef TinyGPS_h
#define TinyGPS_h
#include "WProgram.h"
#define _GPS_VERSION 10 // software version of this library
#define _GPS_MPH_PER_KNOT 1.15077945
#define _GPS_MPS_PER_KNOT 0.51444444
#define _GPS_KMPH_PER_KNOT 1.852
#define _GPS_MILES_PER_METER 0.00062137112
#define _GPS_KM_PER_METER 0.001
#define _GPS_NO_STATS
class TinyGPS
{
public:
TinyGPS();
bool encode(char c); // process one character received from GPS
bool binaryEncode(byte c); // process one binary character received from GPS
TinyGPS &operator << (char c) {encode(c); return *this;}
// lat/long in hundred thousandths of a degree and age of fix in milliseconds
inline void get_position(long *latitude, long *longitude, unsigned long *fix_age = 0)
{
if (latitude) *latitude = _latitude;
if (longitude) *longitude = _longitude;
if (fix_age) *fix_age = _last_position_fix == GPS_INVALID_FIX_TIME ?
GPS_INVALID_AGE : millis() - _last_position_fix;
}
// date as ddmmyy, time as hhmmsscc, and age in milliseconds
inline void get_datetime(unsigned long *date, unsigned long *time, unsigned long *fix_age = 0)
{
if (date) *date = _date;
if (time) *time = _time;
if (fix_age) *fix_age = _last_time_fix == GPS_INVALID_FIX_TIME ?
GPS_INVALID_AGE : millis() - _last_time_fix;
}
// signed altitude in centimeters (from GPGGA sentence)
inline long altitude() { return _altitude; }
// fix type
inline uint8_t fix() { return _fix; }
inline uint8_t getSats(void) { return _num_sats; }
// course in last full GPRMC sentence in 100th of a degree
inline unsigned long course() { return _course; }
// speed in last full GPRMC sentence in 100ths of a knot
unsigned long speed() { return _speed; }
#ifndef _GPS_NO_STATS
void stats(unsigned long *chars, unsigned short *good_sentences, unsigned short *failed_cs);
#endif
inline void f_get_position(float *latitude, float *longitude, unsigned long *fix_age = 0)
{
long lat, lon;
get_position(&lat, &lon, fix_age);
*latitude = lat / 1000000.0;
*longitude = lon / 1000000.0;
}
inline void crack_datetime(int *year, byte *month, byte *day,
byte *hour, byte *minute, byte *second, byte *hundredths = 0, unsigned long *fix_age = 0)
{
unsigned long date, time;
get_datetime(&date, &time, fix_age);
if (year)
{
*year = date % 100;
*year += *year > 80 ? 1900 : 2000;
}
if (month) *month = (date / 100) % 100;
if (day) *day = date / 10000;
if (hour) *hour = time / 1000000;
if (minute) *minute = (time / 10000) % 100;
if (second) *second = (time / 100) % 100;
if (hundredths) *hundredths = time % 100;
}
inline float f_altitude() { return altitude() / 100.0; }
inline float f_course() { return course() / 100.0; }
inline float f_speed_knots() { return speed() / 100.0; }
inline float f_speed_mph() { return _GPS_MPH_PER_KNOT * f_speed_knots(); }
inline float f_speed_mps() { return _GPS_MPS_PER_KNOT * f_speed_knots(); }
inline float f_speed_kmph() { return _GPS_KMPH_PER_KNOT * f_speed_knots(); }
static int library_version() { return _GPS_VERSION; }
enum {GPS_INVALID_AGE = 0xFFFFFFFF, GPS_INVALID_ANGLE = 999999999, GPS_INVALID_ALTITUDE = 999999999, GPS_INVALID_DATE = 0,
GPS_INVALID_TIME = 0xFFFFFFFF, GPS_INVALID_SPEED = 999999999, GPS_INVALID_FIX_TIME = 0xFFFFFFFF};
static float distance_between (float lat1, float long1, float lat2, float long2);
private:
enum {_GPS_SENTENCE_GPGGA, _GPS_SENTENCE_GPRMC, _GPS_SENTENCE_OTHER};
// properties
unsigned long _time, _new_time;
unsigned long _date, _new_date;
long _latitude, _new_latitude;
long _longitude, _new_longitude;
long _altitude, _new_altitude;
unsigned long _speed, _new_speed;
unsigned long _course, _new_course;
unsigned long _last_time_fix, _new_time_fix;
unsigned long _last_position_fix, _new_position_fix;
// parsing state variables
byte _parity;
bool _is_checksum_term;
char _term[15];
byte _sentence_type;
byte _term_number;
byte _term_offset;
bool _gps_data_good;
#ifndef _GPS_NO_STATS
// statistics
unsigned long _encoded_characters;
unsigned short _good_sentences;
unsigned short _failed_checksum;
unsigned short _passed_checksum;
#endif
// internal utilities
int from_hex(char a);
unsigned long parse_decimal();
unsigned long parse_degrees();
bool term_complete();
bool gpsisdigit(char c) { return c >= '0' && c <= '9'; }
long gpsatol(const char *str);
int gpsstrcmp(const char *str1, const char *str2);
// Binary protocol support below this line
uint8_t _fix;
uint8_t _hdop;
uint8_t _num_sats;
#pragma pack(1)
struct diyd_mtk_msg {
int32_t latitude;
int32_t longitude;
int32_t altitude;
int32_t ground_speed;
int32_t ground_course;
uint8_t satellites;
uint8_t fix_type;
uint32_t utc_date;
uint32_t utc_time;
uint16_t hdop;
};
#pragma pack(pop)
enum diyd_mtk_fix_type {
FIX_NONE = 1,
FIX_2D = 2,
FIX_3D = 3
};
enum diyd_mtk_protocol_bytes {
PREAMBLE1 = 0xd0,
PREAMBLE2 = 0xdd,
};
// Packet checksum accumulators
uint8_t _ck_a;
uint8_t _ck_b;
// State machine state
uint8_t _step;
uint8_t _payload_counter;
// Time from UNIX Epoch offset
long _time_offset;
bool _offset_calculated;
// Receive buffer
union {
diyd_mtk_msg msg;
uint8_t bytes[];
} _buffer;
};
// Arduino 0012 workaround
#undef int
#undef char
#undef long
#undef byte
#undef float
#undef abs
#undef round
#endif