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
GPS_Time.cpp@2:8aa059e7d8b1, 2011-04-15 (annotated)
- 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?
User | Revision | Line number | New 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 |