Dependents:   V2_GPSRTC

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GPS_Time.cpp Source File

GPS_Time.cpp

00001 /*
00002     Copyright (c) 2010 Andy Kirkham
00003  
00004     Permission is hereby granted, free of charge, to any person obtaining a copy
00005     of this software and associated documentation files (the "Software"), to deal
00006     in the Software without restriction, including without limitation the rights
00007     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008     copies of the Software, and to permit persons to whom the Software is
00009     furnished to do so, subject to the following conditions:
00010  
00011     The above copyright notice and this permission notice shall be included in
00012     all copies or substantial portions of the Software.
00013  
00014     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020     THE SOFTWARE.
00021 */
00022 
00023 #include "GPS_Time.h"
00024 
00025 //GPS_Time *t = gps.timeNow();
00026 //pc.printf("%02d:%02d:%02d.%i %02d/%02d/%04d\r\n\n", t->hour, t->minute, t->second, t->hundreths, t->day, t->month, t->year);
00027 //delete(t);
00028 
00029 GPS_Time::GPS_Time() 
00030 {
00031     year = 2000;
00032     month = 1;
00033     day = 1;
00034     hour = 0;
00035     minute = 0;
00036     second = 0;
00037     tenths = 0;
00038     hundreths = 0;
00039     status = 'V';
00040     velocity = 0;
00041     track = 0;    
00042     magvar_dir = 'W';
00043     magvar = 0;
00044 }
00045 
00046 time_t
00047 GPS_Time::to_C_tm(bool set) 
00048 {
00049     GPS_Time t;
00050     tm       ct;
00051     time_t   q;
00052     
00053     timeNow(&t);
00054     ct.tm_sec       = t.second;
00055     ct.tm_min       = t.minute;
00056     ct.tm_hour      = t.hour;
00057     ct.tm_mday      = t.day;
00058     ct.tm_mon       = t.month - 1;
00059     ct.tm_year      = t.year - 1900;
00060     ct.tm_isdst     = 0; // GPS has no understanding of DST.    
00061     
00062     q = mktime(&ct);
00063     if (set) {
00064         set_time(q);
00065     }
00066     return q;
00067 }
00068 
00069 GPS_Time *
00070 GPS_Time::timeNow(GPS_Time *n)
00071 {
00072     if (n == NULL) n = new GPS_Time;
00073     
00074     do {
00075         memcpy(n, this, sizeof(GPS_Time));
00076     }
00077     while (memcmp(n, this, sizeof(GPS_Time)));
00078     return n;    
00079 }
00080 
00081 void
00082 GPS_Time::operator++()
00083 {
00084     hundreths++;
00085     if (hundreths == 10) {
00086         hundreths = 0;
00087         tenths++;
00088         if (tenths == 10) {
00089             tenths = hundreths = 0;
00090         }
00091     }
00092 }
00093 
00094 void
00095 GPS_Time::operator++(int)
00096 {
00097     const int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
00098     bool dateInc = false;
00099     
00100     tenths = hundreths = 0;
00101     second++;
00102     
00103     if (second == 60) {
00104         second = 0;
00105         minute++;
00106         if (minute == 60) {
00107             minute = 0;
00108             hour++;
00109             if (hour == 24) {
00110                 hour = 0;
00111                 dateInc = true;
00112             }
00113         }
00114     }
00115     
00116     if (dateInc) {
00117         /* Handle February leap year. */    
00118         int leap_year = ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ? 1 : 0;
00119         int days_this_month = days[month - 1];
00120         if (month == 2 && leap_year) days_this_month++;        
00121         day++;
00122         if (day > days_this_month) {
00123             day = 1;
00124             month++;
00125             if (month == 13) {
00126                 year++;
00127             }
00128         }
00129     }
00130 }
00131 
00132 // $GPRMC,112709.735,A,5611.5340,N,00302.0306,W,000.0,307.0,150411,,,A*70
00133 void 
00134 GPS_Time::nmea_rmc(char *s)
00135 {
00136     char *token;
00137     int  token_counter = 0;
00138     char *time   = (char *)NULL;
00139     char *date   = (char *)NULL;
00140     char *stat   = (char *)NULL;
00141     char *vel    = (char *)NULL;
00142     char *trk    = (char *)NULL;
00143     char *magv   = (char *)NULL;
00144     char *magd   = (char *)NULL;
00145 
00146     token = strtok(s, ",");
00147     while (token) {
00148         switch (token_counter) {
00149             case 9:  date   = token; break;
00150             case 1:  time   = token; break;
00151             case 2:  stat   = token; break;
00152             case 7:  vel    = token; break;
00153             case 8:  trk    = token; break;
00154             case 10: magv   = token; break;
00155             case 11: magd   = token; break;
00156         }
00157         token = strtok((char *)NULL, ",");
00158         token_counter++;
00159     }
00160     
00161     if (stat && date && time) {
00162         hour       = (char)((time[0] - '0') * 10) + (time[1] - '0');
00163         minute     = (char)((time[2] - '0') * 10) + (time[3] - '0');
00164         second     = (char)((time[4] - '0') * 10) + (time[5] - '0');
00165         day        = (char)((date[0] - '0') * 10) + (date[1] - '0');
00166         month      = (char)((date[2] - '0') * 10) + (date[3] - '0');
00167         year       =  (int)((date[4] - '0') * 10) + (date[5] - '0') + 2000;
00168         status     = stat[0];
00169         velocity   = atof(vel);
00170         track      = atof(trk);
00171         magvar     = atof(magv);
00172         magvar_dir = magd[0];
00173     }    
00174 }
00175 
00176 double 
00177 GPS_Time::julian_day_number(GPS_Time *t) {
00178     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;    
00179     return wikipedia_jdn;
00180 }
00181 
00182 double 
00183 GPS_Time::julian_date(GPS_Time *t) {
00184     double hour, minute, second, jd;
00185     hour   = (double)t->hour;
00186     minute = (double)t->minute;
00187     second = (double)t->second + ((double)t->tenths / 10.) + ((double)t->hundreths / 100.);
00188                                  
00189     jd = julian_day_number(t) -  0.5 +
00190          ((hour - 12.) / 24.) +
00191          (minute / 1440.) + 
00192          (second / 86400.);        
00193         
00194     return jd;
00195 }
00196 
00197 double 
00198 GPS_Time::siderealDegrees(double jd, double longitude) {
00199     double sidereal, gmst, lmst;
00200     double T  = jd - 2451545.0;
00201     double T1 = T / 36525.0;
00202     double T2 = T1 * T1;
00203     double T3 = T2 * T1;
00204      
00205     /* Calculate gmst angle. */
00206     sidereal = 280.46061837 + (360.98564736629 * T) + (0.000387933 * T2) - (T3 / 38710000.0);
00207      
00208     /* Convert to degrees. */
00209     sidereal = fmod(sidereal, 360.0);
00210     if (sidereal < 0.0) sidereal += 360.0;
00211  
00212     gmst = sidereal;
00213     lmst = gmst + longitude;
00214     return lmst;
00215 }
00216 
00217 double 
00218 GPS_Time::siderealDegrees(GPS_Time *t, double longitude) {
00219     if (t == NULL) t = new GPS_Time;
00220     return siderealDegrees(julian_date(t), longitude);
00221 }
00222 
00223 double 
00224 GPS_Time::siderealHA(double jd, double longitude) {
00225     double lmst = siderealDegrees(jd, longitude);
00226     return lmst / 360.0 * 24.0;
00227 }
00228 
00229 double 
00230 GPS_Time::siderealHA(GPS_Time *t, double longitude) {
00231     double lmst = siderealDegrees(t, longitude);
00232     return lmst / 360.0 * 24.0;
00233 }
00234