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

Revision:
0:db98027c0bbb
Child:
2:8aa059e7d8b1
diff -r 000000000000 -r db98027c0bbb GPS_Time.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GPS_Time.cpp	Mon Nov 15 20:11:16 2010 +0000
@@ -0,0 +1,191 @@
+/*
+    Copyright (c) 2010 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+
+#include "GPS_Time.h"
+
+GPS_Time::GPS_Time() 
+{
+    year = 2000;
+    month = 1;
+    day = 1;
+    hour = 0;
+    minute = 0;
+    second = 0;
+    tenths = 0;
+    hundreths = 0;
+    status = 'V';
+}
+
+GPS_Time *
+GPS_Time::timeNow(GPS_Time *n)
+{
+    if (n == NULL) n = new GPS_Time;
+    
+    do {
+        memcpy(n, this, sizeof(GPS_Time));
+    }
+    while (memcmp(n, this, sizeof(GPS_Time)));
+    return n;    
+}
+
+void
+GPS_Time::operator++()
+{
+    hundreths++;
+    if (hundreths == 10) {
+        hundreths = 0;
+        tenths++;
+        if (tenths == 10) {
+            tenths = hundreths = 0;
+        }
+    }
+}
+
+void
+GPS_Time::operator++(int)
+{
+    const int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
+    bool dateInc = false;
+    
+    tenths = hundreths = 0;
+    second++;
+    
+    if (second == 60) {
+        second = 0;
+        minute++;
+        if (minute == 60) {
+            minute = 0;
+            hour++;
+            if (hour == 24) {
+                hour = 0;
+                dateInc = true;
+            }
+        }
+    }
+    
+    if (dateInc) {
+        /* Handle February leap year. */    
+        int leap_year = ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ? 1 : 0;
+        int days_this_month = days[month - 1];
+        if (month == 2 && leap_year) days_this_month++;        
+        day++;
+        if (day > days_this_month) {
+            day = 1;
+            month++;
+            if (month == 13) {
+                year++;
+            }
+        }
+    }
+}
+
+void 
+GPS_Time::nmea_rmc(char *s)
+{
+    char *token;
+    int  token_counter = 0;
+    char *time   = (char *)NULL;
+    char *date   = (char *)NULL;
+    char *stat   = (char *)NULL;
+    
+    token = strtok(s, ",");
+    while (token) {
+        switch (token_counter) {
+            case 9: date   = token; break;
+            case 1: time   = token; break;
+            case 2: stat   = token; break;
+        }
+        token = strtok((char *)NULL, ",");
+        token_counter++;
+    }
+    
+    if (stat && date && time) {
+        hour       = (char)((time[0] - '0') * 10) + (time[1] - '0');
+        minute     = (char)((time[2] - '0') * 10) + (time[3] - '0');
+        second     = (char)((time[4] - '0') * 10) + (time[5] - '0');
+        day        = (char)((date[0] - '0') * 10) + (date[1] - '0');
+        month      = (char)((date[2] - '0') * 10) + (date[3] - '0');
+        year       =  (int)((date[4] - '0') * 10) + (date[5] - '0') + 2000;
+        status     = stat[0];
+        
+    }    
+}
+
+double 
+GPS_Time::julian_day_number(GPS_Time *t) {
+    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;    
+    return wikipedia_jdn;
+}
+
+double 
+GPS_Time::julian_date(GPS_Time *t) {
+    double hour, minute, second, jd;
+    hour   = (double)t->hour;
+    minute = (double)t->minute;
+    second = (double)t->second + ((double)t->tenths / 10.) + ((double)t->hundreths / 100.);
+                                 
+    jd = julian_day_number(t) -  0.5 +
+         ((hour - 12.) / 24.) +
+         (minute / 1440.) + 
+         (second / 86400.);        
+        
+    return jd;
+}
+
+double 
+GPS_Time::siderealDegrees(double jd, double longitude) {
+    double sidereal, gmst, lmst;
+    double T  = jd - 2451545.0;
+    double T1 = T / 36525.0;
+    double T2 = T1 * T1;
+    double T3 = T2 * T1;
+     
+    /* Calculate gmst angle. */
+    sidereal = 280.46061837 + (360.98564736629 * T) + (0.000387933 * T2) - (T3 / 38710000.0);
+     
+    /* Convert to degrees. */
+    sidereal = fmod(sidereal, 360.0);
+    if (sidereal < 0.0) sidereal += 360.0;
+ 
+    gmst = sidereal;
+    lmst = gmst + longitude;
+    return lmst;
+}
+
+double 
+GPS_Time::siderealDegrees(GPS_Time *t, double longitude) {
+    if (t == NULL) t = new GPS_Time;
+    return siderealDegrees(julian_date(t), longitude);
+}
+
+double 
+GPS_Time::siderealHA(double jd, double longitude) {
+    double lmst = siderealDegrees(jd, longitude);
+    return lmst / 360.0 * 24.0;
+}
+
+double 
+GPS_Time::siderealHA(GPS_Time *t, double longitude) {
+    double lmst = siderealDegrees(t, longitude);
+    return lmst / 360.0 * 24.0;
+}
+