nmea gps library - without any serial

Dependents:   HARP2 HARP3 20180621_FT813

Fork of GPS_parser by Tyler Weaver

NMEA GPS Serial Output parser.

Routine taken from NMEA Software Standard (NMEA 0183) http://www.winsystems.com/software/nmea.pdf

Only handles GGA and RMC Messages

Files at this revision

API Documentation at this revision

Comitter:
tylerjw
Date:
Thu Dec 13 04:57:10 2012 +0000
Parent:
6:4ed12067a314
Child:
8:59acef1c795b
Commit message:
tokenizer replaces sscanf :)

Changed in this revision

GPS_parser.cpp Show annotated file Show diff for this revision Revisions of this file
GPS_parser.h Show annotated file Show diff for this revision Revisions of this file
--- a/GPS_parser.cpp	Wed Dec 12 17:53:50 2012 +0000
+++ b/GPS_parser.cpp	Thu Dec 13 04:57:10 2012 +0000
@@ -8,7 +8,7 @@
     ns = ' ';
     ew = ' ';
     lock = 0;
-    satelites = 0;
+    satellites = 0;
     hdop = 0.0;
     msl_altitude = 0.0;
     msl_units = ' ';
@@ -21,17 +21,9 @@
     dec_longitude = 0.0;
     dec_latitude = 0.0;
 
-    gll_status = ' ';
+    altitude_ft = 0.0;
 
-    course_t = 0.0; // ground speed true
-    course_t_unit = ' ';
-    course_m = 0.0; // magnetic
-    course_m_unit = ' ';
-    speed_k_unit = ' ';
-    speed_km = 0.0; // speek km/hr
-    speed_km_unit = ' ';
-
-    altitude_ft = 0.0;
+    current = NULL;
 }
 
 float GPS_Parser::nmea_to_dec(float deg_coord, char nsew)
@@ -46,31 +38,6 @@
     return decimal;
 }
 
-int GPS_Parser::sample(char *msg)
-{
-    int line_parsed = 0;
-
-    // Check if it is a GPGGA msg (matches both locked and non-locked msg)
-    if (sscanf(msg, "$GPGGA,%f,%f,%c,%f,%c,%d,%d,%f,%f,%c", &utc_time, &nmea_latitude, &ns, &nmea_longitude, &ew, &lock, &satelites, &hdop, &msl_altitude, &msl_units) >= 1) {
-        line_parsed = GGA;
-    }
-    // Check if it is a GPRMC msg
-    else if (sscanf(msg, "$GPRMC,%f,%f,%c,%f,%c,%f,%f,%d", &utc_time, &nmea_latitude, &ns, &nmea_longitude, &ew, &speed_k, &course_d, &date) >= 1) {
-        line_parsed = RMC;
-    }
-
-    if(satelites == 0) {
-        lock = 0;
-    }
-    if (!lock) {
-        return NO_LOCK;
-    } else if (line_parsed) {
-        return line_parsed;
-    } else {
-        return NOT_PARSED;
-    }
-}
-
 
 // INTERNAL FUNCTINS ////////////////////////////////////////////////////////////
 float GPS_Parser::trunc(float v)
@@ -95,12 +62,12 @@
         return msl_altitude;
 }
 
-int GPS_Parser::get_satelites()
+int GPS_Parser::get_satellites()
 {
     if (!lock)
         return 0;
     else
-        return satelites;
+        return satellites;
 }
 
 float GPS_Parser::get_nmea_longitude()
@@ -137,20 +104,12 @@
         return dec_latitude;
 }
 
-float GPS_Parser::get_course_t()
+float GPS_Parser::get_course_d()
 {
     if (!lock)
         return 0.0;
     else
-        return course_t;
-}
-
-float GPS_Parser::get_course_m()
-{
-    if (!lock)
-        return 0.0;
-    else
-        return course_m;
+        return course_d;
 }
 
 float GPS_Parser::get_speed_k()
@@ -161,14 +120,6 @@
         return speed_k;
 }
 
-float GPS_Parser::get_speed_km()
-{
-    if (!lock)
-        return 0.0;
-    else
-        return speed_km;
-}
-
 float GPS_Parser::get_altitude_ft()
 {
     if (!lock)
@@ -242,3 +193,90 @@
     return calc_dist_to_mi(pointLat, pontLong)*1609.344;
 }
 
