This code holds the complete demo set for the sx1280: PingPong, PER and Ranging Outdoor demo application. >>>>> This code MUST run on the mbed library release 127 or everything will be painfully slow.

Dependencies:   mbed SX1280Lib DmTftLibrary

* This code MUST run on the mbed library release 127 or everything will be painfully slow.*
Revision:
20:626b92b70bf7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Peripherals/GpsMax7.cpp	Thu Nov 08 10:14:39 2018 +0000
@@ -0,0 +1,603 @@
+/*
+  ______                              _
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2016 Semtech
+
+Description: uBlox MAX7 GPS
+
+Maintainer: Gregory Cristian & Gilbert Menth
+*/
+
+#include <stdio.h>
+#include "mbed.h"
+#include "Timers.h"
+#include "GpsMax7.h"
+
+
+#define MAX_NMEA_SENTENCE_LENGTH    100
+#define GPS_I2C_ADDR                ( 0x84 ) // GPS IC I2C address
+#define NUM_SETUP_COMMANDS          7
+#define SETUP_COMMAND_LENGTH        16
+#define DATA_STREAM_ADDRESS         0xFF
+#define I2C_FREQUENCY               100000  //100 kHz
+
+
+typedef enum
+{
+    GPGGA_NMEA_DOLLAR,
+    GPGGA_NMEA_G1,
+    GPGGA_NMEA_P,
+    GPGGA_NMEA_G2,
+    GPGGA_NMEA_G3,
+    GPGGA_NMEA_A,
+    GPGGA_NMEA_CR,
+    GPGGA_NMEA_LF
+}GpggaNmeaFields_t;
+
+typedef enum
+{
+    GPZDA_NMEA_DOLLAR,
+    GPZDA_NMEA_G1,
+    GPZDA_NMEA_P,
+    GPZDA_NMEA_G2,
+    GPZDA_NMEA_G3,
+    GPZDA_NMEA_A,
+    GPZDA_NMEA_CR,
+    GPZDA_NMEA_LF
+}GpzdaNmeaFields_t;
+
+typedef enum
+{
+    GPS_COMMS_INIT,
+    GPS_COMMS_WRITE_SETUP,
+    GPS_COMMS_WAIT_WRITE_SETUP,
+    GPS_COMMS_READ_DATA_BUFFER,
+    GPS_COMMS_WAIT_NEXT_READ
+}GpsCommsState_t;
+
+union GpsBufferSize
+{
+    uint16_t NumBytes;
+    char NumBytesBuffer[2];
+};
+
+
+//MAX7 initialisation commands
+const char SetupArray[NUM_SETUP_COMMANDS][SETUP_COMMAND_LENGTH] =
+{
+    { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29 }, // GxGGA on to I2C
+    { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0x62 }, // GxZDA on to I2C
+    { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x2B }, // GxGLL not on the I2C
+    { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40 }, // GxRMC not on the I2C
+    { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x47 }, // GxVTG not on the I2C
+    { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x32 }, // GxGSA not on the I2C
+    { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x39 }  // GxGSV not on the I2C
+};
+
+I2C GpsI2C( I2C_SDA, I2C_SCL );
+
+GpsStruct Gps;
+
+static uint8_t  GpggaSentenceBuffer[MAX_NMEA_SENTENCE_LENGTH];
+static int      GpggaSentenceBufferPtr = 0;
+static uint8_t  GpzdaSentenceBuffer[MAX_NMEA_SENTENCE_LENGTH];
+static int      GpzdaSentenceBufferPtr = 0;
+
+static GpggaNmeaFields_t GpggaNmeaField;
+static GpzdaNmeaFields_t GpzdaNmeaField;
+static GpsCommsState_t   GpsCommsState;
+static uint32_t          GpsCommsTimer;
+
+
+static void GpsCheckCommandBufferForGpgga( uint8_t thisChar );
+static void GpsCheckCommandBufferForGpzda( uint8_t thisChar );
+static void ParseNmeaGpggaSentence( void );
+static void ParseNmeaGpzdaSentence( void );
+static bool Max7GpsWriteSetupOK( void );
+static bool Max7GpsReadDataBuffer( void );
+static uint8_t Max7GpsReadRegister( char thisRegAddress );
+
+
+void Max7GpsInit( void )
+{
+    GpsI2C.frequency( I2C_FREQUENCY );
+}
+
+void Max7GpsHandle( void )
+{
+    switch( GpsCommsState )
+    {
+        case GPS_COMMS_INIT:
+            GpsCommsState = GPS_COMMS_WRITE_SETUP;
+            break;
+
+        case GPS_COMMS_WRITE_SETUP:
+            if( Max7GpsWriteSetupOK( ) )
+            {
+                GpsCommsState = GPS_COMMS_READ_DATA_BUFFER;
+            }
+            else
+            {
+                TimersSetTimer( &GpsCommsTimer, 1 * TIM_SEC );
+                GpsCommsState = GPS_COMMS_WAIT_WRITE_SETUP;
+            }
+            break;
+
+        case GPS_COMMS_WAIT_WRITE_SETUP:
+            if( TimersTimerHasExpired( &GpsCommsTimer ) )
+            {
+                GpsCommsState = GPS_COMMS_WRITE_SETUP;
+            }
+            break;
+
+        case GPS_COMMS_READ_DATA_BUFFER:
+            Max7GpsReadDataBuffer( );
+            TimersSetTimer( &GpsCommsTimer, 100 * TIM_MSEC );
+            GpsCommsState = GPS_COMMS_WAIT_NEXT_READ;
+            break;
+
+        case GPS_COMMS_WAIT_NEXT_READ:
+            if( TimersTimerHasExpired( &GpsCommsTimer ) )
+            {
+                GpsCommsState = GPS_COMMS_READ_DATA_BUFFER;
+            }
+            break;
+    }
+}
+
+static bool Max7GpsWriteSetupOK( void )
+{
+    int lineCount;
+
+    for( lineCount = 0; lineCount < NUM_SETUP_COMMANDS; lineCount++ )
+    {
+        if( GpsI2C.write( GPS_I2C_ADDR, &SetupArray[lineCount][0], \
+                          SETUP_COMMAND_LENGTH, 0 ) )
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+static bool Max7GpsReadDataBuffer( void )
+{
+    uint8_t incomingCheck;
+    bool contFlag = true;
+
+    while( contFlag )
+    {
+        incomingCheck = Max7GpsReadRegister( DATA_STREAM_ADDRESS );
+        if( incomingCheck == 0xFF )
+        {
+            contFlag = false;
+        }
+        else
+        {
+            GpsCheckCommandBufferForGpgga( incomingCheck );
+            GpsCheckCommandBufferForGpzda( incomingCheck );
+        }
+    }
+    return false;
+}
+
+static uint8_t Max7GpsReadRegister( char thisRegAddress )
+{
+    char thisValue;
+    uint8_t retVal;
+
+    thisValue = thisRegAddress;
+    GpsI2C.write( GPS_I2C_ADDR, &thisValue, 1, 0 );
+    GpsI2C.read( GPS_I2C_ADDR, &thisValue, 1, 0 );
+    retVal = ( uint8_t )thisValue;
+    return retVal;
+}
+
+static void GpsCheckCommandBufferForGpgga( uint8_t thisChar )
+{
+    switch( GpggaNmeaField )
+    {
+        default:
+        case GPGGA_NMEA_DOLLAR:
+            if( thisChar == '$' )
+            {
+                GpggaSentenceBufferPtr = 0;
+                GpggaSentenceBuffer[GpggaSentenceBufferPtr++] = thisChar;
+                GpggaNmeaField = GPGGA_NMEA_G1;
+            }
+            break;
+
+        case GPGGA_NMEA_G1:
+            if( thisChar == 'G' )
+            {
+                GpggaSentenceBuffer[GpggaSentenceBufferPtr++] = thisChar;
+                GpggaNmeaField = GPGGA_NMEA_P;
+            }
+            else
+            {
+                GpggaNmeaField = GPGGA_NMEA_DOLLAR;
+            }
+            break;
+
+        case GPGGA_NMEA_P:
+            if( thisChar == 'P' )
+            {
+                GpggaSentenceBuffer[GpggaSentenceBufferPtr++] = thisChar;
+                GpggaNmeaField = GPGGA_NMEA_G2;
+            }
+            else
+            {
+                GpggaNmeaField = GPGGA_NMEA_DOLLAR;
+            }
+            break;
+
+        case GPGGA_NMEA_G2:
+            if( thisChar == 'G' )
+            {
+                GpggaSentenceBuffer[GpggaSentenceBufferPtr++] = thisChar;
+                GpggaNmeaField = GPGGA_NMEA_G3;
+            }
+            else
+            {
+                GpggaNmeaField = GPGGA_NMEA_DOLLAR;
+            }
+            break;
+
+        case GPGGA_NMEA_G3:
+            if( thisChar == 'G' )
+            {
+                GpggaSentenceBuffer[GpggaSentenceBufferPtr++] = thisChar;
+                GpggaNmeaField = GPGGA_NMEA_A;
+            }
+            else
+            {
+                GpggaNmeaField = GPGGA_NMEA_DOLLAR;
+            }
+            break;
+
+        case GPGGA_NMEA_A:
+            if( thisChar == 'A' )
+            {
+                GpggaSentenceBuffer[GpggaSentenceBufferPtr++] = thisChar;
+                GpggaNmeaField = GPGGA_NMEA_CR;
+            }
+            else
+            {
+                GpggaNmeaField = GPGGA_NMEA_DOLLAR;
+            }
+            break;
+
+        case GPGGA_NMEA_CR:
+            GpggaSentenceBuffer[GpggaSentenceBufferPtr++] = thisChar;
+            if( GpggaSentenceBufferPtr >= MAX_NMEA_SENTENCE_LENGTH )
+            {
+                GpggaNmeaField = GPGGA_NMEA_DOLLAR;
+            }
+            if( thisChar == 0x0A )
+            {
+                ParseNmeaGpggaSentence( );
+            }
+            break;
+
+        case GPGGA_NMEA_LF:
+            break;
+    }
+}
+
+static void GpsCheckCommandBufferForGpzda( uint8_t thisChar )
+{
+    switch( GpzdaNmeaField )
+    {
+        default:
+        case GPZDA_NMEA_DOLLAR:
+            if( thisChar == '$' )
+            {
+                GpzdaSentenceBufferPtr = 0;
+                GpzdaSentenceBuffer[GpzdaSentenceBufferPtr++] = thisChar;
+                GpzdaNmeaField = GPZDA_NMEA_G1;
+            }
+            break;
+
+        case GPZDA_NMEA_G1:
+            if( thisChar == 'G' )
+            {
+                GpzdaSentenceBuffer[GpzdaSentenceBufferPtr++] = thisChar;
+                GpzdaNmeaField = GPZDA_NMEA_P;
+            }
+            else
+            {
+                GpzdaNmeaField = GPZDA_NMEA_DOLLAR;
+            }
+            break;
+
+        case GPZDA_NMEA_P:
+            if( thisChar == 'P' )
+            {
+                GpzdaSentenceBuffer[GpzdaSentenceBufferPtr++] = thisChar;
+                GpzdaNmeaField = GPZDA_NMEA_G2;
+            }
+            else
+            {
+                GpzdaNmeaField = GPZDA_NMEA_DOLLAR;
+            }
+            break;
+
+        case GPZDA_NMEA_G2:
+            if( thisChar == 'Z' )
+            {
+                GpzdaSentenceBuffer[GpzdaSentenceBufferPtr++] = thisChar;
+                GpzdaNmeaField = GPZDA_NMEA_G3;
+            }
+            else
+            {
+                GpzdaNmeaField = GPZDA_NMEA_DOLLAR;
+            }
+            break;
+
+        case GPZDA_NMEA_G3:
+            if( thisChar == 'D' )
+            {
+                GpzdaSentenceBuffer[GpzdaSentenceBufferPtr++] = thisChar;
+                GpzdaNmeaField = GPZDA_NMEA_A;
+            }
+            else
+            {
+                GpzdaNmeaField = GPZDA_NMEA_DOLLAR;
+            }
+            break;
+
+        case GPZDA_NMEA_A:
+            if( thisChar == 'A' )
+            {
+                GpzdaSentenceBuffer[GpzdaSentenceBufferPtr++] = thisChar;
+                GpzdaNmeaField = GPZDA_NMEA_CR;
+            }
+            else
+            {
+                GpzdaNmeaField = GPZDA_NMEA_DOLLAR;
+            }
+            break;
+
+        case GPZDA_NMEA_CR:
+            GpzdaSentenceBuffer[GpzdaSentenceBufferPtr++] = thisChar;
+            if( GpzdaSentenceBufferPtr >= MAX_NMEA_SENTENCE_LENGTH )
+            {
+                GpzdaNmeaField = GPZDA_NMEA_DOLLAR;
+            }
+            if( thisChar == 0x0A )
+            {
+                ParseNmeaGpzdaSentence( );
+            }
+            break;
+
+        case GPZDA_NMEA_LF:
+            break;
+    }
+}
+
+static void ParseNmeaGpggaSentence( void )
+{
+    GpggaStruct thisFix;
+    int sentencePtr = 1;
+    int subStrPtr = 0;
+    int commaCount = 0;
+    uint8_t checkSum = 0;
+    uint8_t thisChar;
+    bool contFlag = true;
+    char tArray[3];
+    char compArray[3];
+    
+    while( contFlag ) //Get the checksum
+    {
+        thisChar = GpggaSentenceBuffer[sentencePtr];
+        if( thisChar == '*' )
+        {
+            contFlag = false;
+        }
+        else
+        {
+            checkSum ^= thisChar;
+        }
+        sentencePtr++;
+        if( sentencePtr >= MAX_NMEA_SENTENCE_LENGTH )
+        {
+            thisFix.Fixed = false;
+            return;
+        }
+    }
+    compArray[0] = GpggaSentenceBuffer[sentencePtr++];
+    compArray[1] = GpggaSentenceBuffer[sentencePtr];
+    compArray[2] = 0x00;
+    sentencePtr = 0;
+    sprintf( tArray, "%02X", checkSum );
+    if( strcmp( tArray, compArray ) != 0 ) //Fails checksum
+    {
+        thisFix.Fixed = false;
+        return;
+    }
+    while( commaCount < 6 ) //Find fix quality
+    {
+        if( GpggaSentenceBuffer[sentencePtr++] == ',' )
+        {
+            commaCount++;
+        }
+        if( sentencePtr >= MAX_NMEA_SENTENCE_LENGTH )
+        {
+            thisFix.Fixed = false;
+            return;
+        }
+    }
+    switch( GpggaSentenceBuffer[sentencePtr++] )
+    {
+        case '1':
+        case '2':
+        case '3':
+        case '4':
+            thisFix.Fixed = true;
+            break;
+
+        default:
+            thisFix.Fixed = false;
+            break;
+    }
+    sentencePtr++; //Skip comma after fix
+    thisFix.NumSats[subStrPtr++] = GpggaSentenceBuffer[sentencePtr++];
+    thisFix.NumSats[subStrPtr++] = GpggaSentenceBuffer[sentencePtr++];
+    thisFix.NumSats[subStrPtr] = 0;
+    if( thisFix.Fixed )
+    {
+        sentencePtr = 0;
+        commaCount = 0;
+        while( commaCount < 1 ) //Find fix time
+        {
+            if( GpggaSentenceBuffer[sentencePtr++] == ',' )
+            {
+                commaCount++;
+            }
+            if( sentencePtr >= MAX_NMEA_SENTENCE_LENGTH )
+            {
+                thisFix.Fixed = false;
+                return;
+            }
+        }
+        subStrPtr = 0;
+        // Skip over time field as this can be picked up from the other sentence
+        sentencePtr += 6;
+        while( commaCount < 2 ) //Find Latitude
+        {
+            if( GpzdaSentenceBuffer[sentencePtr++] == ',' )
+            {
+                commaCount++;
+            }
+            if( sentencePtr >= MAX_NMEA_SENTENCE_LENGTH )
+            {
+                thisFix.Fixed = false;
+                return;
+            }
+        }
+        subStrPtr = 0;
+        for( commaCount = 0; commaCount < 10; commaCount++ )
+        {
+            thisFix.Lat[subStrPtr++] = GpggaSentenceBuffer[sentencePtr++];
+        }
+        sentencePtr++; // Skip next comma
+        thisFix.Lat[subStrPtr++] = ' '; //Add a space
+        thisFix.Lat[subStrPtr++] = GpggaSentenceBuffer[sentencePtr++]; //N or S
+        thisFix.Lat[subStrPtr] = 0x00; //String terminate
+        
+        while( commaCount < 4 ) //Find Longitude
+        {
+            if( GpggaSentenceBuffer[sentencePtr++] == ',' )
+            {
+                commaCount++;
+            }
+            if( sentencePtr >= MAX_NMEA_SENTENCE_LENGTH )
+            {
+                thisFix.Fixed = false;
+                return;
+            }
+        }
+        sentencePtr++; // Skip this comma
+        subStrPtr = 0;
+        for( commaCount = 0; commaCount < 11; commaCount++ )
+        {
+            thisFix.Long[subStrPtr++] = GpggaSentenceBuffer[sentencePtr++];
+        }
+        sentencePtr++; // Skip next comma
+        thisFix.Long[subStrPtr++] = ' '; //Add a space
+        thisFix.Long[subStrPtr++] = GpggaSentenceBuffer[sentencePtr++]; //E or W
+        thisFix.Long[subStrPtr] = 0x00; //String terminate
+    }
+    thisFix.Updated = true;
+    Gps.Position = thisFix;
+}
+
+static void ParseNmeaGpzdaSentence( void )
+{
+    GpzdaStruct thisTime;
+    int sentencePtr = 1;
+    int commaCount = 0;
+    uint8_t checkSum = 0;
+    uint8_t thisChar;
+    bool contFlag = true;
+    char tArray[3];
+    char compArray[3];
+    
+    while( contFlag ) //Get the checksum
+    {
+        thisChar = GpzdaSentenceBuffer[sentencePtr];
+        if( thisChar == '*' )
+        {
+            contFlag = false;
+        }
+        else
+        {
+            checkSum ^= thisChar;
+        }
+        sentencePtr++;
+        if( sentencePtr >= MAX_NMEA_SENTENCE_LENGTH )
+        {
+            return;
+        }
+    }
+    compArray[0] = GpzdaSentenceBuffer[sentencePtr++];
+    compArray[1] = GpzdaSentenceBuffer[sentencePtr];
+    compArray[2] = 0x00;
+    sentencePtr = 0;
+    sprintf( tArray, "%02X", checkSum );
+    if( strcmp( tArray, compArray ) != 0 ) //Fails checksum
+    {
+        return;
+    }
+    while( commaCount < 1 ) //Start with hours (first field)
+    {
+        if( GpzdaSentenceBuffer[sentencePtr++] == ',' )
+        {
+            commaCount++;
+        }
+        if( sentencePtr >= MAX_NMEA_SENTENCE_LENGTH )
+        {
+            return;
+        }
+    }
+    thisTime.Hour[0] = GpzdaSentenceBuffer[sentencePtr++];
+    thisTime.Hour[1] = GpzdaSentenceBuffer[sentencePtr++];
+    thisTime.Hour[2] = 0x00;
+    
+    thisTime.Minute[0] = GpzdaSentenceBuffer[sentencePtr++];
+    thisTime.Minute[1] = GpzdaSentenceBuffer[sentencePtr++];
+    thisTime.Minute[2] = 0x00;
+    
+    thisTime.Second[0] = GpzdaSentenceBuffer[sentencePtr++];
+    thisTime.Second[1] = GpzdaSentenceBuffer[sentencePtr++];
+    thisTime.Second[2] = 0x00;
+    sentencePtr += 4;
+
+    thisTime.Day[0] = GpzdaSentenceBuffer[sentencePtr++];
+    thisTime.Day[1] = GpzdaSentenceBuffer[sentencePtr++];
+    thisTime.Day[2] = 0x00; 
+    sentencePtr += 1;
+
+    thisTime.Month[0] = GpzdaSentenceBuffer[sentencePtr++];
+    thisTime.Month[1] = GpzdaSentenceBuffer[sentencePtr++];
+    thisTime.Month[2] = 0x00; 
+    sentencePtr += 1;
+    
+    thisTime.Year[0] = GpzdaSentenceBuffer[sentencePtr++];
+    thisTime.Year[1] = GpzdaSentenceBuffer[sentencePtr++];
+    thisTime.Year[2] = GpzdaSentenceBuffer[sentencePtr++];
+    thisTime.Year[3] = GpzdaSentenceBuffer[sentencePtr++];
+    thisTime.Year[4] = 0x00;
+    thisTime.Updated = true;
+    Gps.Time = thisTime;
+}
+
+GpsStruct* Max7GpsgetData( void )
+{
+    return &Gps ;
+}
+