Solutions for the GPS experiments for LPC812 MAX

Dependencies:   mbed

Revision:
0:a1d4ae5fb9fa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Nov 24 12:43:53 2013 +0000
@@ -0,0 +1,249 @@
+#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);
+    }
+}