Dependencies:   mbed

Committer:
pd0wm
Date:
Tue Sep 27 19:46:30 2011 +0000
Revision:
0:bec310bde899

        

Who changed what in which revision?

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