@@ -46,8 +46,6 @@ void SFE_UBLOX_GPS::begin(TwoWire &wirePort)
46
46
// ie, there are some platforms that don't handle multiple starts to the wire hardware. Also, every time you start the wire
47
47
// hardware the clock speed reverts back to 100kHz regardless of previous Wire.setClocks().
48
48
// _i2cPort->begin();
49
-
50
- setI2CReadAddress (0x42 ); // By default, use 0x42
51
49
}
52
50
53
51
// Sets the internal global variable that is the I2C address we read from
@@ -142,7 +140,7 @@ void SFE_UBLOX_GPS::process(uint8_t incoming)
142
140
{
143
141
if (currentSentence == NONE || currentSentence == NMEA)
144
142
{
145
- if (incoming == 0xB5 ) // UBX binary frames start with 0xB5
143
+ if (incoming == 0xB5 ) // UBX binary frames start with 0xB5, aka μ
146
144
{
147
145
// This is the start of a binary sentence. Reset flags.
148
146
// We still don't know the response class
@@ -168,9 +166,9 @@ void SFE_UBLOX_GPS::process(uint8_t incoming)
168
166
if (currentSentence == UBX)
169
167
{
170
168
// Decide what type of response this is
171
- if (ubxFrameCounter == 0 && incoming != 0xB5 )
169
+ if (ubxFrameCounter == 0 && incoming != 0xB5 ) // ISO 'μ'
172
170
currentSentence = NONE; // Something went wrong. Reset.
173
- else if (ubxFrameCounter == 1 && incoming != 0x62 )
171
+ else if (ubxFrameCounter == 1 && incoming != 0x62 ) // ASCII 'b'
174
172
currentSentence = NONE; // Something went wrong. Reset.
175
173
else if (ubxFrameCounter == 2 ) // Class
176
174
{
@@ -199,7 +197,12 @@ void SFE_UBLOX_GPS::process(uint8_t incoming)
199
197
else
200
198
{
201
199
#ifdef DEBUG
202
- debug.println (F (" No frame class set" ));
200
+ // Print this character
201
+ debug.print (F (" No frame class set: " ));
202
+ debug.write (incoming);
203
+ debug.print (" 0x" );
204
+ debug.print (incoming, HEX);
205
+ debug.println ();
203
206
#endif
204
207
}
205
208
}
@@ -287,56 +290,63 @@ void SFE_UBLOX_GPS::processRTCM(uint8_t incoming)
287
290
288
291
// Given a character, file it away into the uxb packet structure
289
292
// Set valid = true once sentence is completely received and passes CRC
293
+ // The payload portion of the packet can be 100s of bytes but the max array
294
+ // size is roughly 64 bytes. startingSpot can be set so we only record
295
+ // interim bytes.
290
296
void SFE_UBLOX_GPS::processUBX (uint8_t incoming, ubxPacket *incomingUBX)
291
297
{
292
- if (incomingUBX->counter == 0 )
293
- {
294
- incomingUBX->cls = incoming;
295
- }
296
- else if (incomingUBX->counter == 1 )
297
- {
298
- incomingUBX->id = incoming;
299
- }
300
- else if (incomingUBX->counter == 2 ) // Len LSB
301
- {
302
- incomingUBX->len = incoming;
303
- }
304
- else if (incomingUBX->counter == 3 ) // Len MSB
305
- {
306
- incomingUBX->len |= incoming << 8 ;
307
- }
308
- else if (incomingUBX->counter == incomingUBX->len + 4 ) // ChecksumA
309
- {
310
- incomingUBX->checksumA = incoming;
311
- }
312
- else if (incomingUBX->counter == incomingUBX->len + 5 ) // ChecksumB
313
- {
314
- // Validate this sentence
298
+ if (incomingUBX->counter == 0 )
299
+ {
300
+ incomingUBX->cls = incoming;
301
+ }
302
+ else if (incomingUBX->counter == 1 )
303
+ {
304
+ incomingUBX->id = incoming;
305
+ }
306
+ else if (incomingUBX->counter == 2 ) // Len LSB
307
+ {
308
+ incomingUBX->len = incoming;
309
+ }
310
+ else if (incomingUBX->counter == 3 ) // Len MSB
311
+ {
312
+ incomingUBX->len |= incoming << 8 ;
313
+ }
314
+ else if (incomingUBX->counter == incomingUBX->len + 4 ) // ChecksumA
315
+ {
316
+ incomingUBX->checksumA = incoming;
317
+ }
318
+ else if (incomingUBX->counter == incomingUBX->len + 5 ) // ChecksumB
319
+ {
320
+ // Validate this sentence
315
321
316
- uint8_t tempA = incomingUBX->checksumA ;
317
- uint8_t tempB = incoming;
322
+ uint8_t tempA = incomingUBX->checksumA ;
323
+ uint8_t tempB = incoming;
318
324
319
- calcChecksum (incomingUBX); // Calc checksum across this message. Results stored in message.
325
+ calcChecksum (incomingUBX); // Calc checksum across this message. Results stored in message.
320
326
321
- currentSentence = NONE; // We're done! Reset the sentence to being looking for a new start char
327
+ currentSentence = NONE; // We're done! Reset the sentence to being looking for a new start char
322
328
323
- if (incomingUBX->checksumA == tempA && incomingUBX->checksumB == tempB)
324
- {
329
+ if (incomingUBX->checksumA == tempA && incomingUBX->checksumB == tempB)
330
+ {
325
331
#ifdef DEBUG
326
- debug.print (" Frame cleared: " );
327
- // printFrame(incomingUBX);
332
+ debug.print (" Frame cleared: " );
333
+ // printFrame(incomingUBX);
328
334
#endif
329
335
330
- incomingUBX->valid = true ;
331
- processUBXpacket (incomingUBX); // We've got a valid packet, now do something with it
332
- }
333
- }
334
- else // Load this byte into the payload array
335
- {
336
- // Check to see if we have room for this byte
337
- if ( (incomingUBX->counter - 4 ) < MAX_PAYLOAD_SIZE)
338
- incomingUBX->payload [incomingUBX->counter - 4 ] = incoming; // Store this byte into payload array
339
- }
336
+ incomingUBX->valid = true ;
337
+ processUBXpacket (incomingUBX); // We've got a valid packet, now do something with it
338
+ }
339
+ }
340
+ else // Load this byte into the payload array
341
+ {
342
+ // Begin recording if counter goes past startingSpot
343
+ if (incomingUBX->counter > incomingUBX->startingSpot )
344
+ {
345
+ // Check to see if we have room for this byte
346
+ if ( (incomingUBX->counter - 4 ) < MAX_PAYLOAD_SIZE)
347
+ incomingUBX->payload [incomingUBX->counter - 4 + incomingUBX->startingSpot ] = incoming; // Store this byte into payload array
348
+ }
349
+ }
340
350
341
351
incomingUBX->counter ++;
342
352
}
@@ -368,6 +378,8 @@ void SFE_UBLOX_GPS::processUBXpacket(ubxPacket *msg)
368
378
}
369
379
370
380
// Given a packet and payload, send everything including CRC bytes
381
+ // Poll for a response, returning true if command was ack'd, false if we time out waiting for response
382
+ // Setting timeout to 0 will skip checking for response - handy if you need to scan a raw response (like checking the PROTVER)
371
383
boolean SFE_UBLOX_GPS::sendCommand (ubxPacket outgoingUBX, uint16_t maxWait)
372
384
{
373
385
commandAck = false ; // We're about to send a command. Begin waiting for ack.
@@ -388,42 +400,51 @@ boolean SFE_UBLOX_GPS::sendCommand(ubxPacket outgoingUBX, uint16_t maxWait)
388
400
_i2cPort->write (outgoingUBX.id );
389
401
_i2cPort->write (outgoingUBX.len & 0xFF ); // LSB
390
402
_i2cPort->write (outgoingUBX.len >> 8 ); // MSB
391
- if (_i2cPort->endTransmission (false ) != 0 ) // Don't release bus
392
- return (false ); // Sensor did not ACK
393
-
394
- // Write payload. Limit the sends into 32 byte chunks
395
- // This code based on ublox: https://forum.u-blox.com/index.php/20528/how-to-use-i2c-to-get-the-nmea-frames
396
- uint16_t bytesToSend = outgoingUBX.len ;
403
+
404
+ // Normally we would endTransmission() here but instead, we check if there are more bytes to transmit.
397
405
398
- // "The number of data bytes must be at least 2 to properly distinguish
399
- // from the write access to set the address counter in random read accesses."
400
- uint16_t startSpot = 0 ;
401
- while (bytesToSend > 1 )
406
+ // If we are sending just a command, there are no bytes to send so skip sending anything.
407
+ if (outgoingUBX.len > 0 )
402
408
{
403
- uint8_t len = bytesToSend;
404
- if (len > I2C_BUFFER_LENGTH) len = I2C_BUFFER_LENGTH;
405
-
406
- _i2cPort->beginTransmission ((uint8_t )_gpsI2Caddress);
407
- // _i2cPort->write(outgoingUBX.payload, len); //Write a portion of the payload to the bus
408
-
409
- for (uint16_t x = 0 ; x < len ; x++)
410
- _i2cPort->write (outgoingUBX.payload [startSpot + x]); // Write a portion of the payload to the bus
411
-
412
- if (_i2cPort->endTransmission (false ) != 0 ) // Don't release bus
413
- return (false ); // Sensor did not ACK
414
-
415
- // *outgoingUBX.payload += len; //Move the pointer forward
416
- startSpot += len; // Move the pointer forward
417
- bytesToSend -= len;
409
+ if (_i2cPort->endTransmission (false ) != 0 ) // Do not release bus
410
+ return (false ); // Sensor did not ACK
411
+
412
+ // Write payload. Limit the sends into 32 byte chunks
413
+ // This code based on ublox: https://forum.u-blox.com/index.php/20528/how-to-use-i2c-to-get-the-nmea-frames
414
+ uint16_t bytesToSend = outgoingUBX.len ;
415
+
416
+ // "The number of data bytes must be at least 2 to properly distinguish
417
+ // from the write access to set the address counter in random read accesses."
418
+ uint16_t startSpot = 0 ;
419
+ while (bytesToSend > 1 )
420
+ {
421
+ uint8_t len = bytesToSend;
422
+ if (len > I2C_BUFFER_LENGTH) len = I2C_BUFFER_LENGTH;
423
+
424
+ _i2cPort->beginTransmission ((uint8_t )_gpsI2Caddress);
425
+ // _i2cPort->write(outgoingUBX.payload, len); //Write a portion of the payload to the bus
426
+
427
+ for (uint16_t x = 0 ; x < len ; x++)
428
+ _i2cPort->write (outgoingUBX.payload [startSpot + x]); // Write a portion of the payload to the bus
429
+
430
+ if (_i2cPort->endTransmission (false ) != 0 ) // Don't release bus
431
+ return (false ); // Sensor did not ACK
432
+
433
+ // *outgoingUBX.payload += len; //Move the pointer forward
434
+ startSpot += len; // Move the pointer forward
435
+ bytesToSend -= len;
436
+ }
437
+
438
+ // Write checksum
439
+ _i2cPort->beginTransmission ((uint8_t )_gpsI2Caddress);
440
+ if (bytesToSend == 1 ) _i2cPort->write (outgoingUBX.payload , 1 );
441
+ _i2cPort->write (outgoingUBX.checksumA );
442
+ _i2cPort->write (outgoingUBX.checksumB );
418
443
}
419
-
420
- // Write checksum
421
- _i2cPort->beginTransmission ((uint8_t )_gpsI2Caddress);
422
- if (bytesToSend == 1 ) _i2cPort->write (outgoingUBX.payload , 1 );
423
- _i2cPort->write (outgoingUBX.checksumA );
424
- _i2cPort->write (outgoingUBX.checksumB );
444
+
445
+ // All done transmitting bytes. Release bus.
425
446
if (_i2cPort->endTransmission () != 0 )
426
- return (false ); // Sensor did not ACK
447
+ return (false ); // Sensor did not ACK
427
448
428
449
if (maxWait > 0 )
429
450
{
@@ -499,6 +520,7 @@ boolean SFE_UBLOX_GPS::getSurveyMode(uint16_t maxWait)
499
520
packetCfg.cls = UBX_CLASS_CFG;
500
521
packetCfg.id = UBX_CFG_TMODE3;
501
522
packetCfg.len = 0 ;
523
+ packetCfg.startingSpot = 0 ;
502
524
503
525
return ( sendCommand (packetCfg, maxWait) );
504
526
}
@@ -513,7 +535,12 @@ boolean SFE_UBLOX_GPS::setSurveyMode(uint8_t mode, uint16_t observationTime, flo
513
535
packetCfg.cls = UBX_CLASS_CFG;
514
536
packetCfg.id = UBX_CFG_TMODE3;
515
537
packetCfg.len = 40 ;
538
+ packetCfg.startingSpot = 0 ;
516
539
540
+ // Clear packet payload
541
+ for (uint8_t x = 0 ; x < packetCfg.len ; x++)
542
+ packetCfg.payload [x] = 0 ;
543
+
517
544
// payloadCfg should be loaded with poll response. Now modify only the bits we care about
518
545
payloadCfg[2 ] = mode; // Set mode. Survey-In and Disabled are most common.
519
546
@@ -550,6 +577,7 @@ boolean SFE_UBLOX_GPS::getSurveyStatus(uint16_t maxWait)
550
577
packetCfg.cls = UBX_CLASS_NAV;
551
578
packetCfg.id = UBX_NAV_SVIN;
552
579
packetCfg.len = 0 ;
580
+ packetCfg.startingSpot = 0 ;
553
581
554
582
// Reset variables
555
583
svin.active = false ;
@@ -592,6 +620,7 @@ boolean SFE_UBLOX_GPS::enableRTCMmessage(uint8_t messageNumber, uint8_t portID,
592
620
packetCfg.cls = UBX_CLASS_CFG;
593
621
packetCfg.id = UBX_CFG_MSG;
594
622
packetCfg.len = 8 ;
623
+ packetCfg.startingSpot = 0 ;
595
624
596
625
// Clear packet payload
597
626
for (uint8_t x = 0 ; x < packetCfg.len ; x++)
@@ -620,6 +649,11 @@ boolean SFE_UBLOX_GPS::setRTCMport(uint8_t portID, boolean enableRTCM3, uint16_t
620
649
packetCfg.cls = UBX_CLASS_CFG;
621
650
packetCfg.id = UBX_CFG_PRT;
622
651
packetCfg.len = 20 ;
652
+ packetCfg.startingSpot = 0 ;
653
+
654
+ // Clear packet payload
655
+ for (uint8_t x = 0 ; x < packetCfg.len ; x++)
656
+ packetCfg.payload [x] = 0 ;
623
657
624
658
// msg_payload is now loaded with current bytes. Change only the ones we need to
625
659
payloadCfg[13 ] |= (1 << 5 ); // InProtocolMask LSB - Set inRtcm3
@@ -634,6 +668,8 @@ boolean SFE_UBLOX_GPS::getPortSettings(uint8_t portID, uint16_t maxWait)
634
668
packetCfg.cls = UBX_CLASS_CFG;
635
669
packetCfg.id = UBX_CFG_PRT;
636
670
packetCfg.len = 1 ;
671
+ packetCfg.startingSpot = 0 ;
672
+
637
673
payloadCfg[0 ] = portID;
638
674
639
675
return ( sendCommand (packetCfg, maxWait) );
@@ -646,6 +682,7 @@ uint32_t SFE_UBLOX_GPS::getPositionAccuracy(uint16_t maxWait)
646
682
packetCfg.cls = UBX_CLASS_NAV;
647
683
packetCfg.id = UBX_NAV_HPPOSECEF;
648
684
packetCfg.len = 0 ;
685
+ packetCfg.startingSpot = 0 ;
649
686
650
687
if (sendCommand (packetCfg, maxWait) == false )
651
688
return (0 ); // If command send fails then bail
@@ -670,8 +707,10 @@ int32_t SFE_UBLOX_GPS::getLatitude(uint16_t maxWait)
670
707
packetCfg.cls = UBX_CLASS_NAV;
671
708
packetCfg.id = UBX_NAV_POSLLH;
672
709
packetCfg.len = 0 ;
710
+ packetCfg.startingSpot = 0 ;
673
711
674
- if (sendCommand (packetCfg, maxWait) == false )
712
+ // if(sendCommand(packetCfg, maxWait) == false)
713
+ if (sendCommand (packetCfg, 1500 ) == false )
675
714
return (0 ); // If command send fails then bail
676
715
677
716
// We got a response, now parse the byte fields
@@ -692,6 +731,7 @@ int32_t SFE_UBLOX_GPS::getLongitude(uint16_t maxWait)
692
731
packetCfg.cls = UBX_CLASS_NAV;
693
732
packetCfg.id = UBX_NAV_POSLLH;
694
733
packetCfg.len = 0 ;
734
+ packetCfg.startingSpot = 0 ;
695
735
696
736
if (sendCommand (packetCfg, maxWait) == false )
697
737
return (0 ); // If command send fails then bail
@@ -715,6 +755,7 @@ int32_t SFE_UBLOX_GPS::getAltitudeEllipsoid(uint16_t maxWait)
715
755
packetCfg.cls = UBX_CLASS_NAV;
716
756
packetCfg.id = UBX_NAV_POSLLH;
717
757
packetCfg.len = 0 ;
758
+ packetCfg.startingSpot = 0 ;
718
759
719
760
if (sendCommand (packetCfg, maxWait) == false )
720
761
return (0 ); // If command send fails then bail
@@ -738,6 +779,7 @@ int32_t SFE_UBLOX_GPS::getAltitude(uint16_t maxWait)
738
779
packetCfg.cls = UBX_CLASS_NAV;
739
780
packetCfg.id = UBX_NAV_POSLLH;
740
781
packetCfg.len = 0 ;
782
+ packetCfg.startingSpot = 0 ;
741
783
742
784
if (sendCommand (packetCfg, maxWait) == false )
743
785
return (0 ); // If command send fails then bail
@@ -753,19 +795,34 @@ int32_t SFE_UBLOX_GPS::getAltitude(uint16_t maxWait)
753
795
}
754
796
755
797
// Get the current protocol version of the Ublox module we're communicating with
756
- // This is helpful when deiciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH)
798
+ // This is helpful when deciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH)
757
799
uint8_t SFE_UBLOX_GPS::getProtocolVersionHigh (uint16_t maxWait)
758
800
{
759
801
// Send packet with only CLS and ID, length of zero. This will cause the module to respond with the contents of that CLS/ID.
760
802
packetCfg.cls = UBX_CLASS_MON;
761
803
packetCfg.id = UBX_MON_VER;
762
804
packetCfg.len = 0 ;
763
805
764
- if (sendCommand (packetCfg, maxWait) == false )
765
- return (0 ); // If command send fails then bail
766
-
767
- // We got a response, now find the extension that contains 'PROTVER'
768
- // The response for this register can be quite large, many hundreds of bytes so we have to use a new, much larger array
806
+ // We will send the command repeatedly, increasing the startingSpot as we go
807
+ // Then we look at each extension field of 30 bytes
808
+ for (uint8_t extensionNumber = 0 ; extensionNumber < 1 ; extensionNumber++)
809
+ {
810
+ packetCfg.startingSpot = 40 + (30 *extensionNumber);
811
+
812
+ if (sendCommand (packetCfg, maxWait) == false )
813
+ return (0 ); // If command send fails then bail
814
+
815
+ while (1 );
816
+
817
+ // Now we need to start looking for "PROTVER" in the incoming byte stream
818
+ Serial.print (" Extension: " );
819
+ for (int location ; location < 64 ; location++)
820
+ {
821
+ Serial.write (packetCfg.payload [location]);
822
+ if (packetCfg.payload [location] == ' \0 ' ) break ;
823
+ }
824
+ Serial.println ();
825
+ }
769
826
770
827
return (0 );
771
- }
828
+ }
0 commit comments