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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GpsMax7.cpp Source File

GpsMax7.cpp

00001 /*
00002   ______                              _
00003  / _____)             _              | |
00004 ( (____  _____ ____ _| |_ _____  ____| |__
00005  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00006  _____) ) ____| | | || |_| ____( (___| | | |
00007 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00008     (C)2016 Semtech
00009 
00010 Description: uBlox MAX7 GPS
00011 
00012 Maintainer: Gregory Cristian & Gilbert Menth
00013 */
00014 
00015 #include <stdio.h>
00016 #include "mbed.h"
00017 #include "Timers.h"
00018 #include "GpsMax7.h"
00019 
00020 
00021 #define MAX_NMEA_SENTENCE_LENGTH    100
00022 #define GPS_I2C_ADDR                ( 0x84 ) // GPS IC I2C address
00023 #define NUM_SETUP_COMMANDS          7
00024 #define SETUP_COMMAND_LENGTH        16
00025 #define DATA_STREAM_ADDRESS         0xFF
00026 #define I2C_FREQUENCY               100000  //100 kHz
00027 
00028 
00029 typedef enum
00030 {
00031     GPGGA_NMEA_DOLLAR,
00032     GPGGA_NMEA_G1,
00033     GPGGA_NMEA_P,
00034     GPGGA_NMEA_G2,
00035     GPGGA_NMEA_G3,
00036     GPGGA_NMEA_A,
00037     GPGGA_NMEA_CR,
00038     GPGGA_NMEA_LF
00039 }GpggaNmeaFields_t;
00040 
00041 typedef enum
00042 {
00043     GPZDA_NMEA_DOLLAR,
00044     GPZDA_NMEA_G1,
00045     GPZDA_NMEA_P,
00046     GPZDA_NMEA_G2,
00047     GPZDA_NMEA_G3,
00048     GPZDA_NMEA_A,
00049     GPZDA_NMEA_CR,
00050     GPZDA_NMEA_LF
00051 }GpzdaNmeaFields_t;
00052 
00053 typedef enum
00054 {
00055     GPS_COMMS_INIT,
00056     GPS_COMMS_WRITE_SETUP,
00057     GPS_COMMS_WAIT_WRITE_SETUP,
00058     GPS_COMMS_READ_DATA_BUFFER,
00059     GPS_COMMS_WAIT_NEXT_READ
00060 }GpsCommsState_t;
00061 
00062 union GpsBufferSize
00063 {
00064     uint16_t NumBytes;
00065     char NumBytesBuffer[2];
00066 };
00067 
00068 
00069 //MAX7 initialisation commands
00070 const char SetupArray[NUM_SETUP_COMMANDS][SETUP_COMMAND_LENGTH] =
00071 {
00072     { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29 }, // GxGGA on to I2C
00073     { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0x62 }, // GxZDA on to I2C
00074     { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x2B }, // GxGLL not on the I2C
00075     { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40 }, // GxRMC not on the I2C
00076     { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x47 }, // GxVTG not on the I2C
00077     { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x32 }, // GxGSA not on the I2C
00078     { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x39 }  // GxGSV not on the I2C
00079 };
00080 
00081 I2C GpsI2C( I2C_SDA, I2C_SCL );
00082 
00083 GpsStruct Gps;
00084 
00085 static uint8_t  GpggaSentenceBuffer[MAX_NMEA_SENTENCE_LENGTH];
00086 static int      GpggaSentenceBufferPtr = 0;
00087 static uint8_t  GpzdaSentenceBuffer[MAX_NMEA_SENTENCE_LENGTH];
00088 static int      GpzdaSentenceBufferPtr = 0;
00089 
00090 static GpggaNmeaFields_t GpggaNmeaField;
00091 static GpzdaNmeaFields_t GpzdaNmeaField;
00092 static GpsCommsState_t   GpsCommsState;
00093 static uint32_t          GpsCommsTimer;
00094 
00095 
00096 static void GpsCheckCommandBufferForGpgga( uint8_t thisChar );
00097 static void GpsCheckCommandBufferForGpzda( uint8_t thisChar );
00098 static void ParseNmeaGpggaSentence( void );
00099 static void ParseNmeaGpzdaSentence( void );
00100 static bool Max7GpsWriteSetupOK( void );
00101 static bool Max7GpsReadDataBuffer( void );
00102 static uint8_t Max7GpsReadRegister( char thisRegAddress );
00103 
00104 
00105 void Max7GpsInit( void )
00106 {
00107     GpsI2C.frequency( I2C_FREQUENCY );
00108 }
00109 
00110 void Max7GpsHandle( void )
00111 {
00112     switch( GpsCommsState )
00113     {
00114         case GPS_COMMS_INIT:
00115             GpsCommsState = GPS_COMMS_WRITE_SETUP;
00116             break;
00117 
00118         case GPS_COMMS_WRITE_SETUP:
00119             if( Max7GpsWriteSetupOK( ) )
00120             {
00121                 GpsCommsState = GPS_COMMS_READ_DATA_BUFFER;
00122             }
00123             else
00124             {
00125                 TimersSetTimer( &GpsCommsTimer, 1 * TIM_SEC );
00126                 GpsCommsState = GPS_COMMS_WAIT_WRITE_SETUP;
00127             }
00128             break;
00129 
00130         case GPS_COMMS_WAIT_WRITE_SETUP:
00131             if( TimersTimerHasExpired( &GpsCommsTimer ) )
00132             {
00133                 GpsCommsState = GPS_COMMS_WRITE_SETUP;
00134             }
00135             break;
00136 
00137         case GPS_COMMS_READ_DATA_BUFFER:
00138             Max7GpsReadDataBuffer( );
00139             TimersSetTimer( &GpsCommsTimer, 100 * TIM_MSEC );
00140             GpsCommsState = GPS_COMMS_WAIT_NEXT_READ;
00141             break;
00142 
00143         case GPS_COMMS_WAIT_NEXT_READ:
00144             if( TimersTimerHasExpired( &GpsCommsTimer ) )
00145             {
00146                 GpsCommsState = GPS_COMMS_READ_DATA_BUFFER;
00147             }
00148             break;
00149     }
00150 }
00151 
00152 static bool Max7GpsWriteSetupOK( void )
00153 {
00154     int lineCount;
00155 
00156     for( lineCount = 0; lineCount < NUM_SETUP_COMMANDS; lineCount++ )
00157     {
00158         if( GpsI2C.write( GPS_I2C_ADDR, &SetupArray[lineCount][0], \
00159                           SETUP_COMMAND_LENGTH, 0 ) )
00160         {
00161             return false;
00162         }
00163     }
00164     return true;
00165 }
00166 
00167 static bool Max7GpsReadDataBuffer( void )
00168 {
00169     uint8_t incomingCheck;
00170     bool contFlag = true;
00171 
00172     while( contFlag )
00173     {
00174         incomingCheck = Max7GpsReadRegister( DATA_STREAM_ADDRESS );
00175         if( incomingCheck == 0xFF )
00176         {
00177             contFlag = false;
00178         }
00179         else
00180         {
00181             GpsCheckCommandBufferForGpgga( incomingCheck );
00182             GpsCheckCommandBufferForGpzda( incomingCheck );
00183         }
00184     }
00185     return false;
00186 }
00187 
00188 static uint8_t Max7GpsReadRegister( char thisRegAddress )
00189 {
00190     char thisValue;
00191     uint8_t retVal;
00192 
00193     thisValue = thisRegAddress;
00194     GpsI2C.write( GPS_I2C_ADDR, &thisValue, 1, 0 );
00195     GpsI2C.read( GPS_I2C_ADDR, &thisValue, 1, 0 );
00196     retVal = ( uint8_t )thisValue;
00197     return retVal;
00198 }
00199 
00200 static void GpsCheckCommandBufferForGpgga( uint8_t thisChar )
00201 {
00202     switch( GpggaNmeaField )
00203     {
00204         default:
00205         case GPGGA_NMEA_DOLLAR:
00206             if( thisChar == '$' )
00207             {
00208                 GpggaSentenceBufferPtr = 0;
00209                 GpggaSentenceBuffer[GpggaSentenceBufferPtr++] = thisChar;
00210                 GpggaNmeaField = GPGGA_NMEA_G1;
00211             }
00212             break;
00213 
00214         case GPGGA_NMEA_G1:
00215             if( thisChar == 'G' )
00216             {
00217                 GpggaSentenceBuffer[GpggaSentenceBufferPtr++] = thisChar;
00218                 GpggaNmeaField = GPGGA_NMEA_P;
00219             }
00220             else
00221             {
00222                 GpggaNmeaField = GPGGA_NMEA_DOLLAR;
00223             }
00224             break;
00225 
00226         case GPGGA_NMEA_P:
00227             if( thisChar == 'P' )
00228             {
00229                 GpggaSentenceBuffer[GpggaSentenceBufferPtr++] = thisChar;
00230                 GpggaNmeaField = GPGGA_NMEA_G2;
00231             }
00232             else
00233             {
00234                 GpggaNmeaField = GPGGA_NMEA_DOLLAR;
00235             }
00236             break;
00237 
00238         case GPGGA_NMEA_G2:
00239             if( thisChar == 'G' )
00240             {
00241                 GpggaSentenceBuffer[GpggaSentenceBufferPtr++] = thisChar;
00242                 GpggaNmeaField = GPGGA_NMEA_G3;
00243             }
00244             else
00245             {
00246                 GpggaNmeaField = GPGGA_NMEA_DOLLAR;
00247             }
00248             break;
00249 
00250         case GPGGA_NMEA_G3:
00251             if( thisChar == 'G' )
00252             {
00253                 GpggaSentenceBuffer[GpggaSentenceBufferPtr++] = thisChar;
00254                 GpggaNmeaField = GPGGA_NMEA_A;
00255             }
00256             else
00257             {
00258                 GpggaNmeaField = GPGGA_NMEA_DOLLAR;
00259             }
00260             break;
00261 
00262         case GPGGA_NMEA_A:
00263             if( thisChar == 'A' )
00264             {
00265                 GpggaSentenceBuffer[GpggaSentenceBufferPtr++] = thisChar;
00266                 GpggaNmeaField = GPGGA_NMEA_CR;
00267             }
00268             else
00269             {
00270                 GpggaNmeaField = GPGGA_NMEA_DOLLAR;
00271             }
00272             break;
00273 
00274         case GPGGA_NMEA_CR:
00275             GpggaSentenceBuffer[GpggaSentenceBufferPtr++] = thisChar;
00276             if( GpggaSentenceBufferPtr >= MAX_NMEA_SENTENCE_LENGTH )
00277             {
00278                 GpggaNmeaField = GPGGA_NMEA_DOLLAR;
00279             }
00280             if( thisChar == 0x0A )
00281             {
00282                 ParseNmeaGpggaSentence( );
00283             }
00284             break;
00285 
00286         case GPGGA_NMEA_LF:
00287             break;
00288     }
00289 }
00290 
00291 static void GpsCheckCommandBufferForGpzda( uint8_t thisChar )
00292 {
00293     switch( GpzdaNmeaField )
00294     {
00295         default:
00296         case GPZDA_NMEA_DOLLAR:
00297             if( thisChar == '$' )
00298             {
00299                 GpzdaSentenceBufferPtr = 0;
00300                 GpzdaSentenceBuffer[GpzdaSentenceBufferPtr++] = thisChar;
00301                 GpzdaNmeaField = GPZDA_NMEA_G1;
00302             }
00303             break;
00304 
00305         case GPZDA_NMEA_G1:
00306             if( thisChar == 'G' )
00307             {
00308                 GpzdaSentenceBuffer[GpzdaSentenceBufferPtr++] = thisChar;
00309                 GpzdaNmeaField = GPZDA_NMEA_P;
00310             }
00311             else
00312             {
00313                 GpzdaNmeaField = GPZDA_NMEA_DOLLAR;
00314             }
00315             break;
00316 
00317         case GPZDA_NMEA_P:
00318             if( thisChar == 'P' )
00319             {
00320                 GpzdaSentenceBuffer[GpzdaSentenceBufferPtr++] = thisChar;
00321                 GpzdaNmeaField = GPZDA_NMEA_G2;
00322             }
00323             else
00324             {
00325                 GpzdaNmeaField = GPZDA_NMEA_DOLLAR;
00326             }
00327             break;
00328 
00329         case GPZDA_NMEA_G2:
00330             if( thisChar == 'Z' )
00331             {
00332                 GpzdaSentenceBuffer[GpzdaSentenceBufferPtr++] = thisChar;
00333                 GpzdaNmeaField = GPZDA_NMEA_G3;
00334             }
00335             else
00336             {
00337                 GpzdaNmeaField = GPZDA_NMEA_DOLLAR;
00338             }
00339             break;
00340 
00341         case GPZDA_NMEA_G3:
00342             if( thisChar == 'D' )
00343             {
00344                 GpzdaSentenceBuffer[GpzdaSentenceBufferPtr++] = thisChar;
00345                 GpzdaNmeaField = GPZDA_NMEA_A;
00346             }
00347             else
00348             {
00349                 GpzdaNmeaField = GPZDA_NMEA_DOLLAR;
00350             }
00351             break;
00352 
00353         case GPZDA_NMEA_A:
00354             if( thisChar == 'A' )
00355             {
00356                 GpzdaSentenceBuffer[GpzdaSentenceBufferPtr++] = thisChar;
00357                 GpzdaNmeaField = GPZDA_NMEA_CR;
00358             }
00359             else
00360             {
00361                 GpzdaNmeaField = GPZDA_NMEA_DOLLAR;
00362             }
00363             break;
00364 
00365         case GPZDA_NMEA_CR:
00366             GpzdaSentenceBuffer[GpzdaSentenceBufferPtr++] = thisChar;
00367             if( GpzdaSentenceBufferPtr >= MAX_NMEA_SENTENCE_LENGTH )
00368             {
00369                 GpzdaNmeaField = GPZDA_NMEA_DOLLAR;
00370             }
00371             if( thisChar == 0x0A )
00372             {
00373                 ParseNmeaGpzdaSentence( );
00374             }
00375             break;
00376 
00377         case GPZDA_NMEA_LF:
00378             break;
00379     }
00380 }
00381 
00382 static void ParseNmeaGpggaSentence( void )
00383 {
00384     GpggaStruct thisFix;
00385     int sentencePtr = 1;
00386     int subStrPtr = 0;
00387     int commaCount = 0;
00388     uint8_t checkSum = 0;
00389     uint8_t thisChar;
00390     bool contFlag = true;
00391     char tArray[3];
00392     char compArray[3];
00393     
00394     while( contFlag ) //Get the checksum
00395     {
00396         thisChar = GpggaSentenceBuffer[sentencePtr];
00397         if( thisChar == '*' )
00398         {
00399             contFlag = false;
00400         }
00401         else
00402         {
00403             checkSum ^= thisChar;
00404         }
00405         sentencePtr++;
00406         if( sentencePtr >= MAX_NMEA_SENTENCE_LENGTH )
00407         {
00408             thisFix.Fixed = false;
00409             return;
00410         }
00411     }
00412     compArray[0] = GpggaSentenceBuffer[sentencePtr++];
00413     compArray[1] = GpggaSentenceBuffer[sentencePtr];
00414     compArray[2] = 0x00;
00415     sentencePtr = 0;
00416     sprintf( tArray, "%02X", checkSum );
00417     if( strcmp( tArray, compArray ) != 0 ) //Fails checksum
00418     {
00419         thisFix.Fixed = false;
00420         return;
00421     }
00422     while( commaCount < 6 ) //Find fix quality
00423     {
00424         if( GpggaSentenceBuffer[sentencePtr++] == ',' )
00425         {
00426             commaCount++;
00427         }
00428         if( sentencePtr >= MAX_NMEA_SENTENCE_LENGTH )
00429         {
00430             thisFix.Fixed = false;
00431             return;
00432         }
00433     }
00434     switch( GpggaSentenceBuffer[sentencePtr++] )
00435     {
00436         case '1':
00437         case '2':
00438         case '3':
00439         case '4':
00440             thisFix.Fixed = true;
00441             break;
00442 
00443         default:
00444             thisFix.Fixed = false;
00445             break;
00446     }
00447     sentencePtr++; //Skip comma after fix
00448     thisFix.NumSats[subStrPtr++] = GpggaSentenceBuffer[sentencePtr++];
00449     thisFix.NumSats[subStrPtr++] = GpggaSentenceBuffer[sentencePtr++];
00450     thisFix.NumSats[subStrPtr] = 0;
00451     if( thisFix.Fixed )
00452     {
00453         sentencePtr = 0;
00454         commaCount = 0;
00455         while( commaCount < 1 ) //Find fix time
00456         {
00457             if( GpggaSentenceBuffer[sentencePtr++] == ',' )
00458             {
00459                 commaCount++;
00460             }
00461             if( sentencePtr >= MAX_NMEA_SENTENCE_LENGTH )
00462             {
00463                 thisFix.Fixed = false;
00464                 return;
00465             }
00466         }
00467         subStrPtr = 0;
00468         // Skip over time field as this can be picked up from the other sentence
00469         sentencePtr += 6;
00470         while( commaCount < 2 ) //Find Latitude
00471         {
00472             if( GpzdaSentenceBuffer[sentencePtr++] == ',' )
00473             {
00474                 commaCount++;
00475             }
00476             if( sentencePtr >= MAX_NMEA_SENTENCE_LENGTH )
00477             {
00478                 thisFix.Fixed = false;
00479                 return;
00480             }
00481         }
00482         subStrPtr = 0;
00483         for( commaCount = 0; commaCount < 10; commaCount++ )
00484         {
00485             thisFix.Lat[subStrPtr++] = GpggaSentenceBuffer[sentencePtr++];
00486         }
00487         sentencePtr++; // Skip next comma
00488         thisFix.Lat[subStrPtr++] = ' '; //Add a space
00489         thisFix.Lat[subStrPtr++] = GpggaSentenceBuffer[sentencePtr++]; //N or S
00490         thisFix.Lat[subStrPtr] = 0x00; //String terminate
00491         
00492         while( commaCount < 4 ) //Find Longitude
00493         {
00494             if( GpggaSentenceBuffer[sentencePtr++] == ',' )
00495             {
00496                 commaCount++;
00497             }
00498             if( sentencePtr >= MAX_NMEA_SENTENCE_LENGTH )
00499             {
00500                 thisFix.Fixed = false;
00501                 return;
00502             }
00503         }
00504         sentencePtr++; // Skip this comma
00505         subStrPtr = 0;
00506         for( commaCount = 0; commaCount < 11; commaCount++ )
00507         {
00508             thisFix.Long[subStrPtr++] = GpggaSentenceBuffer[sentencePtr++];
00509         }
00510         sentencePtr++; // Skip next comma
00511         thisFix.Long[subStrPtr++] = ' '; //Add a space
00512         thisFix.Long[subStrPtr++] = GpggaSentenceBuffer[sentencePtr++]; //E or W
00513         thisFix.Long[subStrPtr] = 0x00; //String terminate
00514     }
00515     thisFix.Updated = true;
00516     Gps.Position = thisFix;
00517 }
00518 
00519 static void ParseNmeaGpzdaSentence( void )
00520 {
00521     GpzdaStruct thisTime;
00522     int sentencePtr = 1;
00523     int commaCount = 0;
00524     uint8_t checkSum = 0;
00525     uint8_t thisChar;
00526     bool contFlag = true;
00527     char tArray[3];
00528     char compArray[3];
00529     
00530     while( contFlag ) //Get the checksum
00531     {
00532         thisChar = GpzdaSentenceBuffer[sentencePtr];
00533         if( thisChar == '*' )
00534         {
00535             contFlag = false;
00536         }
00537         else
00538         {
00539             checkSum ^= thisChar;
00540         }
00541         sentencePtr++;
00542         if( sentencePtr >= MAX_NMEA_SENTENCE_LENGTH )
00543         {
00544             return;
00545         }
00546     }
00547     compArray[0] = GpzdaSentenceBuffer[sentencePtr++];
00548     compArray[1] = GpzdaSentenceBuffer[sentencePtr];
00549     compArray[2] = 0x00;
00550     sentencePtr = 0;
00551     sprintf( tArray, "%02X", checkSum );
00552     if( strcmp( tArray, compArray ) != 0 ) //Fails checksum
00553     {
00554         return;
00555     }
00556     while( commaCount < 1 ) //Start with hours (first field)
00557     {
00558         if( GpzdaSentenceBuffer[sentencePtr++] == ',' )
00559         {
00560             commaCount++;
00561         }
00562         if( sentencePtr >= MAX_NMEA_SENTENCE_LENGTH )
00563         {
00564             return;
00565         }
00566     }
00567     thisTime.Hour[0] = GpzdaSentenceBuffer[sentencePtr++];
00568     thisTime.Hour[1] = GpzdaSentenceBuffer[sentencePtr++];
00569     thisTime.Hour[2] = 0x00;
00570     
00571     thisTime.Minute[0] = GpzdaSentenceBuffer[sentencePtr++];
00572     thisTime.Minute[1] = GpzdaSentenceBuffer[sentencePtr++];
00573     thisTime.Minute[2] = 0x00;
00574     
00575     thisTime.Second[0] = GpzdaSentenceBuffer[sentencePtr++];
00576     thisTime.Second[1] = GpzdaSentenceBuffer[sentencePtr++];
00577     thisTime.Second[2] = 0x00;
00578     sentencePtr += 4;
00579 
00580     thisTime.Day[0] = GpzdaSentenceBuffer[sentencePtr++];
00581     thisTime.Day[1] = GpzdaSentenceBuffer[sentencePtr++];
00582     thisTime.Day[2] = 0x00; 
00583     sentencePtr += 1;
00584 
00585     thisTime.Month[0] = GpzdaSentenceBuffer[sentencePtr++];
00586     thisTime.Month[1] = GpzdaSentenceBuffer[sentencePtr++];
00587     thisTime.Month[2] = 0x00; 
00588     sentencePtr += 1;
00589     
00590     thisTime.Year[0] = GpzdaSentenceBuffer[sentencePtr++];
00591     thisTime.Year[1] = GpzdaSentenceBuffer[sentencePtr++];
00592     thisTime.Year[2] = GpzdaSentenceBuffer[sentencePtr++];
00593     thisTime.Year[3] = GpzdaSentenceBuffer[sentencePtr++];
00594     thisTime.Year[4] = 0x00;
00595     thisTime.Updated = true;
00596     Gps.Time = thisTime;
00597 }
00598 
00599 GpsStruct* Max7GpsgetData( void )
00600 {
00601     return &Gps ;
00602 }
00603