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

Files at this revision

API Documentation at this revision

Comitter:
AjK
Date:
Fri Apr 15 12:23:52 2011 +0000
Parent:
1:6aec92e77ad2
Child:
3:28a1b60b0f37
Commit message:
1.12 See ChangeLog.c

Changed in this revision

ChangeLog.c Show annotated file Show diff for this revision Revisions of this file
GPS.cpp Show annotated file Show diff for this revision Revisions of this file
GPS.h Show annotated file Show diff for this revision Revisions of this file
GPS_Time.cpp Show annotated file Show diff for this revision Revisions of this file
GPS_Time.h Show annotated file Show diff for this revision Revisions of this file
GPS_VTG.cpp Show annotated file Show diff for this revision Revisions of this file
GPS_VTG.h Show annotated file Show diff for this revision Revisions of this file
example1.cpp Show annotated file Show diff for this revision Revisions of this file
example2.cpp Show annotated file Show diff for this revision Revisions of this file
example3.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/ChangeLog.c	Sat Nov 20 21:02:06 2010 +0000
+++ b/ChangeLog.c	Fri Apr 15 12:23:52 2011 +0000
@@ -59,5 +59,10 @@
 1.11 - 17/11/2010
 
     * Mbed's systems don't like @mainpage, rolling back
-                           
+
+1.12 - 15/04/2011
+
+    * Added VTG sentence (vectors speed and direction)
+      See example3.cpp
+                                 
 */
--- a/GPS.cpp	Sat Nov 20 21:02:06 2010 +0000
+++ b/GPS.cpp	Fri Apr 15 12:23:52 2011 +0000
@@ -97,6 +97,22 @@
     return q;
 }
 
+GPS_VTG *
+GPS::vtg(GPS_VTG *q)
+{
+    GPS_VTG a, b;
+    
+    if (q == NULL) q = new GPS_VTG;
+    
+    do {
+        memcpy(&a, &theVTG, sizeof(GPS_VTG));
+        memcpy(&b, &theVTG, sizeof(GPS_VTG));
+    }
+    while (memcmp(&a, &b, sizeof(GPS_VTG)) != 0);
+    
+    return q;
+}
+
 void
 GPS::ticktock(void)
 {
@@ -115,6 +131,10 @@
             thePlace.nmea_gga(s);            
             cb_gga.call();
         }
+        else if (!strncmp(s, "$GPVTG", 6)) {
+            theVTG.nmea_vtg(s);            
+            cb_vtg.call();
+        }
         process_required = false;
     }
 }
@@ -126,7 +146,7 @@
     theTime++; // Increment the time/date by one second. 
     cb_pps.call();
 }
