GPS Module GTS-4E-60 library , (NMEA protocol) , can be easily imported into other GPS modules after a few minor changes

Files at this revision

API Documentation at this revision

Comitter:
igbt6
Date:
Sat Jan 03 11:54:41 2015 +0000
Commit message:
Version 0.01 of library for GPS module FIBOCOM GTS-4E-60 (NMEA protocol) released

Changed in this revision

gts4E60.cpp Show annotated file Show diff for this revision Revisions of this file
gts4E60.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r b876c6606429 gts4E60.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gts4E60.cpp	Sat Jan 03 11:54:41 2015 +0000
@@ -0,0 +1,297 @@
+
+#include "gts4E60.h"
+#include <string.h>
+
+
+
+GTS4E60::GTS4E60(PinName tx, PinName rx) : mGpsSerial(tx,rx)
+{
+    mGpsSerial.baud(GTS4E60_SERIAL_DEFAULT_BAUD );
+    init();
+}
+
+int GTS4E60::write(const char* data)
+{
+    return mGpsSerial.printf(data);
+}
+
+//private methods
+
+float GTS4E60::nmeaToDecimal(float deg_coord, char nsew)
+{
+    int degree = (int)(deg_coord/100.0f);
+    float minutes = deg_coord - degree*100;
+    float dec_deg = minutes / 60.0f;
+    float decimal = degree + dec_deg;
+    if (nsew == 'S' || nsew == 'W') {
+        decimal *= -1; // return negative value
+    }
+    return decimal;
+
+    //using trunc
+    /*
+    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);
+    minutes = longitude - (degrees * 100.0f);
+    longitude = degrees + minutes / 60.0f;
+    */
+
+}
+
+float GTS4E60::trunc(float v)
+{
+    if(v < 0.0) {
+        v*= -1.0;
+        v = floor(v);
+        v*=-1.0;
+    } else {
+        v = floor(v);
+    }
+    return v;
+}
+
+
+void GTS4E60::readData()
+{
+    while(mGpsSerial.getc() != '$');  //wait for the correct NMEA protocol message
+    for(int i=0; i<GTS4E60_NMEA_BUF_SIZE; i++) {
+        mNmeaData[i] = mGpsSerial.getc();
+        if(mNmeaData[i] == '\r') {
+            mNmeaData[i] = 0;
+            return;
+        }
+    }
+    error("overflowed message limit");
+}
+
+void GTS4E60::readData(uint8_t nmeaSentence)
+{
+    if(nmeaSentence>=NR_OF_SUPPORTED_NMEA_SENTENCES)return;
+    int counter =0;
+    while(counter<GTS4E60_NMEA_BUF_SIZE) {
+        while(mGpsSerial.getc() != '$');  //wait for the correct NMEA protocol message
+        counter++;
+        char buf[6];
+        for(int i =0; i<5; i++) {
+            buf[i]=mGpsSerial.getc();
+        }
+        buf[5]='\0';
+        if(strcmp(buf,nmeaSentencesString[nmeaSentence])==0) {
+            strcpy(mNmeaData,buf);
+        } else continue;
+        for(int i=5; i<GTS4E60_NMEA_BUF_SIZE; i++) {
+            mNmeaData[i] = mGpsSerial.getc();
+            if(mNmeaData[i] == '\r') {
+                mNmeaData[i] = 0;
+                return;
+            }
+        }
+    }
+    error("overflowed message limit");
+
+}
+
+//public methods
+
+void GTS4E60::init()
+{
+    memset(mNmeaData,0,GTS4E60_NMEA_BUF_SIZE);
+    //GPGAA
+    mFixType= 0;
+    mSatellites = 0;
+    mHdop= 0;
+    mAltitude= 0.0;
+    mUnits= ' ';
+
+    // RMC
+    mLongitude= 0.0;
+    mLatitude = 0.0;
+    NS=' ';
+    EW=' ';
+    mDataStatus= 'V';
+
+    //GSV
+    mNumberOfMsgs=0;
+    mMsgNumber=0;
+    mSatellitesInView=0;
+    wait(1);
+}
+
+
+int GTS4E60::isDataAvailable()
+{
+
+    return mGpsSerial.readable();
+}
+
+uint8_t GTS4E60::parseData(uint8_t param)
+{
+    uint8_t retVal=ERROR;
+    if(param==NULL)
+        readData();
+    else
+        readData(param);
+    // Check if there is a GPGGA snetence
+    if(sscanf(mNmeaData, "GPGGA, %2d%2d%f, %*f, %*c, %*f, %*c, %d, %d, %*f, %f", &mUtcTime.hours, &mUtcTime.minutes, &mUtcTime.seconds, &mFixType, &mSatellites, &mAltitude) >=1) {
+        retVal = GGA;
+        if(mFixType == 0) {
+            mFix = "Invalid or not available";
+            return NO_FIX_FOUND;
+        }
+        if(mSatellites==0) {
+            return NO_SATELLITES;
+        }
+    }
+    //if there is a GPGSA sentence - not used here :)
+    /*
+    else if(sscanf(mNmeaData, "GPGSA, %c, %c, %d ....", &mMode1, &mMode2, &mSatelitesUsed....) >=1){
+    retVal= GSA;
+    }
+    */
+
+    //if there is a GPRMC sentence
+    else if(sscanf(mNmeaData, "GPRMC, %2d%2d%f, %c, %f, %c, %f, %c, %f, %f, %2d%2d%2d", &mUtcTime.hours, &mUtcTime.minutes, &mUtcTime.seconds, &mDataStatus, &mLatitude, &NS, &mLongitude, &EW, &mSpeedKn, &mHeading, &mDate.day, &mDate.month, &mDate.year) >=1) {
+        retVal = RMC;
+        if(mDataStatus=='V')
+            return INVALID_STATUS;
+
+        mDate.year += 2000;
+        mLatitude= nmeaToDecimal(mLatitude,NS);
+        mLongitude= nmeaToDecimal(mLongitude,EW);
+
+        if(mFixType == 1) {
+            mFix = "Positive";
+        }
+        if(mFixType == 2) {
+            mFix = "Differential";
+        }
+        if(mHeading > 0.00 && mHeading < 45.00) {
+            mCardinal = "NNE";
+        } else if(mHeading == 45.00) {
+            mCardinal = "NE";
+        } else if(mHeading > 45.00 && mHeading < 90.00) {
+            mCardinal = "ENE";
+        } else if(mHeading == 90.00) {
+            mCardinal = "E";
+        } else if(mHeading > 90.00 && mHeading < 135.00) {
+            mCardinal = "ESE";
+        } else if(mHeading == 135.00) {
+            mCardinal = "SE";
+        } else if(mHeading > 135.00 && mHeading < 180.00) {
+            mCardinal = "SSE";
+        } else if(mHeading == 180.00) {
+            mCardinal = "S";
+        } else if(mHeading > 180.00 && mHeading < 225.00) {
+            mCardinal = "SSW";
+        } else if(mHeading == 225.00) {
+            mCardinal = "SW";
+        } else if(mHeading > 225.00 && mHeading < 270.00) {
+            mCardinal = "WSW";
+        } else if(mHeading == 270.00) {
+            mCardinal = "W";
+        } else if(mHeading > 270.00 && mHeading < 315.00) {
+            mCardinal = "WNW";
+        } else if(mHeading == 315.00) {
+            mCardinal = "NW";
+        } else if(mHeading > 315.00 && mHeading < 360.00) {
+            mCardinal = "NNW";
+        } else if(mHeading == 360.00 || mHeading == 0.00) {
+            mCardinal = "N";
+        }
+        mSpeedKm = mSpeedKn*1.852;
+
+    }
+
+    //if there is a GPGSV sentence
+    else if(sscanf(mNmeaData, "GPGSV, %d, %d, %d", &mNumberOfMsgs, &mMsgNumber , &mSatellitesInView) >=1) {
+        retVal=GSV;
+    }
+    return retVal;
+}
+
+
+
+
+
+//getter methods
+UTC_Time GTS4E60:: getTime()
+{
+    return mUtcTime;
+}
+
+Date GTS4E60:: getDate()
+{
+    return mDate;
+}
+
+float GTS4E60:: getLongitude()
+{
+    return mLongitude;
+}
+
+float GTS4E60::getLatitude()
+{
+    return mLatitude;
+}
+
+float GTS4E60::getAltitude()
+{
+    return mAltitude;
+}
+
+float GTS4E60::getSpeedKn()
+{
+    return mSpeedKn;
+}
+
+float GTS4E60::getSpeedKm()
+{
+    return mSpeedKm;
+}
+
+int   GTS4E60::getSatelites()
+{
+    return mSatellites;
+}
+
+//float GTS4E60::getCourseT() {}
+//float GTS4E60::getCourseM() {}
+
+int GTS4E60::getFixType()
+{
+    return mFixType;
+}
+
+int GTS4E60::getSatellites()
+{
+    return mSatellites;
+}
+
+int GTS4E60:: getStatus()
+{
+    return mDataStatus;
+}
+
+char GTS4E60:: getNS()
+{
+    return NS;
+}
+char GTS4E60:: getEW()
+{
+    return EW;
+}
+
+float GTS4E60:: getHeading()
+{
+    return mHeading;
+}
+
+
diff -r 000000000000 -r b876c6606429 gts4E60.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gts4E60.h	Sat Jan 03 11:54:41 2015 +0000
@@ -0,0 +1,222 @@
+/*
+  @file gts4E60.h
+
+  @brief GTS-4E-60 GPS Module (FIBOCOM) module Library
+         Easy to change for other module
+
+  @Author lukasz uszko(luszko@op.pl)
+
+  Tested on FRDM-KL46Z and FRDM-KL25Z
+
+  Copyright (c) 2014 lukasz uszko
+  Released under the MIT License (see http://mbed.org/license/mit)
+
+  Nice tutorial about degree formats and ways of computing them:
+  http://home.online.no/~sigurdhu/Deg_formats.htm
+
+  NMEA protocol reference manual:
+  https://www.sparkfun.com/datasheets/GPS/NMEA%20Reference%20Manual1.pdf
+
+  Documentation regarding GTS-4E-60 GPS Module might be found here:
+  http://www.fibocom.com/product/2-1-3-2.html
+*/
+
+//DEMO - HOW TO USE:
+/*
+---------------------------------------- DEMO: 1 version ----------------------------------------
+#include "mbed.h"
+#include "gt4E60.h"
+int main()
+{
+    GTS4E60 gps(GPS_PIN_TX,GPS_PIN_RX);
+    Serial debug(USBTX, USBRX);
+    debug.baud(115200);
+    while(1) {
+        if(gps->isDataAvailable()) {
+            if(gps->parseData()) {
+                struct UTC_Time utcTime= gps->getTime();
+                struct Date date= gps->getDate();
+                debug.printf("GPS_UTC_TIME: %02d:%02d:%02.3f\r\n",utcTime.hours, utcTime.minutes, utcTime.seconds);
+                debug.printf("GPS_DATE: %02d.%02d.%02d\r\n", date.day, date.month, date.year);
+                debug.printf("GPS_DATA: fixtype: %d, satelites: %d, altitude: %f, speed: %f, heading: %f\r\n",gps->getFixType(), gps->getSatellites(), gps->getAltitude(), gps->getSpeedKm(), gps->getHeading());
+                debug.printf("GPS_DATA: status: %c, latitude: %f, ns :%c, longitude: %f, ew: %c\r\n",gps->getStatus(), gps->getLatitude(), gps->getNS(), gps->getLongitude(), gps->getEW());
+            } else {
+                debug.printf("NO GPS FIX FOUND\r\n");
+            }
+        }
+    }
+    return 0;
+}
+
+---------------------------------------- DEMO: 2 version  error handling----------------------------------------
+#include "mbed.h"
+#include "gt4E60.h"
+int main()
+{
+    GTS4E60 gps(GPS_PIN_TX,GPS_PIN_RX);
+    Serial debug(USBTX, USBRX);
+    usbDebug.baud(115200);
+    while(1) {
+        if(gps->isDataAvailable()) {
+            uint8_t ret= gps->parseData();
+            if(ret==ERROR) {
+                usbDebug.printf("ERROR INCORRECT DATA\r\n");
+            } else if(ret==NO_FIX_FOUND) {
+                usbDebug.printf("NO GPS FIX FOUND\r\n");
+            } else if(ret==NO_SATELLITES) {
+                usbDebug.printf("NO SATELLITES FOUND\r\n");
+            } else if(ret==INVALID_STATUS) {
+                usbDebug.printf("STATUS INVALID\r\n");
+            } else {
+                struct UTC_Time utcTime= gps->getTime();
+                struct Date date= gps->getDate();
+                usbDebug.printf("GPS_UTC_TIME: %02d:%02d:%02.3f\r\n",utcTime.hours, utcTime.minutes, utcTime.seconds);
+                usbDebug.printf("GPS_DATE: %02d.%02d.%02d\r\n", date.day, date.month, date.year);
+                usbDebug.printf("GPS_DATA: fixtype: %d, satelites: %d, altitude: %f, speed: %f, heading: %f\r\n",gps->getFixType(), gps->getSatellites(), gps->getAltitude(), gps->getSpeedKm(), gps->getHeading());
+                usbDebug.printf("GPS_DATA: status: %c, latitude: %f, ns :%c, longitude: %f, ew: %c\r\n",gps->getStatus(), gps->getLatitude(), gps->getNS(), gps->getLongitude(), gps->getEW());
+            }
+        }
+    }
+    return 0;
+}
+*/
+#ifndef __GTS4E60_H__
+#define __GTS4E60_H__
+
+#include "mbed.h"
+#include "BufferedSerial.h"
+#include <string>
+
+#define GTS4E60_SERIAL_DEFAULT_BAUD       9600
+#define GTS4E60_SERIAL_TIMEOUT            10000
+#define GTS4E60_SERIAL_EOL                "\r\n"
+#define GTS4E60_NMEA_BUF_SIZE             512
+
+
+typedef enum {
+    //NMEA SENTENCES handled by the module: $GPGGA, $GPGSA, $GPRMC, $GPGSV
+    GGA = 0,
+    GSA = 1,
+    RMC = 2,
+    GSV = 3,
+    NR_OF_SUPPORTED_NMEA_SENTENCES,
+    //parseData() return paramteters
+    ERROR =5,
+    NO_FIX_FOUND= 6,
+    NO_SATELLITES= 7,
+    INVALID_STATUS= 8
+} GTS4E60_Utility;
+static const char* nmeaSentencesString[NR_OF_SUPPORTED_NMEA_SENTENCES]= {"GPGGA","GPGSA","GPRMC","GPGSV"};
+
+
+//deafault serial port on FRDM KL46Z:
+// UART2:
+// RX-PTE17
+// TX-PTE16
+
+//useful data structs
+struct UTC_Time {
+    UTC_Time() {
+        hours =0;
+        minutes =0;
+        seconds=0;
+    }
+    int hours;
+    int minutes;
+    float seconds;
+};
+
+
+struct Date {
+    Date() {
+        day =0;
+        month =0;
+        year =0;
+    }
+    int day;
+    int month;
+    int year;
+};
+
+
+
+class GTS4E60
+{
+public:
+    GTS4E60 (PinName tx, PinName rx);
+    int write(const char* data); //?
+    void init();
+    uint8_t parseData(uint8_t param =NULL);
+    int isDataAvailable();
+    inline int getDataFromRx() {
+        return mGpsSerial.getc();
+    }
+
+//getters
+    UTC_Time getTime();
+    Date getDate();
+    float getLongitude();
+    float getLatitude();
+    float getAltitude();
+    float getSpeedKn();
+    float getSpeedKm();
+    int   getSatelites();
+    float getCourseT();
+    float getCourseM();
+    int   getFixType();
+    int   getSatellites();
+    int   getStatus();
+    char  getNS();
+    char  getEW();
+    float getHeading();
+
+// navigational functions - maybe in future
+    float calcCourseTo(float, float);
+    double calcDistToKm(float, float);
+    double calcDistToM(float, float);
+
+
+private:
+
+    float trunc ( float v);
+    float nmeaToDecimal(float deg_coord, char nsew);
+    void readData();
+    void readData(uint8_t nmeaSentence);
+    Serial mGpsSerial;
+    char mNmeaData[GTS4E60_NMEA_BUF_SIZE];
+
+    // GGA - Global Positioning System Fixed Data
+    struct UTC_Time mUtcTime;         // UTC time
+    int mFixType;        // 0 = no fix;  1 = fix;  2=differential fix
+    int mSatellites;     // number of satellites used
+    float mHdop;
+    float mAltitude;
+    char mUnits;
+
+    //GSA
+    //not used here
+
+    // RMC - Recommended Minimmum Specific GNS Data
+    char mDataStatus;// RMC data status A = Data Valid; V = Data Not valid;
+    float mLatitude;
+    float mLongitude;
+    char NS, EW;
+    float mSpeedKn;      // speed in knots/hour
+    float mSpeedKm;      // speed in kilometres/hour
+    float mHeading;      // heading in degrees derived from previous & current location
+    struct Date mDate;
+
+    //GSV - GNSS Satellites in View
+    int mNumberOfMsgs;
+    int mMsgNumber;
+    int mSatellitesInView;
+
+    //useful variables
+    string mFix;
+    string mCardinal;
+
+};
+
+
+
+#endif // __GTS4E60_H__