A porting of a GPS decoding and presenting program within the mbos RTOS. It is not a definitive application but a study program to test NMEA full decoding library and a first approach to an RTOS. Many thanks to Andrew Levido for his support and his patience on teaching me the RTOS principles from the other side of the Earth. It uses NMEA library by Tim (xtimor@gmail.com) ported by Ken Todotani (http://mbed.org/users/todotani/) on public mbed library (http://mbed.org/users/todotani/programs/GPS_nmeaLib/5yo4h) also available, as original universal C library, on http://nmea.sourceforge.net

Dependencies:   mbos Watchdog TextLCD mbed ConfigFile

Task1Gps.cpp

Committer:
guiott
Date:
2012-02-03
Revision:
3:a2f9eb3b8a16
Parent:
2:8917036cbf69

File content as of revision 3:a2f9eb3b8a16:

#include "Task1Gps.h"

void GpsSerialTask(void) 
{/**
 *\brief TASK 1, wait for the event then get the input char
 */
 while(1)
 {
    os.WaitEvent(GPS_SERIAL_IN_EVT);
    GpsStringParse();
            
    Dest.lat= 4151.32496; // ***************debug
    Dest.lon= 1229.34; // *************debug

    GpsDist();
 }
}

void GpsSerialIsr(void) 
{/**
 *\brief Interrupt handler for serial Rx
         set the event for the serial task
 */
    char c = gps.getc();
    msgBuff[bufferSelect & 1][writePointer] = c;
    if (writePointer++ == BUFF_SIZE)
    {
        writePointer = 0;
    }
    if (writePointer > 200) 
    {// GPS input buffer full, start computing coordinates
        os.SetEvent(GPS_SERIAL_IN_EVT, GPS_SERIAL_TASK);
    }
}

void trace_h(const char *str, int str_size) 
{/**
 *\brief output on console what's received on GPS serial
          Callback function for NMEA parser buffer trace
 */
    if( PcMonitor==5 || PcMonitor>5)
    {
        for (int i = 0; i < str_size; i++)
        {
            pc.putc(*str++);
        }        
    }
}

void error_h(const char *str, int str_size) 
{/**
 *\brief Callback function for NMEA parser error
 */
    for (int i = 0; i < str_size; i++)
    {
        pc.putc(*str++);
    }    
}


double trunc(double v) 
{/**
 *\brief Return nearest integer vaule less than input
 *
 *\parameters double variable to get nearest ingeger
 *
 *\return double 
 */
    if(v < 0.0) 
    {
        v*= -1.0;
        v = floor(v);
        v*=-1.0;
    } else {
        v = floor(v);
    }
    return v;
}

void GpsStringParse(void)
{/**
 *\brief parse the GPS string to extract info
 */
    gps.attach(NULL);   // Suspend serial interrupt while buffer change
    size = writePointer;
    writePointer = 0;
    bufferSelect++;     // Change buffer
    gps.attach( &GpsSerialIsr );  // Resume serial interrupt
    nmea_parse(&parser, msgBuff[(bufferSelect-1)&1], size, &info);
    Coordinates(); // transform nmea coordinates in decimal degrees
}

void GpsDist(void)
{/**
 *\brief compute the distance and direction (forward and reverse) 
    from point A to point B on the ellipsoid
 */
  
    nmea_info2pos(&info, &Pos[0]);  // current position  
    nmea_info2pos(&Dest, &Pos[1]);  // destination 

    Path.Dist = nmea_distance_ellipsoid(&Pos[0], &Pos[1], &Path.Azimuth[1], &Path.Azimuth[0]);

    if(Path.Azimuth[0] > NMEA_PI) 
    {// reverse direction
        Path.Azimuth[0] = Path.Azimuth[0] - NMEA_PI; 
    }
    else
    {
        Path.Azimuth[1] = Path.Azimuth[1] + NMEA_PI; 
    }

    for(int i=0; i < 2; i++)
    {
        Path.Azimuth[i]=(nmea_radian2degree(Path.Azimuth[i]));
        if(Path.Azimuth[i] > 360)
        {
            Path.Azimuth[i] = Path.Azimuth[i] - 360;
        }
        if(Path.Azimuth[i] < 0)
        {
            Path.Azimuth[i] = Path.Azimuth[i] + 360;
        }
    }
}

void Coordinates(void)
{/**
 *\brief transform nmea coordinates in decimal degrees
 */
    degrees = trunc(info.lat / 100.0);
    minutes = info.lat - (degrees * 100.0);
    latitude = degrees + minutes / 60.0;
    degrees = trunc(info.lon / 100.0);
    minutes = info.lon - (degrees * 100.0);
    longitude = degrees + minutes / 60.0;
 }
  
void Deg2DegMinSec(double DecDeg, DegMinSec *DecSec)
{/**
 *\brief convert decimalDeg to Deg Min decimalSec
 */
    DecSec->Deg = trunc(DecDeg);
    double MinDec = (DecDeg - DecSec->Deg);
    DecSec->Min = trunc(MinDec * 60);
    DecSec->Sec = (MinDec * 3600) - (DecSec->Min * 60);
 }