LRAT - UBloxGPS

Dependents:   LRAT-example-lorawan-REFACTOR-and-CLEAN-Branch

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers neo-m8m.cpp Source File

neo-m8m.cpp

00001 #include "Custom_UBloxGPS/neo-m8m.h"
00002 
00003 #define     NEOM8M_ADR_GPS          0x84
00004 #define     NEOM8M_REG_GPS_LENH     0xFD
00005 #define     NEOM8M_REG_GPS_LENL     0xFE
00006 #define     NEOM8M_REG_GPS_DATA     0xFE
00007 
00008 char NeoM8M::sleepCommand[12] {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00};
00009 char NeoM8M::wakeCommand[12] {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00};
00010 char NeoM8M::resetDefaults[21] {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03}; // UBX-CFG-CFG -- Reset to Defaults (also leave 2 bytes)
00011 
00012 // COSNTRUCTOR
00013 
00014 /**
00015     Basic, default constructor for the NeoM8M object
00016  */
00017 NeoM8M::NeoM8M()
00018 {
00019     
00020 }
00021 
00022 /**
00023     Constructor for the NeoM8M object where the I2C Object is passed in
00024  */
00025 NeoM8M::NeoM8M(I2C *_i2c)
00026 {
00027     i2c = _i2c;
00028 }
00029 
00030 // DECONSTRUCTOR
00031 
00032 /**
00033     Basic, default deconstructor for the NeoM8M object
00034  */
00035 NeoM8M::~NeoM8M()
00036 {
00037 
00038 }
00039 
00040 // PUBLIC METHODS
00041 
00042 /**
00043     Initialization method for the NeoM8M object.
00044     
00045     Reset GPS module to default status.
00046     
00047     Object takes in:
00048         -Pointer to Buffer
00049         -Pointer to Position Tracker
00050         -Pointer to MyTime storage variable
00051         -Pointer to MyLat storage variable
00052         -Pointer to MyLon storage variable
00053     And sets variables.
00054     
00055     GPS Read is performed in order to get the time
00056  */
00057 void NeoM8M::init(char *_buf, uint8_t *_pos, uint32_t *_mytime, double *_mylat, double *_mylon)
00058 {
00059     printf("In gpsInitSequence()... Resetting Defaults... \r\n");
00060     
00061     // Setup Commands    
00062     executeCommand(resetDefaults, sizeof(resetDefaults));
00063     
00064     // Setting variables necessary for future reads
00065     buf = _buf;
00066     pos = _pos;
00067     mytime = _mytime;
00068     mylat = _mylat;
00069     mylon = _mylon;
00070     
00071     read();   
00072 }
00073 
00074 /**
00075     Setter for the NeoM8M's I2C Variable
00076  */
00077 void NeoM8M::setI2C(I2C *_i2c)
00078 {
00079     i2c = _i2c;
00080 }
00081 
00082 /**
00083     GPS Read method.
00084     
00085     
00086  */
00087 int NeoM8M::read()
00088 {
00089     bool gpsDone = false;
00090     bool fixGood = false;
00091     
00092     uint8_t crcPass = 0;
00093     uint8_t crcFail = 0;
00094     
00095     uint32_t tDate = 0;
00096     uint32_t tTime = 0;
00097     
00098     char ret = 0xFF;
00099     
00100     char cmd[2];
00101     cmd[0] = 0xFF;
00102     
00103     i2c->write(NEOM8M_ADR_GPS, cmd, 1);
00104     while(!gpsDone)
00105     {
00106         while (ret == 0xFF)
00107         {
00108             i2c->read(NEOM8M_ADR_GPS, &ret, 1);
00109         }   
00110         while (ret != 0xFF)
00111         {
00112             buf[*pos++] = ret;
00113             i2c->read(NEOM8M_ADR_GPS, &ret, 1);
00114             if (ret == '\r')
00115             {
00116                 i2c->read(NEOM8M_ADR_GPS, &ret, 1);
00117                 if (ret == '\n')
00118                 {
00119                     buf[*pos] = 0x00;
00120                     // NMEA Validation
00121                     uint16_t crc = 0;
00122                     char clr = '\0';
00123                     
00124                     if (buf[0] == '$' && buf[*pos-3] == '*')
00125                     {
00126                         for (int i = 1; i < *pos-3; i++)
00127                         {
00128                             crc ^= buf[i];
00129                         }
00130                     }
00131                     
00132                     if (crc == ((buf[*pos-2] < 'A' ? buf[*pos-2] - '0' : buf[*pos-2] - '7') << 4 | (buf[*pos-1] < 'A' ? buf[*pos-1] - '0' : buf[*pos-1] - '7')))
00133                     {
00134                         clr = '2'; // 2 = Green
00135                         crcPass++;
00136                     }
00137                     
00138                     else
00139                     {
00140                         clr = '1'; // 1 = Red
00141                         crcFail++;
00142                     }
00143                     
00144                     printf("GPS: [\u001b[3%cm%02X\u001b[0m] |%s|\r\n", clr, crc, buf);
00145                     
00146                     if (clr == '2')
00147                     {
00148                         // Global Positioning System Fix Data
00149                         if(strncmp(buf, "$GNGGA", 6) == 0)
00150                         {
00151                             printf("GNGGA> ");
00152                             float fldTim, fldAlt;
00153                             double fldLat, fldLon;
00154                             char fldN_S, fldE_W;
00155                             int fldFix, fldSat;
00156                             if (sscanf(buf, "$GNGGA,%f,%lf,%c,%lf,%c,%d,%d,%*f,%f", &fldTim, &fldLat, &fldN_S, &fldLon, &fldE_W, &fldFix, &fldSat, &fldAlt) == 8)
00157                                 printf("Sec: %.2f, Lat: %.5f %c, Lon: %.5f %c, Fix: %d, Sat: %d, Alt: %.1f M\r\n", fldTim, fldLat, fldN_S, fldLon, fldE_W, fldFix, fldSat, fldAlt);
00158                             if (clr == '2')
00159                             {
00160                                 *mylat = fldLat / (fldN_S == 'S' ? -100 : 100);
00161                                 *mylon = fldLon / (fldE_W == 'W' ? -100 : 100);
00162                             }
00163                         }
00164                         
00165                         // Satellite status
00166                         if(strncmp(buf, "$GNGSA", 6) == 0)
00167                         {
00168                             char fldTyp;
00169                             int fldDim, fldSat;
00170                             sscanf(buf, "$GNGSA,%c,%d,%d", &fldTyp, &fldDim, &fldSat);
00171                         }
00172                         
00173                         // Geographic position, Latitude and Longitude
00174                         if(strncmp(buf, "$GNGLL", 6) == 0)
00175                         {
00176                             float fldTim;
00177                             double fldLat, fldLon;
00178                             char fldN_S, fldE_W;
00179                             sscanf(buf, "$GNGLL,%lf,%c,%lf,%c,%f", &fldLat, &fldN_S, &fldLon, &fldE_W, &fldTim);
00180                         }
00181                         
00182                         // Geographic position, Latitude and Longitude
00183                         if(strncmp(buf, "$GNRMC", 6) == 0)
00184                         {
00185                             printf("GNRMC> ");
00186                             float fldTim, fldSpd, fldTrk;
00187                             fldTrk = 0;
00188                             double fldLat, fldLon;
00189                             char fldSts, fldN_S, fldE_W;
00190                             uint32_t fldDat;
00191                             if (sscanf(buf, "$GNRMC,,%c", &fldSts) != 1 && 
00192                                 sscanf(buf, "$GNRMC,%f,%c,,,,,,,%d", &fldTim, &fldSts, &fldDat) != 3 && 
00193                                 sscanf(buf, "$GNRMC,%f,%c,%lf,%c,%lf,%c,%f,,%d", &fldTim, &fldSts, &fldLat, &fldN_S, &fldLon, &fldE_W, &fldSpd, &fldDat) != 8 &&
00194                                 sscanf(buf, "$GNRMC,%f,%c,%lf,%c,%lf,%c,%f,%f,%d", &fldTim, &fldSts, &fldLat, &fldN_S, &fldLon, &fldE_W, &fldSpd, &fldTrk, &fldDat) != 9)
00195                                 printf("[\u001b[33mWARN\u001b[0m] Invalid GNRMC packet detected.\r\n");
00196                             
00197                             if (fldN_S == 'N' || fldN_S == 'S' && fldE_W == 'E' || fldE_W == 'W')
00198                                 printf("Sec: %.2f, Sts: %c, Lat: %.5f %c, Lon: %.5f %c, Spd: %.3f, Dat: %06d\r\n", fldTim, fldSts, fldLat, fldN_S, fldLon, fldE_W, fldSpd, fldDat);
00199                             else
00200                                 printf("\r\n");
00201                                 
00202                             if (clr == '2')
00203                             {
00204                                 tTime = (uint32_t)fldTim;
00205                                 tDate = fldDat;
00206                                 if (fldSts == 'A')
00207                                     fixGood = true;
00208                             }
00209                         }
00210                     }
00211                     
00212                     *pos = 0;
00213                     i2c->read(NEOM8M_ADR_GPS, &ret, 1);
00214                 }
00215                 else
00216                 {
00217                     printf("[\u001b[33mWARN\u001b[0m] Expected '0A', received '%02X'.\r\n", ret);
00218                 }
00219             }
00220             
00221             //else if (pos == 82)
00222             else if (*pos == 191)
00223             {
00224                 buf[*pos] = 0x00;
00225                 printf("GPS: |%s| ...\r\n", buf);
00226                 *pos = 0;
00227                 i2c->read(NEOM8M_ADR_GPS, &ret, 1);
00228             }
00229         }
00230         
00231         buf[*pos] = 0x00;
00232         gpsDone = true;
00233     }
00234     
00235     if (*pos > 0)
00236         printf("GPS: |%s|\r\n", buf);
00237 
00238     if (crcFail)
00239         printf("[\u001b[33mWARN\u001b[0m] CRC PASS: %d FAIL: %d\r\n", crcPass, crcFail);
00240 
00241     struct tm ts;
00242     time_t t;
00243     
00244     uint8_t tDay = tDate / 10000;
00245     uint8_t tMon = (tDate - (tDay * 10000)) / 100;
00246     uint8_t tYear = (tDate - ((tDay * 10000) + (tMon * 100))) + 100;
00247     uint8_t tHour = tTime / 10000;
00248     uint8_t tMin = (tTime - (tHour * 10000)) / 100;
00249     uint8_t tSec = (tTime - ((tHour * 10000) + (tMin * 100)));
00250     
00251     ts.tm_year = tYear;
00252     ts.tm_mon = tMon - 1;
00253     ts.tm_mday = tDay;
00254     ts.tm_hour = tHour;
00255     ts.tm_min = tMin;
00256     ts.tm_sec = tSec;
00257     t = mktime(&ts);
00258 
00259     printf("GPS: %08X\t%s", t, ctime(&t));
00260     *mytime = t;
00261 
00262     if (fixGood)
00263         return 0;
00264     else
00265         return 1;
00266 }
00267 
00268 /**
00269     Places the NeoM8M GPS Module to sleep by calling inner private method
00270  */        
00271 void NeoM8M::sleep()
00272 {
00273     return executeCommand(sleepCommand, sizeof(sleepCommand));
00274 }
00275 
00276 /**
00277     Wakes the NeoM8M GPS Module up by calling inner private method
00278  */
00279 void NeoM8M::wake()
00280 {
00281     return executeCommand(wakeCommand, sizeof(wakeCommand));
00282 }
00283 
00284 /**
00285     
00286  */
00287 void NeoM8M::ubxRead()
00288 {
00289     uint8_t crcPass = 0;
00290     uint8_t crcFail = 0;
00291     
00292     *pos = 0;
00293     char ret = 0xFF;
00294     
00295     char cmd[2];
00296     cmd[0] = 0xFF;
00297     
00298     i2c->write(NEOM8M_ADR_GPS, cmd, 1);
00299     
00300     while (ret == 0xFF)
00301     {
00302         i2c->read(NEOM8M_ADR_GPS, &ret, 1);
00303     }
00304     
00305     while (ret != 0xFF)
00306     {
00307         buf[*pos++] = ret;
00308         i2c->read(NEOM8M_ADR_GPS, &ret, 1);
00309     }
00310     
00311     printf("UBX: | ");
00312     
00313     for (int i = 0; i <= *pos; i++)
00314         printf("%02X ", buf[i]);
00315     printf("|\r\n", buf);
00316     
00317 }
00318 
00319 // PRIVATE METHODS
00320 
00321 void NeoM8M::executeCommand(char *command, int length)
00322 {
00323     uint8_t crcA = 0;
00324     uint8_t crcB = 0;
00325     
00326     for(int i = 2; i <= (length - 3); i++)
00327     {
00328         crcA = crcA + command[i];
00329         crcB = crcB + crcA;
00330     }
00331     
00332     command[(length - 2)] = crcA;
00333     command[(length - 1)] = crcB;
00334     
00335     printf("UBX CRC: %02X %02X\r\n", crcA, crcB);
00336     
00337     i2c->write(NEOM8M_ADR_GPS, command, length);
00338     ubxRead();
00339     
00340     printf("Command Executed \r\n");
00341 }