Slightly modified version of the SerialGPS library (https://os.mbed.com/teams/components/code/SerialGPS/) to support the BufferedSerial class

Revision:
3:ebd79e3acf14
Parent:
2:e7f24389167b
Child:
4:2c76f1ec13a9
--- a/SerialGPS.cpp	Tue Feb 16 16:48:14 2021 +0100
+++ b/SerialGPS.cpp	Tue Mar 02 18:27:46 2021 +0100
@@ -28,56 +28,96 @@
     _gps_p(new BufferedSerial(tx, rx, baud)),
     _gps(*_gps_p)
 {
-    longitude   = 0.0;
-    latitude    = 0.0;        
+    this->_gps_p->set_baud(baud);
+    this->_UTCtime    = 0.0;
+    this->_lat        = 0.0;
+    this->_lon        = 0.0;
+    this->_lock       = 0;
+    this->_fix        = false;
+}
+
+SerialGPS::SerialGPS(BufferedSerial* serial)
+    :
+    _gps_p(serial),
+    _gps(*_gps_p)
+{
+    this->_UTCtime    = 0.0;
+    this->_lat        = 0.0;
+    this->_lon        = 0.0;
+    this->_lock       = 0;
+    this->_fix        = false;
 }
 
-int SerialGPS::sample() 
+bool SerialGPS::fix()
+{
+    return this->_fix;
+}
+
+float SerialGPS::get_lat()
 {
-    char ns, ew, unit;
-    int lock;
+    return this->_lat;
+}
+
+float SerialGPS::get_lon()
+{
+    return this->_lon;
+}
 
-    while(1)
-    {
+void SerialGPS::send_command(const char* cmd)
+{
+    this->_gps_p->write(cmd, sizeof(cmd));
+}
+
+void SerialGPS::read() 
+{
         getline();
 
-        // 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,%f", &time, &latitude, &ns, &longitude, &ew, &lock, &sats, &hdop, &alt, &unit, &geoid) >= 1) 
-        { 
-            if(!lock) 
+        //printf("NMEA sentence: %s\n", this->_nmea);
+
+        // GPRMC sentence: UTC time, status, lat, N/S, lon, E/W, speed, course, date
+        if(sscanf(this->_nmea, "GPRMC,%f,%c,%f,%c,%f,%c", &this->_UTCtime, &this->_status, &this->_lat, &this->_NS, &this->_lon, &this->_EW) > 0)
+        {
+            if(this->_status != 'A')
+            {
+                this->_fix = false;
+            }
+            else
             {
-                time        = 0.0;
-                longitude   = 0.0;
-                latitude    = 0.0;
-                sats        = 0;
-                hdop        = 0.0;
-                alt         = 0.0;
-                geoid       = 0.0;
-
-                return 0;
-            } 
+                set_vals();
+            }
+        }
+        // GPGGA sentence: UTC time, lat, N/S, lon, E/W, fix indicator
+        else if(sscanf(this->_nmea, "GPGGA,%f,%f,%c,%f,%c,%d", &this->_UTCtime, &this->_lat, &this->_NS, &this->_lon, &this->_EW, &this->_lock) > 0)
+        {
+            if(!this->_lock)
+            {
+                this->_fix = false;
+            }
             else 
             {
-                //GPGGA format according http://aprs.gids.nl/nmea/#gga
-                // time (float), lat (f), (N/S) (c), long (f), (E/W) (c), fix (d), sats (d),
-                // hdop (float), altitude (float), M, geoid (float), M, , ,  
-                //GPGGA,092010.000,5210.9546,N,00008.8913,E,1,07,1.3,9.7,M,47.0,M,,0000*5D
-                
-                if(ns == 'S') { latitude  *= -1.0;  }
-                if(ew == 'W') { longitude *= -1.0;  }
-
-                float degrees   = trunc(latitude / 100.0f);
-                float minutes   = latitude - (degrees * 100.0f);
-
-                latitude        = degrees + minutes / 60.0f;    
-                degrees         = trunc(longitude / 100.0f * 0.01f);
-                minutes         = longitude - (degrees * 100.0f);
-                longitude       = degrees + minutes / 60.0f;
-
-                return 1;
+                set_vals();
             }
         }
-    }
+        // GPGLL sentence: lat, N/S, lo, E/W, UTC time, status
+        else if(sscanf(this->_nmea, "GPGLL,%f,%c,%f,%c,%f,%c", &this->_lat, &this->_NS, &this->_lon, &this->_EW, &this->_UTCtime, &this->_status) > 0)
+        {
+            if(this->_status != 'A')
+            {
+                this->_fix = false;
+            }
+            else 
+            {
+                set_vals();
+            }
+        }
+        else
+        {
+            //printf("No NMEA sentence found");
+            this->_fix = false;
+        }
+
+    // Clear the NMEA buffer
+    strcpy(this->_nmea, "");
 }
 
 float SerialGPS::trunc(float v) 
@@ -95,29 +135,51 @@
     return v;
 }
 
+void SerialGPS::set_vals()
+{
+    if(this->_NS == 'S') { this->_lat *= -1.0; }
+    if(this->_EW == 'W') { this->_lon *= -1.0; }
+
+    float degrees   = trunc(_lat / 100.0f);
+    float minutes   = this->_lat *= -1.0;
+
+    this->_lat            = degrees + minutes / 60.0f;
+    degrees               = trunc(this->_lon / 100.0f * 0.01f);
+    minutes               = this->_lon - (degrees * 100.0f);
+    this->_lon            = degrees + minutes / 60.0f;
+    this->_fix            = true;
+}
+
 void SerialGPS::getline() 
 {
     char ch;
-    int idx = 0;
+    int idx = -1;
+
+    if(!this->_gps_p->readable())
+    {
+        return;
+    }
 
-    while(1)
+    // Wait for start of sentence
+    while(read_char() != '$');
+
+    // Read from serial one char at a time until max length or read terminal
+    while(idx++ <= MAX_LINELENGTH)
     {
-        _gps.read(&ch, 1);
-        if(ch != '$')
+        ch = read_char();
+
+        if(ch == '\r')
         {
-            while(idx++ < 256)
-            {
-                if(ch == '\r')
-                {
-                    msg[idx] = 0;
-                    return;
-                }
+            break;
+        }
+
+        this->_nmea[idx] = ch;
+    }
+}
 
-                msg[idx] = ch;
-            }
-        }
-    }
-    fprintf(stderr, "\r\nGPS: Overflowed message limit\r\n");
-    return;
-    //error("Overflowed message limit");
+char SerialGPS::read_char()
+{
+    char ch;
+    _gps_p->read(&ch, 1);
+    return ch;
 }
\ No newline at end of file