Graham Cantin / MODGPS

Dependents:   Telnet_server

Fork of MODGPS by Andy K

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::GPS_Time() 
00026 {
00027     year = 2000;
00028     month = 1;
00029     day = 1;
00030     hour = 0;
00031     minute = 0;
00032     second = 0;
00033     tenths = 0;
00034     hundreths = 0;
00035     status = 'V';
00036 }
00037 
00038 GPS_Time *
00039 GPS_Time::timeNow(GPS_Time *n)
00040 {
00041     if (n == NULL) n = new GPS_Time;
00042     
00043     do {
00044         memcpy(n, this, sizeof(GPS_Time));
00045     }
00046     while (memcmp(n, this, sizeof(GPS_Time)));
00047     return n;    
00048 }
00049 
00050 void
00051 GPS_Time::operator++()
00052 {
00053     hundreths++;
00054     if (hundreths == 10) {
00055         hundreths = 0;
00056         tenths++;
00057         if (tenths == 10) {
00058             tenths = hundreths = 0;
00059         }
00060     }
00061 }
00062 
00063 void
00064 GPS_Time::operator++(int)
00065 {
00066     const int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
00067     bool dateInc = false;
00068     
00069     tenths = hundreths = 0;
00070     second++;
00071     
00072     if (second == 60) {
00073         second = 0;
00074         minute++;
00075         if (minute == 60) {
00076             minute = 0;
00077             hour++;
00078             if (hour == 24) {
00079                 hour = 0;
00080                 dateInc = true;
00081             }
00082         }
00083     }
00084     
00085     if (dateInc) {
00086         /* Handle February leap year. */    
00087         int leap_year = ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ? 1 : 0;
00088         int days_this_month = days[month - 1];
00089         if (month == 2 && leap_year) days_this_month++;        
00090         day++;
00091         if (day > days_this_month) {
00092             day = 1;
00093             month++;
00094             if (month == 13) {
00095                 year++;
00096             }
00097         }
00098     }
00099 }
00100 
00101 void 
00102 GPS_Time::nmea_rmc(char *s)
00103 {
00104     char *token;
00105     int  token_counter = 0;
00106     char *time   = (char *)NULL;
00107     char *date   = (char *)NULL;
00108     char *stat   = (char *)NULL;
00109     
00110     token = strtok(s, ",");
00111     while (token) {
00112         switch (token_counter) {
00113             case 9: date   = token; break;
00114             case 1: time   = token; break;
00115             case 2: stat   = token; break;
00116         }
00117         token = strtok((char *)NULL, ",");
00118         token_counter++;
00119     }
00120     
00121     if (stat && date && time) {
00122         hour       = (char)((time[0] - '0') * 10) + (time[1] - '0');
00123         minute     = (char)((time[2] - '0') * 10) + (time[3] - '0');
00124         second     = (char)((time[4] - '0') * 10) + (time[5] - '0');
00125         day        = (char)((date[0] - '0') * 10) + (date[1] - '0');
00126         month      = (char)((date[2] - '0') * 10) + (date[3] - '0');
00127         year       =  (int)((date[4] - '0') * 10) + (date[5] - '0') + 2000;
00128         status     = stat[0];
00129         
00130     }    
00131 }
00132 
00133 double 
00134 GPS_Time::julian_day_number(GPS_Time *t) {
00135     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;    
00136     return wikipedia_jdn;
00137 }
00138 
00139 double 
00140 GPS_Time::julian_date(GPS_Time *t) {
00141     double hour, minute, second, jd;
00142     hour   = (double)t->hour;
00143     minute = (double)t->minute;
00144     second = (double)t->second + ((double)t->tenths / 10.) + ((double)t->hundreths / 100.);
00145                                  
00146     jd = julian_day_number(t) -  0.5 +
00147          ((hour - 12.) / 24.) +
00148          (minute / 1440.) + 
00149          (second / 86400.);        
00150         
00151     return jd;
00152 }
00153 
00154 double 
00155 GPS_Time::siderealDegrees(double jd, double longitude) {
00156     double sidereal, gmst, lmst;
00157     double T  = jd - 2451545.0;
00158     double T1 = T / 36525.0;
00159     double T2 = T1 * T1;
00160     double T3 = T2 * T1;
00161      
00162     /* Calculate gmst angle. */
00163     sidereal = 280.46061837 + (360.98564736629 * T) + (0.000387933 * T2) - (T3 / 38710000.0);
00164      
00165     /* Convert to degrees. */
00166     sidereal = fmod(sidereal, 360.0);
00167     if (sidereal < 0.0) sidereal += 360.0;
00168  
00169     gmst = sidereal;
00170     lmst = gmst + longitude;
00171     return lmst;
00172 }
00173 
00174 double 
00175 GPS_Time::siderealDegrees(GPS_Time *t, double longitude) {
00176     if (t == NULL) t = new GPS_Time;
00177     return siderealDegrees(julian_date(t), longitude);
00178 }
00179 
00180 double 
00181 GPS_Time::siderealHA(double jd, double longitude) {
00182     double lmst = siderealDegrees(jd, longitude);
00183     return lmst / 360.0 * 24.0;
00184 }
00185 
00186 double 
00187 GPS_Time::siderealHA(GPS_Time *t, double longitude) {
00188     double lmst = siderealDegrees(t, longitude);
00189     return lmst / 360.0 * 24.0;
00190 }
00191