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

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     velocity = 0;
00037     track = 0;    
00038     magvar_dir = 'W';
00039     magvar = 0;
00040 }
00041 
00042 time_t
00043 GPS_Time::to_C_tm(bool set) 
00044 {
00045     GPS_Time t;
00046     tm       ct;
00047     time_t   q;
00048     
00049     timeNow(&t);
00050     ct.tm_sec       = t.second;
00051     ct.tm_min       = t.minute;
00052     ct.tm_hour      = t.hour;
00053     ct.tm_mday      = t.day;
00054     ct.tm_mon       = t.month - 1;
00055     ct.tm_year      = t.year - 1900;
00056     ct.tm_isdst     = 0; // GPS has no understanding of DST.    
00057     
00058     q = mktime(&ct);
00059     if (set) {
00060         set_time(q);
00061     }
00062     return q;
00063 }
00064 
00065 GPS_Time *
00066 GPS_Time::timeNow(GPS_Time *n)
00067 {
00068     if (n == NULL) n = new GPS_Time;
00069     
00070     do {
00071         memcpy(n, this, sizeof(GPS_Time));
00072     }
00073     while (memcmp(n, this, sizeof(GPS_Time)));
00074     return n;    
00075 }
00076 
00077 void
00078 GPS_Time::operator++()
00079 {
00080     hundreths++;
00081     if (hundreths == 10) {
00082         hundreths = 0;
00083         tenths++;
00084         if (tenths == 10) {
00085             tenths = hundreths = 0;
00086         }
00087     }
00088 }
00089 
00090 void
00091 GPS_Time::operator++(int)
00092 {
00093     const int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
00094     bool dateInc = false;
00095     
00096     tenths = hundreths = 0;
00097     second++;
00098     
00099     if (second == 60) {
00100         second = 0;
00101         minute++;
00102         if (minute == 60) {
00103             minute = 0;
00104             hour++;
00105             if (hour == 24) {
00106                 hour = 0;
00107                 dateInc = true;
00108             }
00109         }
00110     }
00111     
00112     if (dateInc) {
00113         /* Handle February leap year. */    
00114         int leap_year = ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ? 1 : 0;
00115         int days_this_month = days[month - 1];
00116         if (month == 2 && leap_year) days_this_month++;        
00117         day++;
00118         if (day > days_this_month) {
00119             day = 1;
00120             month++;
00121             if (month == 13) {
00122                 year++;
00123             }
00124         }
00125     }
00126 }
00127 
00128 // $GPRMC,112709.735,A,5611.5340,N,00302.0306,W,000.0,307.0,150411,,,A*70
00129 void 
00130 GPS_Time::nmea_rmc(char *s)
00131 {
00132     char *token;
00133     int  token_counter = 0;
00134     char *time   = (char *)NULL;
00135     char *date   = (char *)NULL;
00136     char *stat   = (char *)NULL;
00137     char *vel    = (char *)NULL;
00138     char *trk    = (char *)NULL;
00139     char *magv   = (char *)NULL;
00140     char *magd   = (char *)NULL;
00141 
00142     token = strtok(s, ",");
00143     while (token) {
00144         switch (token_counter) {
00145             case 9:  date   = token; break;
00146             case 1:  time   = token; break;
00147             case 2:  stat   = token; break;
00148             case 7:  vel    = token; break;
00149             case 8:  trk    = token; break;
00150             case 10: magv   = token; break;
00151             case 11: magd   = token; break;
00152         }
00153         token = strtok((char *)NULL, ",");
00154         token_counter++;
00155     }
00156     
00157     if (stat && date && time) {
00158         hour       = (char)((time[0] - '0') * 10) + (time[1] - '0');
00159         minute     = (char)((time[2] - '0') * 10) + (time[3] - '0');
00160         second     = (char)((time[4] - '0') * 10) + (time[5] - '0');
00161         day        = (char)((date[0] - '0') * 10) + (date[1] - '0');
00162         month      = (char)((date[2] - '0') * 10) + (date[3] - '0');
00163         year       =  (int)((date[4] - '0') * 10) + (date[5] - '0') + 2000;
00164         status     = stat[0];
00165         velocity   = atof(vel);
00166         track      = atof(trk);
00167         magvar     = atof(magv);
00168         magvar_dir = magd[0];
00169     }    
00170 }
00171 
00172 double 
00173 GPS_Time::julian_day_number(GPS_Time *t) {
00174     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;    
00175     return wikipedia_jdn;
00176 }
00177 
00178 double 
00179 GPS_Time::julian_date(GPS_Time *t) {
00180     double hour, minute, second, jd;
00181     hour   = (double)t->hour;
00182     minute = (double)t->minute;
00183     second = (double)t->second + ((double)t->tenths / 10.) + ((double)t->hundreths / 100.);
00184                                  
00185     jd = julian_day_number(t) -  0.5 +
00186          ((hour - 12.) / 24.) +
00187          (minute / 1440.) + 
00188          (second / 86400.);        
00189         
00190     return jd;
00191 }
00192 
00193 double 
00194 GPS_Time::siderealDegrees(double jd, double longitude) {
00195     double sidereal, gmst, lmst;
00196     double T  = jd - 2451545.0;
00197     double T1 = T / 36525.0;
00198     double T2 = T1 * T1;
00199     double T3 = T2 * T1;
00200      
00201     /* Calculate gmst angle. */
00202     sidereal = 280.46061837 + (360.98564736629 * T) + (0.000387933 * T2) - (T3 / 38710000.0);
00203      
00204     /* Convert to degrees. */
00205     sidereal = fmod(sidereal, 360.0);
00206     if (sidereal < 0.0) sidereal += 360.0;
00207  
00208     gmst = sidereal;
00209     lmst = gmst + longitude;
00210     return lmst;
00211 }
00212 
00213 double 
00214 GPS_Time::siderealDegrees(GPS_Time *t, double longitude) {
00215     if (t == NULL) t = new GPS_Time;
00216     return siderealDegrees(julian_date(t), longitude);
00217 }
00218 
00219 double 
00220 GPS_Time::siderealHA(double jd, double longitude) {
00221     double lmst = siderealDegrees(jd, longitude);
00222     return lmst / 360.0 * 24.0;
00223 }
00224 
00225 double 
00226 GPS_Time::siderealHA(GPS_Time *t, double longitude) {
00227     double lmst = siderealDegrees(t, longitude);
00228     return lmst / 360.0 * 24.0;
00229 }
00230