+char *GPS_Parser::my_token(char *source,char token)
+{
+    char *start;
+    /* The source string is real only for the first call. Subsequent calls
+                are made with the source string pointer as NULL
+                */
+    if(source != NULL) {
+        /* If the string is empty return NULL */
+        if(strlen(source) == 0)
+            return NULL;
+        strcpy(stat_string,source);
+        /* Current is our 'current' position within the string */
+        current = stat_string;
+    }
+    start = current;
+
+    while (true) {
+        /* If we're at the end of the string, return NULL */
+        if((*current == '\0') && (current == start))
+            return NULL;
+        /* If we're at the end now, but weren't when we started, we need
+        to return the pointer for the last field before the end of string
+        */
+        if(*current == '\0')
+            return start;
+        /* If we've located our specified token (comma) in the string
+                                                load its location in the copy with an end of string marker
+                                                so that it can be handled correctly by the calling program.
+                                */
+        if(*current == token) {
+            *current = '\0';
+            current++;
+            return start;
+        } else {
+            current++;
+        }
+    }
+}
+
+int GPS_Parser::parse(char *string)
+{
+    int field_count;
+    field_count = 0;
+    /* NMEA 0183 fields are delimited by commas. The my_token function returns
+    pointers to the fields.
+                */
+    /* Get the first field pointer */
+    field[0] = my_token(string,',');
+    field_count++;
+
+    while (true) {
+        /* Contiue retrieving fields until there are no more (NULL) */
+        field[field_count] = my_token(NULL,',');
+        if(field[field_count] == NULL)
+            break;
+        field_count++;
+    }
+    /* If we got at least ONE field */
+    if(field_count) {
+        /* Check the first field for the valid NMEA 0183 headers */
+        if(strcmp(field[0],"$GPGGA") == 0) {
+            /* Retrieve the values from the remaining fields */
+            utc_time = atof(field[1]);
+            nmea_latitude = atof(field[2]);
+            ns = *(field[3]);
+            nmea_longitude = atof(field[4]);
+            ew = *(field[5]);
+            lock = atoi(field[6]);
+            satellites = atoi(field[7]);
+            hdop = atof(field[8]);
+            msl_altitude = atof(field[9]);
+            msl_units = *(field[10]);
+        }
+        if(strcmp(field[0],"$GPRMC") == 0) {
+            /* Retrieve the data from the remaining fields */
+            utc_time = atof(field[1]);
+            nmea_latitude = atof(field[3]);
+            ns = *(field[4]);
+            nmea_longitude = atof(field[5]);
+            ew = *(field[6]);
+            speed_k = atof(field[7]);
+            course_d = atof(field[8]);
+            date = atol(field[9]);
+        }
+    }
+    return field_count;
+}
\ No newline at end of file
--- a/GPS_parser.h	Wed Dec 12 17:53:50 2012 +0000
+++ b/GPS_parser.h	Thu Dec 13 04:57:10 2012 +0000
@@ -13,75 +13,76 @@
 #define PI (3.141592653589793)
 
 /**  A GPS_parser interface for reading from a Globalsat EM-406 GPS Module */
-class GPS_Parser {
+class GPS_Parser
+{
 public:
 
     GPS_Parser();
-    
-    /** Sample the incoming GPS data, returning whether there is a lock
-     * 
+
+    /** Parse the incoming GPS data, returning whether there is a lock
+     *
+     * @param line the nmea string to parse, uses tokenizer vs sscanf 
      * @return 1 if there was a lock when the sample was taken (and therefore .longitude and .latitude are valid), else 0
      */
-    int sample(char *);
-    int get_lock() { return lock; }
-    int get_date() { return date; }
-    float get_time() { return utc_time; }
+    int parse(char *);
+    int get_lock() {
+        return lock;
+    }
+    int get_date() {
+        return date;
+    }
+    float get_time() {
+        return utc_time;
+    }
     float get_nmea_longitude();
     float get_nmea_latitude();
     float get_dec_longitude();
     float get_dec_latitude();
     float get_msl_altitude();
-    float get_course_t();
-    float get_course_m();
+    float get_course_d();
     float get_speed_k();
     float get_speed_km();
-    int get_satelites();
+    int get_satellites();
     float get_altitude_ft();
-    
+
     // navigational functions
     float calc_course_to(float, float);
     double calc_dist_to_mi(float, float);
     double calc_dist_to_ft(float, float);
     double calc_dist_to_km(float, float);
     double calc_dist_to_m(float, float);
-    
+
 private:
     float nmea_to_dec(float, char);
     float trunc(float v);
+    char *my_token(char *,char);
+
+    char stat_string[128]; // used in my_token
+    char *current;
     
+    char *field[50]; // used by parse nmea
+
     // calculated values
     volatile float dec_longitude;
     volatile float dec_latitude;
     volatile float altitude_ft;
-    
+
     // GGA - Global Positioning System Fixed Data
     volatile float nmea_longitude;
-    volatile float nmea_latitude;    
+    volatile float nmea_latitude;
     volatile float utc_time;
     volatile char ns, ew;
     volatile int lock;
-    volatile int satelites;
+    volatile int satellites;
     volatile float hdop;
     volatile float msl_altitude;
     volatile char msl_units;
-    
+
     // RMC - Recommended Minimmum Specific GNS Data
     volatile char rmc_status;
     volatile float speed_k;
     volatile float course_d;
     volatile int date;
-    
-    // GLL
-    volatile char gll_status;
-    
-    // VTG - Course over ground, ground speed
-    volatile float course_t; // ground speed true
-    volatile char course_t_unit;
-    volatile float course_m; // magnetic
-    volatile char course_m_unit;
-    volatile char speed_k_unit;
-    volatile float speed_km; // speek km/hr
-    volatile char speed_km_unit;
 };
 
 #endif