LRAT - UBloxGPS
Dependents: LRAT-example-lorawan-REFACTOR-and-CLEAN-Branch
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 }
Generated on Sun Jul 31 2022 05:53:11 by
1.7.2