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
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
Generated on Wed Jul 13 2022 01:03:22 by 1.7.2