Mbed library to handle GPS data reception and parsing

Dependents:   GPS_U-blox_NEO-6M_Code

Features

  • All positionning parameters are contained into a global data structure.
  • Automatic nema string parsing and data structure update.
    • GSA,GGA,VTG and RMC
  • Convert latitude and longitude to decimal value.
  • Converts latittude,longitude and altitude to ECEF coordinates.

Planed developement

  • Test library for RTOS use.
  • Complete the nema parsing decoders (couple of parameters are not parsed yet and not present in the data structure).
  • Add conversion tool to get ENU coordinates.

GPS.cpp

Committer:
chris215
Date:
2016-02-16
Revision:
5:8a73e34b3978
Parent:
4:d911d7c4e09d

File content as of revision 5:8a73e34b3978:

#include "GPS.h"
#include "GPSUtils.hpp"

GPS::GPS(PinName tx, PinName rx) : RawSerial(tx, rx)
{
    _gpsTimer.start();
    _gpsTimer.reset();
    RxQueueSize=0;
    RxQueueWriteIndex=0;
    RxQueueReadIndex=0;
    RawSerial::baud(115200);
    attach(this, &GPS::RxIrqHandler);
}

void GPS::SetBaud(int rate){
    RawSerial::baud(rate);
    }

void GPS::RxIrqHandler(void)
{
    char in;
    while(RawSerial::readable())
    {
        in = RawSerial::getc();
        if(in == START_CHAR)
        {
            insertIndex = 0;
            RxMessageBuffer.data[(insertIndex++)%RX_BUFFER_SIZE] = in;
            RxMessageBuffer.MessageIsNew = 1;
        }
        else if(in == END_CHAR)
        {
            RxMessageBuffer.data[(insertIndex++)%RX_BUFFER_SIZE] = 0;   
            //identify GPS message
            int GPSMessageType = IdentifyGPSMessage(RxMessageBuffer);
            if(GPSMessageType > 0)
            {
                if(GPSMessageType == GPS_GPGGAR)
                    memcpy(&GPSGGAMessage,&RxMessageBuffer,sizeof(message));
                if(GPSMessageType == GPS_GPGSAR)
                    memcpy(&GPSGSAMessage,&RxMessageBuffer,sizeof(message));
                if(GPSMessageType == GPS_GPVTGR)
                    memcpy(&GPSVTGMessage,&RxMessageBuffer,sizeof(message));
                if(GPSMessageType == GPS_GPRMCR)
                    memcpy(&GPSRMCMessage,&RxMessageBuffer,sizeof(message));
            }   
        }
        else
            RxMessageBuffer.data[(insertIndex++)%RX_BUFFER_SIZE] = in;
    }
}
void GPS::UpdateGPS(void)
{
    if(GPSRMCMessage.MessageIsNew > 0)
    {
        GPSRMCMessage.MessageIsNew = 0;
        DecodeMessage(GPSRMCMessage,info);
        _gpsTimer.reset();
    }
    if(GPSGGAMessage.MessageIsNew > 0)
    {
        GPSGGAMessage.MessageIsNew = 0;
        DecodeMessage(GPSGGAMessage,info);
        _gpsTimer.reset();
    }
    if(GPSVTGMessage.MessageIsNew > 0)
    {
        GPSVTGMessage.MessageIsNew = 0;
        DecodeMessage(GPSVTGMessage,info);
        _gpsTimer.reset();
    }
    if(GPSGSAMessage.MessageIsNew > 0)
    {
        GPSGSAMessage.MessageIsNew = 0;
        DecodeMessage(GPSGSAMessage,info);
        _gpsTimer.reset();
    }
    
    if(_gpsTimer.read_ms() > 5000)
    {
        info.fix = 1;
    }
}

ECEFPoint GPS::ReadPositionECEF(void)
{   
    return GeoDesicToECEF(ReadDecGeodLoc());
}
ECEFDistance GPS::DistanceBetweenTwoWP(ECEFPoint p1,ECEFPoint p2)
{
    
    return DistanceBetweenTwoECEFPoints(p1,p2);
}

geodPoint   GPS::ReadDecGeodLoc(void){
    geodPoint newLoc;
    UpdateGPS();
    newLoc.latitude = nmea_to_dec(info.latitude,info.latLoc);
    newLoc.longitude = nmea_to_dec(info.longitude,info.lonLoc);
    newLoc.altitude = info.GPSAltitude;
    return newLoc;
    }
    
geodPoint   GPS::ReadRawGeodLoc(void){
    geodPoint newLoc;
    UpdateGPS();
    newLoc.latitude = info.latitude;
    newLoc.longitude = info.longitude;
    newLoc.altitude = info.GPSAltitude;
    return newLoc;
    }
    
    
bool    GPS::FixIs3d(void){
    UpdateGPS();
    return (info.fix == 3);
    }
bool    GPS::FixIs2d(void){
    UpdateGPS();
    return (FixIs3d() || (info.fix == 2));
    }
bool    GPS::GPSFixValid(void){
        UpdateGPS();
        return (info.GPSStatus == 'A');
    }