-    
+
 void 
 GPS::rx_irq(void)
 {
@@ -137,6 +157,7 @@
         iir = (uint32_t)*((char *)_base + GPS_IIR); 
         while((int)(*((char *)_base + GPS_LSR) & 0x1)) {
             c = (char)(*((char *)_base + GPS_RBR) & 0xFF); 
+            // debugging LPC_UART0->RBR = c;
             buffer[active_buffer][rx_buffer_in++] = c;
             rx_buffer_in &= (GPS_BUFFER_LEN - 1);
             if (c == '\n') {
--- a/GPS.h	Sat Nov 20 21:02:06 2010 +0000
+++ b/GPS.h	Fri Apr 15 12:23:52 2011 +0000
@@ -24,6 +24,7 @@
 #define GPS_H
 
 #include "mbed.h"
+#include "GPS_VTG.h"
 #include "GPS_Time.h"
 #include "GPS_Geodetic.h"
 
@@ -258,6 +259,54 @@
      */
     double height(void) { return altitude(); }
     
+    //! Get all vector parameters together.
+    /**
+     * Pass a pointer to a GPS_VTG object and the current
+     * GPS data will be copied into it.
+     *
+     * @code
+     *     // Assuming we have a GPS object previously created...
+     *     GPS gps(NC, p9); 
+     *
+     *     // Then get the data...
+     *     GPS_VTG p;
+     *     gps.vtg(&p);
+     *     printf("Speed (knots)  = %.4f", p.velocity_knots);
+     *     printf("Speed (kps)    = %.4f", p.velocity_kps);
+     *     printf("Track (true)  = %.4f", p.track_true);
+     *     printf("Track (mag)    = %.4f", p.track_mag);
+     *
+     * @endcode
+     *
+     * @ingroup API
+     * @param g A GSP_VTG pointer to an existing GPS_VTG object.
+     * @return GPS_VTG * The pointer passed in.
+     */
+    GPS_VTG *vtg(GPS_VTG *g);
+    
+    //! Get all vector parameters together.
+    /**
+     * Get all the vector data at once. For example:-
+     *
+     * @code
+     *     // Assuming we have a GPS object previously created...
+     *     GPS gps(NC, p9); 
+     *
+     *     // Then get the data...
+     *     GPS_VTG *p = gps.vtg();
+     *     printf("Speed (knots)  = %.4f", p->velocity_knots);
+     *     printf("Speed (kps)    = %.4f", p->velocity_kps);
+     *     printf("Track (true)  = %.4f", p->track_true);
+     *     printf("Track (mag)    = %.4f", p->track_mag);     
+     *     delete(p); // then remember to delete the object to prevent memory leaks.
+     *
+     * @endcode
+     *
+     * @ingroup API
+     * @return GPS_Geodetic * A pointer to the data.
+     */
+    GPS_VTG *vtg(void) { return vtg(NULL); }
+    
     //! Get all three geodetic parameters together.
     /**
      * Pass a pointer to a GPS_Geodetic object and the current
@@ -601,6 +650,52 @@
     //! A callback object for the NMEA GGA message processed signal user API.
     FunctionPointer cb_gga;
 
+
+    //! Attach a user callback function to the NMEA VTG message processed signal.
+    /**
+     * Attach a user callback object/method to call when an NMEA VTG packet has been processed. 
+     *
+     * @code
+     *     class FOO {
+     *     public:
+     *         void myCallback(void);
+     *     };
+     *
+     *     GPS gps(NC, p9); 
+     *     Foo foo;
+     *
+     *     gps.attach_vtg(foo, &FOO::myCallback);
+     * 
+     * @endcode
+     *
+     * @ingroup API 
+     * @param tptr pointer to the object to call the member function on
+     * @param mptr pointer to the member function to be called
+     */
+    template<typename T>
+    void attach_vtg(T* tptr, void (T::*mptr)(void)) { cb_vtg.attach(tptr, mptr); }
+    
+    //! Attach a user callback function to the NMEA VTG message processed signal.
+    /**
+     * Attach a user callback function pointer to call when an NMEA VTG packet has been processed. 
+     *
+     * @code
+     *     void myCallback(void) { ... }
+     *
+     *     GPS gps(NC, p9); 
+     *     Foo foo;
+     *
+     *     gps.attach_vtg(&myCallback);
+     * 
+     * @endcode
+     *
+     * @ingroup API 
+     * @param fptr Callback function pointer.
+     */
+    void attach_vtg(void (*fptr)(void)) { cb_vtg.attach(fptr); } 
+    
+    //! A callback object for the NMEA RMS message processed signal user API.
+    FunctionPointer cb_vtg;
     //! Set the baud rate the GPS module is using.
     /** 
      * Set the baud rate of the serial port
@@ -640,7 +735,10 @@
     GPS_Time     theTime;
     
     //! A GPS_Geodetic object used to hold the last parsed positional data.
-    GPS_Geodetic thePlace;        
+    GPS_Geodetic thePlace;
+    
+    //! A GPS_VTG object used to hold vector data.
+    GPS_VTG      theVTG;       
 };
 
 #endif
--- a/GPS_Time.cpp	Sat Nov 20 21:02:06 2010 +0000
+++ b/GPS_Time.cpp	Fri Apr 15 12:23:52 2011 +0000
@@ -33,6 +33,10 @@
     tenths = 0;
     hundreths = 0;
     status = 'V';
+    velocity = 0;
+    track = 0;    
+    magvar_dir = 'W';
+    magvar = 0;
 }
 
 GPS_Time *
@@ -98,6 +102,7 @@
     }
 }
 
+// $GPRMC,112709.735,A,5611.5340,N,00302.0306,W,000.0,307.0,150411,,,A*70
 void 
 GPS_Time::nmea_rmc(char *s)
 {
@@ -106,13 +111,21 @@
     char *time   = (char *)NULL;
     char *date   = (char *)NULL;
     char *stat   = (char *)NULL;
-    
+    char *vel    = (char *)NULL;
+    char *trk    = (char *)NULL;
+    char *magv   = (char *)NULL;
+    char *magd   = (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;
+            case 9:  date   = token; break;
+            case 1:  time   = token; break;
+            case 2:  stat   = token; break;
+            case 7:  vel    = token; break;
+            case 8:  trk    = token; break;
+            case 10: magv   = token; break;
+            case 11: magd   = token; break;
         }
         token = strtok((char *)NULL, ",");
         token_counter++;
@@ -126,7 +139,10 @@
         month      = (char)((date[2] - '0') * 10) + (date[3] - '0');
         year       =  (int)((date[4] - '0') * 10) + (date[5] - '0') + 2000;
         status     = stat[0];
-        
+        velocity   = atof(vel);
+        track      = atof(trk);
+        magvar     = atof(magv);
+        magvar_dir = magd[0];
     }    
 }
 
--- a/GPS_Time.h	Sat Nov 20 21:02:06 2010 +0000
+++ b/GPS_Time.h	Fri Apr 15 12:23:52 2011 +0000
@@ -48,6 +48,14 @@
     int  hundreths; 
     //! Time status.
     char status;    
+    //! The velocity (in knots)
+    double velocity;
+    //! The track (in decimal degrees true)
+    double track;    
+    //! The magnetic variation direction
+    char magvar_dir;
+    //! The magnetic variation value
+    double magvar;
     
     GPS_Time();
     void fractionalReset(void) { tenths = hundreths = 0; }
@@ -56,6 +64,12 @@
     GPS_Time * timeNow(GPS_Time *n);
     GPS_Time * timeNow(void) { return timeNow(NULL); }
     void nmea_rmc(char *s);
+    double velocity_knots(void) { return velocity; }
+    double velocity_kph(void) { return (velocity * 1.852); }
+    double velocity_mps(void) { return velocity_kph() / 3600.0; }
+    double velocity_mph(void) { return velocity_kph() / 0.621371192; }
+    double track_over_ground(void) { return track; }
+    double magnetic_variation(void) { return magvar_dir == 'W' ? (magvar * -1.0) : (magvar); }
     double julian_day_number(GPS_Time *t);
     double julian_date(GPS_Time *t);
     double julian_day_number(void) { return julian_day_number(this); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GPS_VTG.cpp	Fri Apr 15 12:23:52 2011 +0000
@@ -0,0 +1,72 @@
+/*
+    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_VTG.h"
+
+GPS_VTG::GPS_VTG() 
+{
+    _velocity_knots = 0;
+    _velocity_kph = 0;
+    _track_true = 0;    
+    _track_mag = 0;    
+}
+
+GPS_VTG *
+GPS_VTG::vtg(GPS_VTG *n)
+{
+    if (n == NULL) n = new GPS_VTG;
+    
+    do {
+        memcpy(n, this, sizeof(GPS_VTG));
+    }
+    while (memcmp(n, this, sizeof(GPS_VTG)));
+    return n;    
+}
+
+void 
+GPS_VTG::nmea_vtg(char *s)
+{
+    char *token;
+    int  token_counter = 0;
+    char *vel_knots = (char *)NULL;
+    char *vel_kph   = (char *)NULL;
+    char *trk_t  = (char *)NULL;
+    char *trk_m  = (char *)NULL;
+    
+    token = strtok(s, ",");
+    while (token) {
+        switch (token_counter) {
+            case 5:  vel_knots = token; break;
+            case 7:  vel_kph   = token; break;
+            case 1:  trk_t     = token; break;
+            case 3:  trk_m     = token; break;            
+        }
+        token = strtok((char *)NULL, ",");
+        token_counter++;
+    }
+    
+    if (vel_knots) { _velocity_knots = atof(vel_knots); }
+    if (vel_kph)   { _velocity_kph   = atof(vel_kph); }
+    if (trk_t)     { _track_true     = atof(trk_t); }
+    if (trk_m)     { _track_mag      = atof(trk_m); }    
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GPS_VTG.h	Fri Apr 15 12:23:52 2011 +0000
@@ -0,0 +1,54 @@
+/*
+    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.
+*/
+
+#ifndef GPS_VTG_H
+#define GPS_VTG_H
+
+#include "mbed.h"
+
+/** GPS_Time definition.
+ */
+class GPS_VTG {
+public:
+
+    //! The velocity (in knots)
+    double _velocity_knots;
+    //! The velocity (in kph)
+    double _velocity_kph;
+    //! The track (in decimal degrees true)
+    double _track_true;    
+    //! The track (in decimal degrees magnetic)
+    double _track_mag;    
+    
+    GPS_VTG();
+    GPS_VTG * vtg(GPS_VTG *n);
+    void nmea_vtg(char *s); 
+    
+    double velocity_knots(void) { return _velocity_knots; }
+    double velocity_kph(void)   { return _velocity_kph; }
+    double track_true(void)     { return _track_true;   } 
+    double track_mag(void)      { return _track_mag;    }
+     
+};
+
+#endif
+
--- a/example1.cpp	Sat Nov 20 21:02:06 2010 +0000
+++ b/example1.cpp	Fri Apr 15 12:23:52 2011 +0000
@@ -1,4 +1,4 @@
-#ifdef COMPILE_EXAMPLE_CODE_MODGPS
+#ifdef COMPILE_EXAMPLE1_CODE_MODGPS
 
 #include "mbed.h"
 #include "GPS.h"
--- a/example2.cpp	Sat Nov 20 21:02:06 2010 +0000
+++ b/example2.cpp	Fri Apr 15 12:23:52 2011 +0000
@@ -1,4 +1,4 @@
-#ifdef COMPILE_EXAMPLE_CODE_MODGPS
+#ifdef COMPILE_EXAMPLE2_CODE_MODGPS
 
 #include "mbed.h"
 #include "GPS.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example3.cpp	Fri Apr 15 12:23:52 2011 +0000
@@ -0,0 +1,113 @@
+#ifdef COMPILE_EXAMPLE3_CODE_MODGPS
+
+// See forum post http://mbed.org/forum/mbed/topic/2151/
+
+#include "mbed.h"
+#include "GPS.h"
+
+Serial pc(USBTX, USBRX);
+DigitalOut led1(LED1);
+
+// SET THIS.
+// Create an instance of the GPS object. You will need to
+// set p25 to whichever Serial RX pin you have connected
+// your GPS module to.
+GPS gps(NC, GPSRX);
+
+// 0.05 second flash of LED2
+DigitalOut led2(LED2);
+Timeout t2;
+void t2out(void) { led2 = 0; }
+void blip2(void) { led2 = 1; t2.attach(&t2out, 0.05); }
+
+// 0.05 second flash of LED3
+DigitalOut led3(LED3);
+Timeout t3;
+void t3out(void) { led3 = 0; }
+void blip3(void) { led3 = 1; t3.attach(&t3out, 0.05); }
+
+// 0.05 second flash of LED4
+DigitalOut led4(LED4);
+
+Timeout t4;
+void t4out(void) { led4 = 0; }
+void blip4(void) { led4 = 1; t4.attach(&t4out, 0.05); }
+
+int main() {
+    GPS_Time q1;
+    GPS_VTG  v1;
+    
+    // SET THIS.
+    // Ensure you set the baud rate to match your serial
+    // communications to your PC/Max/Linux host so you
+    // can read the messages.
+    pc.baud(PCBAUD);
+    
+    // SET THIS.
+    // Most GPS modules use 9600,8,n,1 so that's what
+    // we default to here. Ensure your GPS module matches
+    // this, otherwise set it to match.
+    gps.baud(GPSBUAD);
+    gps.format(8, GPS::None, 1);
+    
+    // OPTIONAL
+    // If you GPS has a 1 pulse per second output you can
+    // connect it to an Mbed pin. Here you specify what pin
+    // and on what "edge" teh signal is active. If your GPS
+    // module has a rising edge at the one second point then
+    // use GPS::ppsRise
+    #ifdef PPSPIN
+    gps.ppsAttach(PPSPIN, GPS::ppsFall);
+    #endif
+
+    // Sample of a callback to a function when a NMEA GGA message is recieved.
+    // For this example, we flash LED2 for 0.05 second.
+    gps.attach_gga(&blip2);
+    
+    // Sample of a callback to a function when a NMEA RMC message is recieved.
+    // For this example, we flash LED3 for 0.05 second.
+    gps.attach_rmc(&blip3);
+
+    // Sample of a callback to a function when a NMEA VTG message is recieved.
+    // For this example, we flash LED4 for 0.05 second.
+    gps.attach_vtg(&blip4);
+        
+    while(1) {
+        // Every 3 seconds, flip LED1 and print the basic GPS info.
+        wait(3);
+        led1 = 1;
+        
+        // Demonstrate how to find out the GPS location co-ords.
+        pc.printf("Method 1. Lat = %.4f ", gps.latitude());
+        pc.printf("Lon = %.4f ", gps.longitude());
+        pc.printf("Alt = %.4f ", gps.altitude());
+        
+        // Grab a snapshot of the current time.
+        gps.timeNow(&q1);
+        pc.printf("%c %02d:%02d:%02d %02d/%02d/%04d\r\n", 
+            q1.status, q1.hour, q1.minute, q1.second, q1.day, q1.month, q1.year);
+        
+        gps.vtg(&v1);
+        pc.printf("Method 1. Vector data, Speed (knots):%lf, Speed(kph):%lf, Track(true):%lf, Track(mag)%lf\r\n", 
+            v1.velocity_knots(), v1.velocity_kph(), v1.track_true(), v1.track_mag());
+            
+        // Alternative method that does the same thing.        
+        pc.printf("Method 2. Lat = %.4f ", gps.latitude());
+        pc.printf("Lon = %.4f ", gps.longitude());
+        pc.printf("Alt = %.4f ", gps.altitude());
+        
+        GPS_Time *q2 = gps.timeNow();
+        pc.printf("%c %02d:%02d:%02d %02d/%02d/%04d\r\n", 
+            q2->status, q2->hour, q2->minute, q2->second, q2->day, q2->month, q2->year);
+        delete(q2); 
+        
+        GPS_VTG *v2 = gps.vtg();
+        pc.printf("Method 2. Vector data, Speed (knots):%lf, Speed(kph):%lf, Track(true):%lf, Track(mag):%lf\r\n\n", 
+            v2->velocity_knots(), v2->velocity_kph(), v2->track_true(), v2->track_mag());
+        delete(v2); 
+         
+        led1 = 0;
+    }
+}
+
+#endif