Solutions for the GPS experiments for LPC812 MAX

Dependencies:   mbed

main.cpp

Committer:
embeddedartists
Date:
2013-11-24
Revision:
0:a1d4ae5fb9fa

File content as of revision 0:a1d4ae5fb9fa:

#include "mbed.h"

Serial pc(USBTX, USBRX); // tx, rx
Serial uart(P0_4, P0_0);

/**
* Data structure for the GPS values
*/
typedef struct gpsData {
    uint8_t satellitesUsed[20];
    uint8_t utcTime[20];
    uint8_t altitude[20];
    uint8_t bufLatitude[20];
    uint8_t bufLongitude[20];
    int positionFixed;
    int northSouthIndicator;
    int eastWestIndicator;
    int latitude;
    int longitude;
} gpsData;

static uint8_t END_OF_MESSAGE = '\0';
static uint8_t DIVIDER = ',';

// The parsed data
static gpsData data;

/*****************************************************************************
** Function name: hasPattern
**
** Descriptions: Tests if pBuf starts with pPattern.
**
** parameters: Buffer to search and pattern to match
** Returned value: 1 if pBuf starts with pPattern, 0 otherwise
**
*****************************************************************************/
static uint8_t hasPattern(uint8_t *pBuf, uint8_t *pPattern)
{
    while(*pBuf != END_OF_MESSAGE && *pPattern != END_OF_MESSAGE) {
        if(*pBuf != *pPattern) {
            return 0;
        }
        pPattern++;
        pBuf++;
    }
    return 1;
}
/*****************************************************************************
** Function name: pointToNextValue
**
** Descriptions:    Moves past the next divider
**
** parameters: Pointer to the string to search
** Returned value: None
**
*****************************************************************************/
static void pointToNextValue(uint8_t **ppBuf)
{
    while(**ppBuf != END_OF_MESSAGE) {
        if (**ppBuf == DIVIDER) {
            (*ppBuf)++; // point to the start of next value
            break;
        }
        (*ppBuf)++;
    }
}
/*****************************************************************************
** Function name: convertCordinateToDegree
**
** Descriptions: Converts the pBuf string which is in the
** "ddmm.mmmm" format into an integer representation
**
** parameters: The buffer, the resulting integer and the
** length of the buffer
** Returned value: None
**
*****************************************************************************/
static void convertCordinateToDegree(uint8_t *pBuf, int* pDegree, int len)
{
    int index = 0;
    int sum = 0;
    int deg = 0;
    int min = 0;
    int div = 0;
    int pow = 1;
    for (index = len; index >=0; index--) {
        if (pBuf[index] == '.') {
            div = 1;
            continue;
        }
        sum += pow * (pBuf[index] & 0x0F);
        if (index > 0) {
            pow *= 10;
            div *= 10;
        }
    }

    div = pow / div;
    deg = sum / (div*100);
    min = sum - (deg*div*100);
    
    // convert to decimal minutes
    min = (min * 100) / 60;
    *pDegree = (deg*div*100) + min;
    if (div > 10000) {
        // normalize minutes to 6 decimal places
        *pDegree /= (div / 10000);
    }
}
/*****************************************************************************
** Function name: parseUTC
**
** Descriptions:    Extracts the UTC time string in hhmmss.sss,
** ignoring the .sss part and stores the result
** as a string in data.utcTime.
**
** parameters: The buffer
** Returned value: None
**
*****************************************************************************/
static void parseUTC(uint8_t **ppBuf)
{
    int index = 0;
    // parse utc hhmmss.sss
    while(**ppBuf != END_OF_MESSAGE) {
        if(**ppBuf == '.') {
            pointToNextValue(ppBuf);
            break; //reached end of the value
        }
        data.utcTime[index++] = **ppBuf;
        if(index == 2 || index == 5) {
            //Add divider
            data.utcTime[index++] = ':';
        }
        (*ppBuf)++;
    }
    data.utcTime[index] = '\0';
}
/*****************************************************************************
** Function name: parseLatitude
**
** Descriptions: Extracts the latitude information and stores
** the result as an integer in data.latitude.
**
** parameters: The buffer
** Returned value: None
**
*****************************************************************************/
static void parseLatitude(uint8_t **ppBuf)
{
    int index = 0;
    while(**ppBuf != END_OF_MESSAGE) {
        if (**ppBuf == DIVIDER) {
            (*ppBuf)++; //reached end of the value
            break;
        }
        data.bufLatitude[index++] = **ppBuf;
        (*ppBuf)++;
    }
    convertCordinateToDegree((uint8_t *) &data.bufLatitude, &data.latitude, 8);
}
/*****************************************************************************
** Function name: GPSRetreiveData
**
** Descriptions: Reads and parses the next set of GPS data.
**
** parameters:  None
** Returned value: The parsed information
**
*****************************************************************************/
const gpsData* GPSRetreiveData(void)
{
    uint8_t * pattern = (uint8_t*)"GPGGA";
    while (1) {
        uint8_t buf[100];
        uint8_t ch = 0;
        uint8_t *ptr = 0;
        int index = 0;
        
        // Retrieve the first byte
        //if (!UARTGetChar(&ch))
        //    continue;
        ch = uart.getc();
            
        // look for "$GPGGA," header
        if (ch != '$') {
            continue;
        }
        
        // Retrieve the next six bytes
        for (index=0; index<6; index++) {
            buf[index] = uart.getc();
        }
        
        //Check if its Global Positioning System fixed Data
        if (hasPattern((uint8_t*)&buf, pattern) == 0) {
            continue;
        }
        
        //Retrieve the data from the GPS module
        for (index=0; index<100; index++) {
            buf[index] = uart.getc();
            if (buf[index] == '\r') {
                buf[index] = END_OF_MESSAGE;
                break;
            }
        }
        ptr = &buf[0];
        
        //parse UTC time
        parseUTC(&ptr);
        
        //parse Latitude
        parseLatitude(&ptr);
        break;
    }
    return &data;
}
static void displayGpsData(const gpsData* pData)
{
    //Time
    printf("\n%s\n", pData->utcTime);

    //Latitude (in ddmmmmmm format, convert to dd.mmmmmm)
    printf("Latitude: %d.%06d\n", pData->latitude/1000000, pData->latitude%1000000);

    //Longitude (in ddmmmmmm format, convert to dd.mmmmmm)
    printf("Longitude: %d.%06d\n", pData->longitude/1000000, pData->longitude%1000000);

    //Number of satellites in view
    printf("#Satellites: %s\n", pData->satellitesUsed);
}

int main (void)
{
    //initialize the UART to 9600bps 8N1
    uart.baud(9600);
    //uart.format(8, Serial::None, 1);
    
    pc.printf("Waiting for GPS data...\n");
    
    //enter forever loop
    while(1)
    {
        const gpsData* pData = GPSRetreiveData();
        displayGpsData(pData);
        wait(1);
    }
}