@@ -46,8 +46,6 @@ void SFE_UBLOX_GPS::begin(TwoWire &wirePort)
4646 // ie, there are some platforms that don't handle multiple starts to the wire hardware. Also, every time you start the wire
4747 // hardware the clock speed reverts back to 100kHz regardless of previous Wire.setClocks().
4848 // _i2cPort->begin();
49-
50- setI2CReadAddress (0x42 ); // By default, use 0x42
5149}
5250
5351// 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)
142140{
143141 if (currentSentence == NONE || currentSentence == NMEA)
144142 {
145- if (incoming == 0xB5 ) // UBX binary frames start with 0xB5
143+ if (incoming == 0xB5 ) // UBX binary frames start with 0xB5, aka μ
146144 {
147145 // This is the start of a binary sentence. Reset flags.
148146 // We still don't know the response class
@@ -168,9 +166,9 @@ void SFE_UBLOX_GPS::process(uint8_t incoming)
168166 if (currentSentence == UBX)
169167 {
170168 // Decide what type of response this is
171- if (ubxFrameCounter == 0 && incoming != 0xB5 )
169+ if (ubxFrameCounter == 0 && incoming != 0xB5 ) // ISO 'μ'
172170 currentSentence = NONE; // Something went wrong. Reset.
173- else if (ubxFrameCounter == 1 && incoming != 0x62 )
171+ else if (ubxFrameCounter == 1 && incoming != 0x62 ) // ASCII 'b'
174172 currentSentence = NONE; // Something went wrong. Reset.
175173 else if (ubxFrameCounter == 2 ) // Class
176174 {
@@ -199,7 +197,12 @@ void SFE_UBLOX_GPS::process(uint8_t incoming)
199197 else
200198 {
201199#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 ();
203206#endif
204207 }
205208 }
@@ -287,56 +290,63 @@ void SFE_UBLOX_GPS::processRTCM(uint8_t incoming)
287290
288291// Given a character, file it away into the uxb packet structure
289292// 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.
290296void SFE_UBLOX_GPS::processUBX (uint8_t incoming, ubxPacket *incomingUBX)
291297{
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
315321
316- uint8_t tempA = incomingUBX->checksumA ;
317- uint8_t tempB = incoming;
322+ uint8_t tempA = incomingUBX->checksumA ;
323+ uint8_t tempB = incoming;
318324
319- calcChecksum (incomingUBX); // Calc checksum across this message. Results stored in message.
325+ calcChecksum (incomingUBX); // Calc checksum across this message. Results stored in message.
320326
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
322328
323- if (incomingUBX->checksumA == tempA && incomingUBX->checksumB == tempB)
324- {
329+ if (incomingUBX->checksumA == tempA && incomingUBX->checksumB == tempB)
330+ {
325331#ifdef DEBUG
326- debug.print (" Frame cleared: " );
327- // printFrame(incomingUBX);
332+ debug.print (" Frame cleared: " );
333+ // printFrame(incomingUBX);
328334#endif
329335
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+ }
340350
341351 incomingUBX->counter ++;
342352}
@@ -368,6 +378,8 @@ void SFE_UBLOX_GPS::processUBXpacket(ubxPacket *msg)
368378}
369379
370380// 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)
371383boolean SFE_UBLOX_GPS::sendCommand (ubxPacket outgoingUBX, uint16_t maxWait)
372384{
373385 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)
388400 _i2cPort->write (outgoingUBX.id );
389401 _i2cPort->write (outgoingUBX.len & 0xFF ); // LSB
390402 _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.
397405
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 )
402408 {
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 );
418443 }
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.
425446 if (_i2cPort->endTransmission () != 0 )
426- return (false ); // Sensor did not ACK
447+ return (false ); // Sensor did not ACK
427448
428449 if (maxWait > 0 )
429450 {
@@ -499,6 +520,7 @@ boolean SFE_UBLOX_GPS::getSurveyMode(uint16_t maxWait)
499520 packetCfg.cls = UBX_CLASS_CFG;
500521 packetCfg.id = UBX_CFG_TMODE3;
501522 packetCfg.len = 0 ;
523+ packetCfg.startingSpot = 0 ;
502524
503525 return ( sendCommand (packetCfg, maxWait) );
504526}
@@ -513,7 +535,12 @@ boolean SFE_UBLOX_GPS::setSurveyMode(uint8_t mode, uint16_t observationTime, flo
513535 packetCfg.cls = UBX_CLASS_CFG;
514536 packetCfg.id = UBX_CFG_TMODE3;
515537 packetCfg.len = 40 ;
538+ packetCfg.startingSpot = 0 ;
516539
540+ // Clear packet payload
541+ for (uint8_t x = 0 ; x < packetCfg.len ; x++)
542+ packetCfg.payload [x] = 0 ;
543+
517544 // payloadCfg should be loaded with poll response. Now modify only the bits we care about
518545 payloadCfg[2 ] = mode; // Set mode. Survey-In and Disabled are most common.
519546
@@ -550,6 +577,7 @@ boolean SFE_UBLOX_GPS::getSurveyStatus(uint16_t maxWait)
550577 packetCfg.cls = UBX_CLASS_NAV;
551578 packetCfg.id = UBX_NAV_SVIN;
552579 packetCfg.len = 0 ;
580+ packetCfg.startingSpot = 0 ;
553581
554582 // Reset variables
555583 svin.active = false ;
@@ -592,6 +620,7 @@ boolean SFE_UBLOX_GPS::enableRTCMmessage(uint8_t messageNumber, uint8_t portID,
592620 packetCfg.cls = UBX_CLASS_CFG;
593621 packetCfg.id = UBX_CFG_MSG;
594622 packetCfg.len = 8 ;
623+ packetCfg.startingSpot = 0 ;
595624
596625 // Clear packet payload
597626 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
620649 packetCfg.cls = UBX_CLASS_CFG;
621650 packetCfg.id = UBX_CFG_PRT;
622651 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 ;
623657
624658 // msg_payload is now loaded with current bytes. Change only the ones we need to
625659 payloadCfg[13 ] |= (1 << 5 ); // InProtocolMask LSB - Set inRtcm3
@@ -634,6 +668,8 @@ boolean SFE_UBLOX_GPS::getPortSettings(uint8_t portID, uint16_t maxWait)
634668 packetCfg.cls = UBX_CLASS_CFG;
635669 packetCfg.id = UBX_CFG_PRT;
636670 packetCfg.len = 1 ;
671+ packetCfg.startingSpot = 0 ;
672+
637673 payloadCfg[0 ] = portID;
638674
639675 return ( sendCommand (packetCfg, maxWait) );
@@ -646,6 +682,7 @@ uint32_t SFE_UBLOX_GPS::getPositionAccuracy(uint16_t maxWait)
646682 packetCfg.cls = UBX_CLASS_NAV;
647683 packetCfg.id = UBX_NAV_HPPOSECEF;
648684 packetCfg.len = 0 ;
685+ packetCfg.startingSpot = 0 ;
649686
650687 if (sendCommand (packetCfg, maxWait) == false )
651688 return (0 ); // If command send fails then bail
@@ -670,8 +707,10 @@ int32_t SFE_UBLOX_GPS::getLatitude(uint16_t maxWait)
670707 packetCfg.cls = UBX_CLASS_NAV;
671708 packetCfg.id = UBX_NAV_POSLLH;
672709 packetCfg.len = 0 ;
710+ packetCfg.startingSpot = 0 ;
673711
674- if (sendCommand (packetCfg, maxWait) == false )
712+ // if(sendCommand(packetCfg, maxWait) == false)
713+ if (sendCommand (packetCfg, 1500 ) == false )
675714 return (0 ); // If command send fails then bail
676715
677716 // We got a response, now parse the byte fields
@@ -692,6 +731,7 @@ int32_t SFE_UBLOX_GPS::getLongitude(uint16_t maxWait)
692731 packetCfg.cls = UBX_CLASS_NAV;
693732 packetCfg.id = UBX_NAV_POSLLH;
694733 packetCfg.len = 0 ;
734+ packetCfg.startingSpot = 0 ;
695735
696736 if (sendCommand (packetCfg, maxWait) == false )
697737 return (0 ); // If command send fails then bail
@@ -715,6 +755,7 @@ int32_t SFE_UBLOX_GPS::getAltitudeEllipsoid(uint16_t maxWait)
715755 packetCfg.cls = UBX_CLASS_NAV;
716756 packetCfg.id = UBX_NAV_POSLLH;
717757 packetCfg.len = 0 ;
758+ packetCfg.startingSpot = 0 ;
718759
719760 if (sendCommand (packetCfg, maxWait) == false )
720761 return (0 ); // If command send fails then bail
@@ -738,6 +779,7 @@ int32_t SFE_UBLOX_GPS::getAltitude(uint16_t maxWait)
738779 packetCfg.cls = UBX_CLASS_NAV;
739780 packetCfg.id = UBX_NAV_POSLLH;
740781 packetCfg.len = 0 ;
782+ packetCfg.startingSpot = 0 ;
741783
742784 if (sendCommand (packetCfg, maxWait) == false )
743785 return (0 ); // If command send fails then bail
@@ -753,19 +795,34 @@ int32_t SFE_UBLOX_GPS::getAltitude(uint16_t maxWait)
753795}
754796
755797// 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)
757799uint8_t SFE_UBLOX_GPS::getProtocolVersionHigh (uint16_t maxWait)
758800{
759801 // Send packet with only CLS and ID, length of zero. This will cause the module to respond with the contents of that CLS/ID.
760802 packetCfg.cls = UBX_CLASS_MON;
761803 packetCfg.id = UBX_MON_VER;
762804 packetCfg.len = 0 ;
763805
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+ }
769826
770827 return (0 );
771- }
828+ }
0 commit comments