Allows for a GPS module to be connected to a serial port and exposes an easy to use API to get the GPS data.

Fork of MODGPS by Andy K

Committer:
xanter
Date:
Sat Sep 29 20:31:31 2018 +0000
Revision:
7:049436bc2225
Parent:
5:7f130f85d5a4
Fixed compiler errors/warnings; Removed hardcode for LPC17xx

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AjK 0:db98027c0bbb 1 /*
AjK 0:db98027c0bbb 2 Copyright (c) 2010 Andy Kirkham
AjK 0:db98027c0bbb 3
AjK 0:db98027c0bbb 4 Permission is hereby granted, free of charge, to any person obtaining a copy
AjK 0:db98027c0bbb 5 of this software and associated documentation files (the "Software"), to deal
AjK 0:db98027c0bbb 6 in the Software without restriction, including without limitation the rights
AjK 0:db98027c0bbb 7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
AjK 0:db98027c0bbb 8 copies of the Software, and to permit persons to whom the Software is
AjK 0:db98027c0bbb 9 furnished to do so, subject to the following conditions:
AjK 0:db98027c0bbb 10
AjK 0:db98027c0bbb 11 The above copyright notice and this permission notice shall be included in
AjK 0:db98027c0bbb 12 all copies or substantial portions of the Software.
AjK 0:db98027c0bbb 13
AjK 0:db98027c0bbb 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
AjK 0:db98027c0bbb 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
AjK 0:db98027c0bbb 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AjK 0:db98027c0bbb 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
AjK 0:db98027c0bbb 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
AjK 0:db98027c0bbb 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
AjK 0:db98027c0bbb 20 THE SOFTWARE.
AjK 0:db98027c0bbb 21 */
AjK 0:db98027c0bbb 22
AjK 0:db98027c0bbb 23 #include "GPS_Time.h"
AjK 0:db98027c0bbb 24
xanter 7:049436bc2225 25 GPS_Time::GPS_Time() {
AjK 0:db98027c0bbb 26 year = 2000;
AjK 0:db98027c0bbb 27 month = 1;
AjK 0:db98027c0bbb 28 day = 1;
AjK 0:db98027c0bbb 29 hour = 0;
AjK 0:db98027c0bbb 30 minute = 0;
AjK 0:db98027c0bbb 31 second = 0;
AjK 0:db98027c0bbb 32 tenths = 0;
AjK 0:db98027c0bbb 33 hundreths = 0;
AjK 0:db98027c0bbb 34 status = 'V';
AjK 2:8aa059e7d8b1 35 velocity = 0;
AjK 2:8aa059e7d8b1 36 track = 0;
AjK 2:8aa059e7d8b1 37 magvar_dir = 'W';
AjK 2:8aa059e7d8b1 38 magvar = 0;
AjK 0:db98027c0bbb 39 }
AjK 0:db98027c0bbb 40
xanter 7:049436bc2225 41 time_t GPS_Time::to_C_tm(bool set) {
AjK 5:7f130f85d5a4 42 GPS_Time t;
AjK 5:7f130f85d5a4 43 tm ct;
AjK 5:7f130f85d5a4 44 time_t q;
AjK 5:7f130f85d5a4 45
AjK 5:7f130f85d5a4 46 timeNow(&t);
AjK 5:7f130f85d5a4 47 ct.tm_sec = t.second;
AjK 5:7f130f85d5a4 48 ct.tm_min = t.minute;
AjK 5:7f130f85d5a4 49 ct.tm_hour = t.hour;
AjK 5:7f130f85d5a4 50 ct.tm_mday = t.day;
AjK 5:7f130f85d5a4 51 ct.tm_mon = t.month - 1;
AjK 5:7f130f85d5a4 52 ct.tm_year = t.year - 1900;
AjK 5:7f130f85d5a4 53 ct.tm_isdst = 0; // GPS has no understanding of DST.
AjK 5:7f130f85d5a4 54
AjK 5:7f130f85d5a4 55 q = mktime(&ct);
AjK 5:7f130f85d5a4 56 if (set) {
AjK 5:7f130f85d5a4 57 set_time(q);
AjK 5:7f130f85d5a4 58 }
AjK 5:7f130f85d5a4 59 return q;
AjK 5:7f130f85d5a4 60 }
AjK 5:7f130f85d5a4 61
xanter 7:049436bc2225 62 GPS_Time * GPS_Time::timeNow(GPS_Time *n) {
xanter 7:049436bc2225 63 if (n == NULL)
xanter 7:049436bc2225 64 n = new GPS_Time;
AjK 0:db98027c0bbb 65
AjK 0:db98027c0bbb 66 do {
AjK 0:db98027c0bbb 67 memcpy(n, this, sizeof(GPS_Time));
AjK 0:db98027c0bbb 68 }
AjK 0:db98027c0bbb 69 while (memcmp(n, this, sizeof(GPS_Time)));
AjK 0:db98027c0bbb 70 return n;
AjK 0:db98027c0bbb 71 }
AjK 0:db98027c0bbb 72
xanter 7:049436bc2225 73 void GPS_Time::operator++() {
AjK 0:db98027c0bbb 74 hundreths++;
AjK 0:db98027c0bbb 75 if (hundreths == 10) {
AjK 0:db98027c0bbb 76 hundreths = 0;
AjK 0:db98027c0bbb 77 tenths++;
AjK 0:db98027c0bbb 78 if (tenths == 10) {
AjK 0:db98027c0bbb 79 tenths = hundreths = 0;
AjK 0:db98027c0bbb 80 }
AjK 0:db98027c0bbb 81 }
AjK 0:db98027c0bbb 82 }
AjK 0:db98027c0bbb 83
xanter 7:049436bc2225 84 void GPS_Time::operator++(int) {
AjK 0:db98027c0bbb 85 const int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
AjK 0:db98027c0bbb 86 bool dateInc = false;
AjK 0:db98027c0bbb 87
AjK 0:db98027c0bbb 88 tenths = hundreths = 0;
AjK 0:db98027c0bbb 89 second++;
AjK 0:db98027c0bbb 90
AjK 0:db98027c0bbb 91 if (second == 60) {
AjK 0:db98027c0bbb 92 second = 0;
AjK 0:db98027c0bbb 93 minute++;
AjK 0:db98027c0bbb 94 if (minute == 60) {
AjK 0:db98027c0bbb 95 minute = 0;
AjK 0:db98027c0bbb 96 hour++;
AjK 0:db98027c0bbb 97 if (hour == 24) {
AjK 0:db98027c0bbb 98 hour = 0;
AjK 0:db98027c0bbb 99 dateInc = true;
AjK 0:db98027c0bbb 100 }
AjK 0:db98027c0bbb 101 }
AjK 0:db98027c0bbb 102 }
AjK 0:db98027c0bbb 103
AjK 0:db98027c0bbb 104 if (dateInc) {
AjK 0:db98027c0bbb 105 /* Handle February leap year. */
AjK 0:db98027c0bbb 106 int leap_year = ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ? 1 : 0;
AjK 0:db98027c0bbb 107 int days_this_month = days[month - 1];
AjK 0:db98027c0bbb 108 if (month == 2 && leap_year) days_this_month++;
AjK 0:db98027c0bbb 109 day++;
AjK 0:db98027c0bbb 110 if (day > days_this_month) {
AjK 0:db98027c0bbb 111 day = 1;
AjK 0:db98027c0bbb 112 month++;
AjK 0:db98027c0bbb 113 if (month == 13) {
AjK 0:db98027c0bbb 114 year++;
AjK 0:db98027c0bbb 115 }
AjK 0:db98027c0bbb 116 }
AjK 0:db98027c0bbb 117 }
AjK 0:db98027c0bbb 118 }
AjK 0:db98027c0bbb 119
AjK 2:8aa059e7d8b1 120 // $GPRMC,112709.735,A,5611.5340,N,00302.0306,W,000.0,307.0,150411,,,A*70
xanter 7:049436bc2225 121 void GPS_Time::nmea_rmc(char *s) {
AjK 0:db98027c0bbb 122 char *token;
AjK 0:db98027c0bbb 123 int token_counter = 0;
AjK 0:db98027c0bbb 124 char *time = (char *)NULL;
AjK 0:db98027c0bbb 125 char *date = (char *)NULL;
AjK 0:db98027c0bbb 126 char *stat = (char *)NULL;
AjK 2:8aa059e7d8b1 127 char *vel = (char *)NULL;
AjK 2:8aa059e7d8b1 128 char *trk = (char *)NULL;
AjK 2:8aa059e7d8b1 129 char *magv = (char *)NULL;
AjK 2:8aa059e7d8b1 130 char *magd = (char *)NULL;
AjK 2:8aa059e7d8b1 131
AjK 0:db98027c0bbb 132 token = strtok(s, ",");
AjK 0:db98027c0bbb 133 while (token) {
AjK 0:db98027c0bbb 134 switch (token_counter) {
AjK 2:8aa059e7d8b1 135 case 9: date = token; break;
AjK 2:8aa059e7d8b1 136 case 1: time = token; break;
AjK 2:8aa059e7d8b1 137 case 2: stat = token; break;
AjK 2:8aa059e7d8b1 138 case 7: vel = token; break;
AjK 2:8aa059e7d8b1 139 case 8: trk = token; break;
AjK 2:8aa059e7d8b1 140 case 10: magv = token; break;
AjK 2:8aa059e7d8b1 141 case 11: magd = token; break;
AjK 0:db98027c0bbb 142 }
AjK 0:db98027c0bbb 143 token = strtok((char *)NULL, ",");
AjK 0:db98027c0bbb 144 token_counter++;
AjK 0:db98027c0bbb 145 }
AjK 0:db98027c0bbb 146
AjK 0:db98027c0bbb 147 if (stat && date && time) {
AjK 0:db98027c0bbb 148 hour = (char)((time[0] - '0') * 10) + (time[1] - '0');
AjK 0:db98027c0bbb 149 minute = (char)((time[2] - '0') * 10) + (time[3] - '0');
AjK 0:db98027c0bbb 150 second = (char)((time[4] - '0') * 10) + (time[5] - '0');
AjK 0:db98027c0bbb 151 day = (char)((date[0] - '0') * 10) + (date[1] - '0');
AjK 0:db98027c0bbb 152 month = (char)((date[2] - '0') * 10) + (date[3] - '0');
AjK 0:db98027c0bbb 153 year = (int)((date[4] - '0') * 10) + (date[5] - '0') + 2000;
AjK 0:db98027c0bbb 154 status = stat[0];
AjK 2:8aa059e7d8b1 155 velocity = atof(vel);
AjK 2:8aa059e7d8b1 156 track = atof(trk);
AjK 2:8aa059e7d8b1 157 magvar = atof(magv);
AjK 2:8aa059e7d8b1 158 magvar_dir = magd[0];
AjK 0:db98027c0bbb 159 }
AjK 0:db98027c0bbb 160 }
AjK 0:db98027c0bbb 161
xanter 7:049436bc2225 162 double GPS_Time::julian_day_number(GPS_Time *t) {
AjK 0:db98027c0bbb 163 double wikipedia_jdn = (double)(1461 * ((int)t->year + 4800 + ((int)t->month - 14) / 12)) / 4 + (367 * ((int)t->month - 2 - 12 * (((int)t->month - 14) / 12))) / 12 - (3 * (((int)t->year + 4900 + ((int)t->month - 14) / 12 ) / 100)) / 4 + (int)t->day - 32075;
AjK 0:db98027c0bbb 164 return wikipedia_jdn;
AjK 0:db98027c0bbb 165 }
AjK 0:db98027c0bbb 166
xanter 7:049436bc2225 167 double GPS_Time::julian_date(GPS_Time *t) {
AjK 0:db98027c0bbb 168 double hour, minute, second, jd;
AjK 0:db98027c0bbb 169 hour = (double)t->hour;
AjK 0:db98027c0bbb 170 minute = (double)t->minute;
AjK 0:db98027c0bbb 171 second = (double)t->second + ((double)t->tenths / 10.) + ((double)t->hundreths / 100.);
AjK 0:db98027c0bbb 172
AjK 0:db98027c0bbb 173 jd = julian_day_number(t) - 0.5 +
AjK 0:db98027c0bbb 174 ((hour - 12.) / 24.) +
AjK 0:db98027c0bbb 175 (minute / 1440.) +
AjK 0:db98027c0bbb 176 (second / 86400.);
AjK 0:db98027c0bbb 177
AjK 0:db98027c0bbb 178 return jd;
AjK 0:db98027c0bbb 179 }
AjK 0:db98027c0bbb 180
xanter 7:049436bc2225 181 double GPS_Time::siderealDegrees(double jd, double longitude) {
AjK 0:db98027c0bbb 182 double sidereal, gmst, lmst;
AjK 0:db98027c0bbb 183 double T = jd - 2451545.0;
AjK 0:db98027c0bbb 184 double T1 = T / 36525.0;
AjK 0:db98027c0bbb 185 double T2 = T1 * T1;
AjK 0:db98027c0bbb 186 double T3 = T2 * T1;
AjK 0:db98027c0bbb 187
AjK 0:db98027c0bbb 188 /* Calculate gmst angle. */
AjK 0:db98027c0bbb 189 sidereal = 280.46061837 + (360.98564736629 * T) + (0.000387933 * T2) - (T3 / 38710000.0);
AjK 0:db98027c0bbb 190
AjK 0:db98027c0bbb 191 /* Convert to degrees. */
AjK 0:db98027c0bbb 192 sidereal = fmod(sidereal, 360.0);
AjK 0:db98027c0bbb 193 if (sidereal < 0.0) sidereal += 360.0;
AjK 0:db98027c0bbb 194
AjK 0:db98027c0bbb 195 gmst = sidereal;
AjK 0:db98027c0bbb 196 lmst = gmst + longitude;
AjK 0:db98027c0bbb 197 return lmst;
AjK 0:db98027c0bbb 198 }
AjK 0:db98027c0bbb 199
xanter 7:049436bc2225 200 double GPS_Time::siderealDegrees(GPS_Time *t, double longitude) {
AjK 0:db98027c0bbb 201 if (t == NULL) t = new GPS_Time;
AjK 0:db98027c0bbb 202 return siderealDegrees(julian_date(t), longitude);
AjK 0:db98027c0bbb 203 }
AjK 0:db98027c0bbb 204
xanter 7:049436bc2225 205 double GPS_Time::siderealHA(double jd, double longitude) {
AjK 0:db98027c0bbb 206 double lmst = siderealDegrees(jd, longitude);
AjK 0:db98027c0bbb 207 return lmst / 360.0 * 24.0;
AjK 0:db98027c0bbb 208 }
AjK 0:db98027c0bbb 209
xanter 7:049436bc2225 210 double GPS_Time::siderealHA(GPS_Time *t, double longitude) {
AjK 0:db98027c0bbb 211 double lmst = siderealDegrees(t, longitude);
AjK 0:db98027c0bbb 212 return lmst / 360.0 * 24.0;
AjK 0:db98027c0bbb 213 }
AjK 0:db98027c0bbb 214