Allows for a GPS module to be connected to a serial port and exposes an easy to use API to get the GPS data. New feature, added Mbed/LPC17xx RTC synchronisation

Dependents:   SatGPS AntiTheftGPS FLIGHT_CONTROL_AND_COMMUNICATIONS_SYSTEM GPS-Lora ... more

Committer:
AjK
Date:
Fri Apr 15 12:23:52 2011 +0000
Revision:
2:8aa059e7d8b1
Parent:
0:db98027c0bbb
Child:
5:7f130f85d5a4
1.12 See ChangeLog.c

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
AjK 0:db98027c0bbb 25 GPS_Time::GPS_Time()
AjK 0:db98027c0bbb 26 {
AjK 0:db98027c0bbb 27 year = 2000;
AjK 0:db98027c0bbb 28 month = 1;
AjK 0:db98027c0bbb 29 day = 1;
AjK 0:db98027c0bbb 30 hour = 0;
AjK 0:db98027c0bbb 31 minute = 0;
AjK 0:db98027c0bbb 32 second = 0;
AjK 0:db98027c0bbb 33 tenths = 0;
AjK 0:db98027c0bbb 34 hundreths = 0;
AjK 0:db98027c0bbb 35 status = 'V';
AjK 2:8aa059e7d8b1 36 velocity = 0;
AjK 2:8aa059e7d8b1 37 track = 0;
AjK 2:8aa059e7d8b1 38 magvar_dir = 'W';
AjK 2:8aa059e7d8b1 39 magvar = 0;
AjK 0:db98027c0bbb 40 }
AjK 0:db98027c0bbb 41
AjK 0:db98027c0bbb 42 GPS_Time *
AjK 0:db98027c0bbb 43 GPS_Time::timeNow(GPS_Time *n)
AjK 0:db98027c0bbb 44 {
AjK 0:db98027c0bbb 45 if (n == NULL) n = new GPS_Time;
AjK 0:db98027c0bbb 46
AjK 0:db98027c0bbb 47 do {
AjK 0:db98027c0bbb 48 memcpy(n, this, sizeof(GPS_Time));
AjK 0:db98027c0bbb 49 }
AjK 0:db98027c0bbb 50 while (memcmp(n, this, sizeof(GPS_Time)));
AjK 0:db98027c0bbb 51 return n;
AjK 0:db98027c0bbb 52 }
AjK 0:db98027c0bbb 53
AjK 0:db98027c0bbb 54 void
AjK 0:db98027c0bbb 55 GPS_Time::operator++()
AjK 0:db98027c0bbb 56 {
AjK 0:db98027c0bbb 57 hundreths++;
AjK 0:db98027c0bbb 58 if (hundreths == 10) {
AjK 0:db98027c0bbb 59 hundreths = 0;
AjK 0:db98027c0bbb 60 tenths++;
AjK 0:db98027c0bbb 61 if (tenths == 10) {
AjK 0:db98027c0bbb 62 tenths = hundreths = 0;
AjK 0:db98027c0bbb 63 }
AjK 0:db98027c0bbb 64 }
AjK 0:db98027c0bbb 65 }
AjK 0:db98027c0bbb 66
AjK 0:db98027c0bbb 67 void
AjK 0:db98027c0bbb 68 GPS_Time::operator++(int)
AjK 0:db98027c0bbb 69 {
AjK 0:db98027c0bbb 70 const int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
AjK 0:db98027c0bbb 71 bool dateInc = false;
AjK 0:db98027c0bbb 72
AjK 0:db98027c0bbb 73 tenths = hundreths = 0;
AjK 0:db98027c0bbb 74 second++;
AjK 0:db98027c0bbb 75
AjK 0:db98027c0bbb 76 if (second == 60) {
AjK 0:db98027c0bbb 77 second = 0;
AjK 0:db98027c0bbb 78 minute++;
AjK 0:db98027c0bbb 79 if (minute == 60) {
AjK 0:db98027c0bbb 80 minute = 0;
AjK 0:db98027c0bbb 81 hour++;
AjK 0:db98027c0bbb 82 if (hour == 24) {
AjK 0:db98027c0bbb 83 hour = 0;
AjK 0:db98027c0bbb 84 dateInc = true;
AjK 0:db98027c0bbb 85 }
AjK 0:db98027c0bbb 86 }
AjK 0:db98027c0bbb 87 }
AjK 0:db98027c0bbb 88
AjK 0:db98027c0bbb 89 if (dateInc) {
AjK 0:db98027c0bbb 90 /* Handle February leap year. */
AjK 0:db98027c0bbb 91 int leap_year = ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ? 1 : 0;
AjK 0:db98027c0bbb 92 int days_this_month = days[month - 1];
AjK 0:db98027c0bbb 93 if (month == 2 && leap_year) days_this_month++;
AjK 0:db98027c0bbb 94 day++;
AjK 0:db98027c0bbb 95 if (day > days_this_month) {
AjK 0:db98027c0bbb 96 day = 1;
AjK 0:db98027c0bbb 97 month++;
AjK 0:db98027c0bbb 98 if (month == 13) {
AjK 0:db98027c0bbb 99 year++;
AjK 0:db98027c0bbb 100 }
AjK 0:db98027c0bbb 101 }
AjK 0:db98027c0bbb 102 }
AjK 0:db98027c0bbb 103 }
AjK 0:db98027c0bbb 104
AjK 2:8aa059e7d8b1 105 // $GPRMC,112709.735,A,5611.5340,N,00302.0306,W,000.0,307.0,150411,,,A*70
AjK 0:db98027c0bbb 106 void
AjK 0:db98027c0bbb 107 GPS_Time::nmea_rmc(char *s)
AjK 0:db98027c0bbb 108 {
AjK 0:db98027c0bbb 109 char *token;
AjK 0:db98027c0bbb 110 int token_counter = 0;
AjK 0:db98027c0bbb 111 char *time = (char *)NULL;
AjK 0:db98027c0bbb 112 char *date = (char *)NULL;
AjK 0:db98027c0bbb 113 char *stat = (char *)NULL;
AjK 2:8aa059e7d8b1 114 char *vel = (char *)NULL;
AjK 2:8aa059e7d8b1 115 char *trk = (char *)NULL;
AjK 2:8aa059e7d8b1 116 char *magv = (char *)NULL;
AjK 2:8aa059e7d8b1 117 char *magd = (char *)NULL;
AjK 2:8aa059e7d8b1 118
AjK 0:db98027c0bbb 119 token = strtok(s, ",");
AjK 0:db98027c0bbb 120 while (token) {
AjK 0:db98027c0bbb 121 switch (token_counter) {
AjK 2:8aa059e7d8b1 122 case 9: date = token; break;
AjK 2:8aa059e7d8b1 123 case 1: time = token; break;
AjK 2:8aa059e7d8b1 124 case 2: stat = token; break;
AjK 2:8aa059e7d8b1 125 case 7: vel = token; break;
AjK 2:8aa059e7d8b1 126 case 8: trk = token; break;
AjK 2:8aa059e7d8b1 127 case 10: magv = token; break;
AjK 2:8aa059e7d8b1 128 case 11: magd = token; break;
AjK 0:db98027c0bbb 129 }
AjK 0:db98027c0bbb 130 token = strtok((char *)NULL, ",");
AjK 0:db98027c0bbb 131 token_counter++;
AjK 0:db98027c0bbb 132 }
AjK 0:db98027c0bbb 133
AjK 0:db98027c0bbb 134 if (stat && date && time) {
AjK 0:db98027c0bbb 135 hour = (char)((time[0] - '0') * 10) + (time[1] - '0');
AjK 0:db98027c0bbb 136 minute = (char)((time[2] - '0') * 10) + (time[3] - '0');
AjK 0:db98027c0bbb 137 second = (char)((time[4] - '0') * 10) + (time[5] - '0');
AjK 0:db98027c0bbb 138 day = (char)((date[0] - '0') * 10) + (date[1] - '0');
AjK 0:db98027c0bbb 139 month = (char)((date[2] - '0') * 10) + (date[3] - '0');
AjK 0:db98027c0bbb 140 year = (int)((date[4] - '0') * 10) + (date[5] - '0') + 2000;
AjK 0:db98027c0bbb 141 status = stat[0];
AjK 2:8aa059e7d8b1 142 velocity = atof(vel);
AjK 2:8aa059e7d8b1 143 track = atof(trk);
AjK 2:8aa059e7d8b1 144 magvar = atof(magv);
AjK 2:8aa059e7d8b1 145 magvar_dir = magd[0];
AjK 0:db98027c0bbb 146 }
AjK 0:db98027c0bbb 147 }
AjK 0:db98027c0bbb 148
AjK 0:db98027c0bbb 149 double
AjK 0:db98027c0bbb 150 GPS_Time::julian_day_number(GPS_Time *t) {
AjK 0:db98027c0bbb 151 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 152 return wikipedia_jdn;
AjK 0:db98027c0bbb 153 }
AjK 0:db98027c0bbb 154
AjK 0:db98027c0bbb 155 double
AjK 0:db98027c0bbb 156 GPS_Time::julian_date(GPS_Time *t) {
AjK 0:db98027c0bbb 157 double hour, minute, second, jd;
AjK 0:db98027c0bbb 158 hour = (double)t->hour;
AjK 0:db98027c0bbb 159 minute = (double)t->minute;
AjK 0:db98027c0bbb 160 second = (double)t->second + ((double)t->tenths / 10.) + ((double)t->hundreths / 100.);
AjK 0:db98027c0bbb 161
AjK 0:db98027c0bbb 162 jd = julian_day_number(t) - 0.5 +
AjK 0:db98027c0bbb 163 ((hour - 12.) / 24.) +
AjK 0:db98027c0bbb 164 (minute / 1440.) +
AjK 0:db98027c0bbb 165 (second / 86400.);
AjK 0:db98027c0bbb 166
AjK 0:db98027c0bbb 167 return jd;
AjK 0:db98027c0bbb 168 }
AjK 0:db98027c0bbb 169
AjK 0:db98027c0bbb 170 double
AjK 0:db98027c0bbb 171 GPS_Time::siderealDegrees(double jd, double longitude) {
AjK 0:db98027c0bbb 172 double sidereal, gmst, lmst;
AjK 0:db98027c0bbb 173 double T = jd - 2451545.0;
AjK 0:db98027c0bbb 174 double T1 = T / 36525.0;
AjK 0:db98027c0bbb 175 double T2 = T1 * T1;
AjK 0:db98027c0bbb 176 double T3 = T2 * T1;
AjK 0:db98027c0bbb 177
AjK 0:db98027c0bbb 178 /* Calculate gmst angle. */
AjK 0:db98027c0bbb 179 sidereal = 280.46061837 + (360.98564736629 * T) + (0.000387933 * T2) - (T3 / 38710000.0);
AjK 0:db98027c0bbb 180
AjK 0:db98027c0bbb 181 /* Convert to degrees. */
AjK 0:db98027c0bbb 182 sidereal = fmod(sidereal, 360.0);
AjK 0:db98027c0bbb 183 if (sidereal < 0.0) sidereal += 360.0;
AjK 0:db98027c0bbb 184
AjK 0:db98027c0bbb 185 gmst = sidereal;
AjK 0:db98027c0bbb 186 lmst = gmst + longitude;
AjK 0:db98027c0bbb 187 return lmst;
AjK 0:db98027c0bbb 188 }
AjK 0:db98027c0bbb 189
AjK 0:db98027c0bbb 190 double
AjK 0:db98027c0bbb 191 GPS_Time::siderealDegrees(GPS_Time *t, double longitude) {
AjK 0:db98027c0bbb 192 if (t == NULL) t = new GPS_Time;
AjK 0:db98027c0bbb 193 return siderealDegrees(julian_date(t), longitude);
AjK 0:db98027c0bbb 194 }
AjK 0:db98027c0bbb 195
AjK 0:db98027c0bbb 196 double
AjK 0:db98027c0bbb 197 GPS_Time::siderealHA(double jd, double longitude) {
AjK 0:db98027c0bbb 198 double lmst = siderealDegrees(jd, longitude);
AjK 0:db98027c0bbb 199 return lmst / 360.0 * 24.0;
AjK 0:db98027c0bbb 200 }
AjK 0:db98027c0bbb 201
AjK 0:db98027c0bbb 202 double
AjK 0:db98027c0bbb 203 GPS_Time::siderealHA(GPS_Time *t, double longitude) {
AjK 0:db98027c0bbb 204 double lmst = siderealDegrees(t, longitude);
AjK 0:db98027c0bbb 205 return lmst / 360.0 * 24.0;
AjK 0:db98027c0bbb 206 }
AjK 0:db98027c0bbb 207