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:
Mon Nov 15 20:11:16 2010 +0000
Revision:
0:db98027c0bbb
Child:
2:8aa059e7d8b1
1.8

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