Add ring buffer for incoming MGA ACKs

This commit is contained in:
PaulZC
2021-11-25 12:29:29 +00:00
parent d6109694eb
commit 28e7c12b32
5 changed files with 383 additions and 30 deletions
@@ -39,8 +39,6 @@ const char tokenSuffix[] = ";";
const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal
const char getDataType[] = "datatype=eph,alm,aux;"; // Data type can be: eph,alm,aux,pos const char getDataType[] = "datatype=eph,alm,aux;"; // Data type can be: eph,alm,aux,pos
const unsigned long maxTimeBeforeHangup_ms = 10000; //If we fail to get data after 10s, then disconnect
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS #include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
@@ -58,18 +56,18 @@ void setup()
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Start I2C. Connect to the GNSS. // Start I2C. Connect to the GNSS.
// Wire.begin(); //Start I2C Wire.begin(); //Start I2C
//
// if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port
// { {
// Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing."));
// while (1); while (1);
// } }
// Serial.println(F("u-blox module connected")); Serial.println(F("u-blox module connected"));
//
// myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise
//
// myGNSS.setNavigationFrequency(1); //Set output in Hz. myGNSS.setNavigationFrequency(1); //Set output in Hz.
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Connect to WiFi. // Connect to WiFi.
@@ -86,14 +84,14 @@ void setup()
Serial.println("WiFi connected!"); Serial.println("WiFi connected!");
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Make the HTTP request // Use HTTP GET to receive the AssistNow_Online data
const int URL_BUFFER_SIZE = 512; const int URL_BUFFER_SIZE = 256;
char theURL[URL_BUFFER_SIZE]; char theURL[URL_BUFFER_SIZE]; // This will contain the HTTP URL
int payloadSize; int payloadSize = 0; // This will be updated with the length of the data we get from the server
String payload; String payload; // This will store the data we get from the server
// Assemble the URL // Assemble the URL. Note the slash after assistNowServer
snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s", snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s",
assistNowServer, assistNowServer,
getQuery, getQuery,
@@ -103,14 +101,14 @@ void setup()
getGNSS, getGNSS,
getDataType); getDataType);
Serial.print("URL is: "); Serial.print("HTTP URL is: ");
Serial.println(theURL); Serial.println(theURL);
HTTPClient http; HTTPClient http;
http.begin(theURL); http.begin(theURL);
int httpCode = http.GET(); int httpCode = http.GET(); // HTTP GET
// httpCode will be negative on error // httpCode will be negative on error
if(httpCode > 0) if(httpCode > 0)
@@ -118,7 +116,7 @@ void setup()
// HTTP header has been sent and Server response header has been handled // HTTP header has been sent and Server response header has been handled
Serial.printf("[HTTP] GET... code: %d\n", httpCode); Serial.printf("[HTTP] GET... code: %d\n", httpCode);
// file found at server // If the GET was successful, read the data
if(httpCode == HTTP_CODE_OK) // Code 200 if(httpCode == HTTP_CODE_OK) // Code 200
{ {
payloadSize = http.getSize(); payloadSize = http.getSize();
@@ -127,6 +125,7 @@ void setup()
payload = http.getString(); // Get the payload payload = http.getString(); // Get the payload
// Pretty-print the payload as HEX // Pretty-print the payload as HEX
/*
int i; int i;
for(i = 0; i < payloadSize; i++) for(i = 0; i < payloadSize; i++)
{ {
@@ -139,6 +138,7 @@ void setup()
} }
if ((i % 16) != 15) if ((i % 16) != 15)
Serial.println(); Serial.println();
*/
} }
} }
else else
@@ -151,13 +151,46 @@ void setup()
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Push the AssistNow data to the module // Push the AssistNow data to the module
if (payloadSize > 0)
{
// Enable the 'major' debug messages on Serial so we can see what AssistNow data is being sent
myGNSS.enableDebugging(Serial, true);
// Push all the AssistNow data - without checking for UBX-MGA-ACK messages
myGNSS.pushAssistNowData((uint8_t *)&payload, (size_t)payloadSize);
}
} }
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void loop() void loop()
{ {
// Nothing to do here long latitude = myGNSS.getLatitude();
Serial.print(F("Lat: "));
Serial.print(latitude);
long longitude = myGNSS.getLongitude();
Serial.print(F(" Long: "));
Serial.print(longitude);
Serial.print(F(" (degrees * 10^-7)"));
long altitude = myGNSS.getAltitude();
Serial.print(F(" Alt: "));
Serial.print(altitude);
Serial.print(F(" (mm)"));
byte SIV = myGNSS.getSIV();
Serial.print(F(" SIV: "));
Serial.print(SIV);
byte fixType = myGNSS.getFixType();
Serial.print(F(" Fix: "));
if(fixType == 0) Serial.print(F("No fix"));
else if(fixType == 1) Serial.print(F("Dead reckoning"));
else if(fixType == 2) Serial.print(F("2D"));
else if(fixType == 3) Serial.print(F("3D"));
else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning"));
else if(fixType == 5) Serial.print(F("Time only"));
Serial.println();
} }
+25 -4
View File
@@ -90,6 +90,8 @@ checkCallbacks KEYWORD2
pushRawData KEYWORD2 pushRawData KEYWORD2
pushAssistNowData KEYWORD2
setFileBufferSize KEYWORD2 setFileBufferSize KEYWORD2
getFileBufferSize KEYWORD2 getFileBufferSize KEYWORD2
extractFileBufferData KEYWORD2 extractFileBufferData KEYWORD2
@@ -153,6 +155,18 @@ getDynamicModel KEYWORD2
resetOdometer KEYWORD2 resetOdometer KEYWORD2
enableGNSS KEYWORD2 enableGNSS KEYWORD2
isGNSSenabled KEYWORD2
resetIMUalignment KEYWORD2
getESFAutoAlignment KEYWORD2
setESFAutoAlignment KEYWORD2
getTimePulseParameters KEYWORD2
setTimePulseParameters KEYWORD2
getAckAiding KEYWORD2
setAckAiding KEYWORD2
createKey KEYWORD2 createKey KEYWORD2
getVal KEYWORD2 getVal KEYWORD2
@@ -367,9 +381,6 @@ initPacketUBXESFRAW KEYWORD2
flushESFRAW KEYWORD2 flushESFRAW KEYWORD2
logESFRAW KEYWORD2 logESFRAW KEYWORD2
getESFAutoAlignment KEYWORD2
setESFAutoAlignment KEYWORD2
getHNRAtt KEYWORD2 getHNRAtt KEYWORD2
getHNRATT KEYWORD2 getHNRATT KEYWORD2
setAutoHNRATT KEYWORD2 setAutoHNRATT KEYWORD2
@@ -675,4 +686,14 @@ SFE_UBLOX_GNSS_ID_IMES LITERAL1
SFE_UBLOX_GNSS_ID_QZSS LITERAL1 SFE_UBLOX_GNSS_ID_QZSS LITERAL1
SFE_UBLOX_GNSS_ID_GLONASS LITERAL1 SFE_UBLOX_GNSS_ID_GLONASS LITERAL1
DAYS_SINCE_MONTH LITERAL1 SFE_UBLOX_MGA_ASSIST_ACK_NO LITERAL1
SFE_UBLOX_MGA_ASSIST_ACK_YES LITERAL1
SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE LITERAL1
SFE_UBLOX_MGA_ACK_INFOCODE_ACCEPTED LITERAL1
SFE_UBLOX_MGA_ACK_INFOCODE_NO_TIME LITERAL1
SFE_UBLOX_MGA_ACK_INFOCODE_NOT_SUPPORTED LITERAL1
SFE_UBLOX_MGA_ACK_INFOCODE_SIZE_MISMATCH LITERAL1
SFE_UBLOX_MGA_ACK_INFOCODE_NOT_STORED LITERAL1
SFE_UBLOX_MGA_ACK_INFOCODE_NOT_READY LITERAL1
SFE_UBLOX_MGA_ACK_INFOCODE_TYPE_UNKNOWN LITERAL1
@@ -2715,6 +2715,44 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg)
} }
} }
break; break;
case UBX_CLASS_MGA:
if (msg->id == UBX_MGA_ACK_DATA0 && msg->len == UBX_MGA_ACK_DATA0_LEN)
{
//Parse various byte fields into storage - but only if we have memory allocated for it
if (packetUBXMGAACK != NULL)
{
// Calculate how many ACKs are already stored in the ring buffer
uint8_t ackBufferContains;
if (packetUBXMGAACK->head >= packetUBXMGAACK->tail) // Check if wrap-around has occurred
{
// Wrap-around has not occurred so do a simple subtraction
ackBufferContains = packetUBXMGAACK->head - packetUBXMGAACK->tail;
}
else
{
// Wrap-around has occurred so do a simple subtraction but add in the buffer length (UBX_MGA_ACK_RINGBUFFER_LEN)
ackBufferContains = ((uint8_t)(((uint16_t)packetUBXMGAACK->head + (uint16_t)UBX_MGA_ACK_DATA0_RINGBUFFER_LEN) - (uint16_t)packetUBXMGAACK->tail));
}
// Have we got space to store this ACK?
if (ackBufferContains < (UBX_MGA_ACK_DATA0_RINGBUFFER_LEN - 1))
{
// Yes, we have, so store it
packetUBXMGAACK->data[packetUBXMGAACK->head].type = extractByte(msg, 0);
packetUBXMGAACK->data[packetUBXMGAACK->head].version = extractByte(msg, 1);
packetUBXMGAACK->data[packetUBXMGAACK->head].infoCode = extractByte(msg, 2);
packetUBXMGAACK->data[packetUBXMGAACK->head].msgId = extractByte(msg, 3);
packetUBXMGAACK->data[packetUBXMGAACK->head].msgPayloadStart[0] = extractByte(msg, 4);
packetUBXMGAACK->data[packetUBXMGAACK->head].msgPayloadStart[1] = extractByte(msg, 5);
packetUBXMGAACK->data[packetUBXMGAACK->head].msgPayloadStart[2] = extractByte(msg, 6);
packetUBXMGAACK->data[packetUBXMGAACK->head].msgPayloadStart[3] = extractByte(msg, 7);
// Increment the head
packetUBXMGAACK->head++;
if (packetUBXMGAACK->head == UBX_MGA_ACK_DATA0_RINGBUFFER_LEN)
packetUBXMGAACK->head = 0;
}
}
}
break;
case UBX_CLASS_HNR: case UBX_CLASS_HNR:
if (msg->id == UBX_HNR_PVT && msg->len == UBX_HNR_PVT_LEN) if (msg->id == UBX_HNR_PVT && msg->len == UBX_HNR_PVT_LEN)
{ {
@@ -3931,6 +3969,169 @@ bool SFE_UBLOX_GNSS::pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool s
} }
} }
// Push MGA AssistNow data to the module
// Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE)
// Wait for maxWait millis after sending each packet (if mgaAck is NO)
// Return how many MGA packets were pushed successfully
uint16_t SFE_UBLOX_GNSS::pushAssistNowData(uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait)
{
size_t dataPtr = 0; // Pointer into dataBytes
uint16_t packetsProcessed = 0; // Keep count of how many packets have been processed
bool checkForAcks = (mgaAck == SFE_UBLOX_MGA_ASSIST_ACK_YES); // If mgaAck is YES, always check for Acks
// If mgaAck is ENQUIRE, we need to check UBX-CFG-NAVX5 ackAiding to determine if UBX-MGA-ACK's are expected
if (mgaAck == SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE)
{
uint8_t ackAiding = getAckAiding(maxWait); // Enquire if we should expect Acks
if (ackAiding == 1)
checkForAcks = true;
}
// If checkForAcks is true, then we need to set up storage for the UBX-MGA-ACK-DATA0 messages and use the callback
if (checkForAcks)
{
if (packetUBXMGAACK == NULL) initPacketUBXMGAACK(); //Check that RAM has been allocated for the MGA_ACK data
if (packetUBXMGAACK == NULL) //Bail if the RAM allocation failed
return (0);
}
while (dataPtr < numDataBytes) // Keep going until we have processed all the bytes
{
// Start by checking the validity of the packet being pointed to
bool dataIsOK = true;
dataIsOK &= dataBytes[dataPtr + 0] == UBX_SYNCH_1; // Check for 0xB5
dataIsOK &= dataBytes[dataPtr + 1] == UBX_SYNCH_2; // Check for 0x62
dataIsOK &= dataBytes[dataPtr + 2] == UBX_CLASS_MGA; // Check for class UBX-MGA
size_t packetLength = (size_t)dataBytes[dataPtr + 4] + ((size_t)dataBytes[dataPtr + 5] << 8); // Extract the length
uint8_t checksumA = 0;
uint8_t checksumB = 0;
// Calculate the checksum bytes
// Keep going until the end of the packet is reached (payloadPtr == (dataPtr + packetLength))
// or we reach the end of the AssistNow data (payloadPtr == numDataBytes)
for (size_t payloadPtr = dataPtr + ((size_t)6); (payloadPtr < (dataPtr + packetLength + ((size_t)6))) && (payloadPtr < numDataBytes); payloadPtr++)
{
checksumA += dataBytes[payloadPtr];
checksumB += checksumA;
}
// Check the checksum bytes
dataIsOK &= checksumA == dataBytes[dataPtr + packetLength + ((size_t)6)];
dataIsOK &= checksumB == dataBytes[dataPtr + packetLength + ((size_t)7)];
dataIsOK &= (dataPtr + packetLength + ((size_t)8)) <= numDataBytes; // Check we haven't overrun
// If the data is valid, push it
if (dataIsOK)
{
pushRawData((uint8_t *)&dataBytes[dataPtr], packetLength + ((size_t)8)); // Push the data
if (checkForAcks)
{
unsigned long startTime = millis();
bool keepGoing = true;
while (keepGoing && (millis() < (startTime + maxWait))) // Keep checking for the ACK until we time out
{
checkUblox();
if (packetUBXMGAACK->head != packetUBXMGAACK->tail) // Does the MGA ACK ringbuffer contain any ACK's?
{
bool dataAckd = true; // Check if we've received the correct ACK
dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgId == dataBytes[dataPtr + 3];
dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[0] == dataBytes[dataPtr + 6];
dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[1] == dataBytes[dataPtr + 7];
dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[2] == dataBytes[dataPtr + 8];
dataAckd &= packetUBXMGAACK->data[packetUBXMGAACK->tail].msgPayloadStart[3] == dataBytes[dataPtr + 9];
if (dataAckd) // Is this the ACK we are looking for?
{
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
{
_debugSerial->print(F("pushAssistNowData: packet ID 0x"));
if (dataBytes[dataPtr + 3] < 0x10)
_debugSerial->print(F("0"));
_debugSerial->print(dataBytes[dataPtr + 3], HEX);
}
if ((packetUBXMGAACK->data[packetUBXMGAACK->tail].type == (uint8_t)1) && (packetUBXMGAACK->data[packetUBXMGAACK->tail].infoCode == (uint8_t)SFE_UBLOX_MGA_ACK_INFOCODE_ACCEPTED))
{
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
{
_debugSerial->println(F(" was accepted"));
}
packetsProcessed++;
}
else
{
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
{
_debugSerial->print(F(" was _not_ accepted. infoCode is "));
_debugSerial->println(packetUBXMGAACK->data[packetUBXMGAACK->tail].infoCode);
}
}
keepGoing = false;
}
// Increment the tail
packetUBXMGAACK->tail++;
if (packetUBXMGAACK->tail == UBX_MGA_ACK_DATA0_RINGBUFFER_LEN)
packetUBXMGAACK->tail = 0;
}
}
if (keepGoing) // If keepGoing is still true, we must have timed out
{
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
{
_debugSerial->print(F("pushAssistNowData: packet ID 0x"));
if (dataBytes[dataPtr + 3] < 0x10)
_debugSerial->print(F("0"));
_debugSerial->print(dataBytes[dataPtr + 3], HEX);
_debugSerial->println(F(" timed out!"));
}
}
}
else
{
// We are not checking for Acks, so delay for maxWait millis unless we've reached the end of the data
if ((dataPtr + packetLength + ((size_t)8)) < numDataBytes)
{
delay(maxWait);
}
}
dataPtr += packetLength + ((size_t)8); // Point to the next message
}
else
{
// The data was invalid. Send a debug message and then try to find the next 0xB5
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
{
_debugSerial->print(F("pushAssistNowData: bad data - ignored! dataPtr is"));
_debugSerial->println(dataPtr);
}
while ((dataPtr < numDataBytes) && (dataBytes[++dataPtr] != UBX_SYNCH_1))
{
; // Increment dataPtr until we are pointing at the next 0xB5 - or we reach the end of the data
}
}
}
return (packetsProcessed);
}
// PRIVATE: Allocate RAM for packetUBXMGAACK and initialize it
bool SFE_UBLOX_GNSS::initPacketUBXMGAACK()
{
packetUBXMGAACK = new UBX_MGA_ACK_DATA0_t; //Allocate RAM for the main struct
if (packetUBXMGAACK == NULL)
{
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
_debugSerial->println(F("initPacketUBXMGAACK: RAM alloc failed!"));
return (false);
}
packetUBXMGAACK->head = 0; // Initialize the ring buffer pointers
packetUBXMGAACK->tail = 0;
return (true);
}
// Support for data logging // Support for data logging
//Set the file buffer size. This must be called _before_ .begin //Set the file buffer size. This must be called _before_ .begin
@@ -5383,6 +5584,44 @@ bool SFE_UBLOX_GNSS::setTimePulseParameters(UBX_CFG_TP5_data_t *data, uint16_t m
return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
} }
//UBX-CFG-NAVX5 - get/set the ackAiding byte. If ackAiding is 1, UBX-MGA-ACK messages will be sent by the module to acknowledge the MGA data
uint8_t SFE_UBLOX_GNSS::getAckAiding(uint16_t maxWait) // Get the ackAiding byte - returns 255 if the sendCommand fails
{
packetCfg.cls = UBX_CLASS_CFG;
packetCfg.id = UBX_CFG_NAVX5;
packetCfg.len = 0;
packetCfg.startingSpot = 0;
if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK
return (255);
// Extract the ackAiding byte
// There are three versions of UBX-CFG-NAVX5 but ackAiding is always in byte 17
return (extractByte(&packetCfg, 17));
}
bool SFE_UBLOX_GNSS::setAckAiding(uint8_t ackAiding, uint16_t maxWait) // Set the ackAiding byte
{
packetCfg.cls = UBX_CLASS_CFG;
packetCfg.id = UBX_CFG_NAVX5;
packetCfg.len = 0;
packetCfg.startingSpot = 0;
if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK
return (false);
// Set the ackAiding byte
// There are three versions of UBX-CFG-NAVX5 but ackAiding is always in byte 17
payloadCfg[17] = ackAiding;
// There are three versions of UBX-CFG-NAVX5 but the ackAid flag is always in bit 10 of mask1
payloadCfg[2] = 0x00; // Clear the LS byte of mask1
payloadCfg[3] = 0x40; // Set _only_ the ackAid flag = bit 10 of mask1 = bit 2 of the MS byte
payloadCfg[4] = 0x00; // Clear the LS byte of mask2, just in case
payloadCfg[5] = 0x00; // Clear the LS byte of mask2, just in case
return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
}
// CONFIGURATION INTERFACE (protocol v27 and above) // CONFIGURATION INTERFACE (protocol v27 and above)
//Form 32-bit key from group/id/size //Form 32-bit key from group/id/size
+36 -1
View File
@@ -200,7 +200,7 @@ const uint8_t UBX_CFG_BATCH = 0x93; //Get/set data batching configuration.
const uint8_t UBX_CFG_CFG = 0x09; //Clear, Save, and Load Configurations. Used to save current configuration const uint8_t UBX_CFG_CFG = 0x09; //Clear, Save, and Load Configurations. Used to save current configuration
const uint8_t UBX_CFG_DAT = 0x06; //Set User-defined Datum or The currently defined Datum const uint8_t UBX_CFG_DAT = 0x06; //Set User-defined Datum or The currently defined Datum
const uint8_t UBX_CFG_DGNSS = 0x70; //DGNSS configuration const uint8_t UBX_CFG_DGNSS = 0x70; //DGNSS configuration
const uint8_t UBX_CFG_ESFALG = 0x56; //ESF alignment const uint8_t UBX_CFG_ESFALG = 0x56; //ESF alignment
const uint8_t UBX_CFG_ESFA = 0x4C; //ESF accelerometer const uint8_t UBX_CFG_ESFA = 0x4C; //ESF accelerometer
const uint8_t UBX_CFG_ESFG = 0x4D; //ESF gyro const uint8_t UBX_CFG_ESFG = 0x4D; //ESF gyro
const uint8_t UBX_CFG_GEOFENCE = 0x69; //Geofencing configuration. Used to configure a geofence const uint8_t UBX_CFG_GEOFENCE = 0x69; //Geofencing configuration. Used to configure a geofence
@@ -496,6 +496,27 @@ enum sfe_ublox_ls_src_e
SFE_UBLOX_LS_SRC_UNKNOWN = 255 SFE_UBLOX_LS_SRC_UNKNOWN = 255
}; };
typedef enum
{
SFE_UBLOX_MGA_ASSIST_ACK_NO, // Do not expect UBX-MGA-ACK's. If the module outputs them, they will be ignored
SFE_UBLOX_MGA_ASSIST_ACK_YES, // Expect and check for UBX-MGA-ACK's
SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE // Check UBX-CFG-NAVX5 ackAiding to determine if UBX-MGA-ACK's are expected
} sfe_ublox_mga_assist_ack_e;
// The infoCode byte included in UBX-MGA-ACK-DATA0
enum sfe_ublox_mga_ack_infocode_e
{
SFE_UBLOX_MGA_ACK_INFOCODE_ACCEPTED,
SFE_UBLOX_MGA_ACK_INFOCODE_NO_TIME,
SFE_UBLOX_MGA_ACK_INFOCODE_NOT_SUPPORTED,
SFE_UBLOX_MGA_ACK_INFOCODE_SIZE_MISMATCH,
SFE_UBLOX_MGA_ACK_INFOCODE_NOT_STORED,
SFE_UBLOX_MGA_ACK_INFOCODE_NOT_READY,
SFE_UBLOX_MGA_ACK_INFOCODE_TYPE_UNKNOWN
};
//-=-=-=-=-
#ifndef MAX_PAYLOAD_SIZE #ifndef MAX_PAYLOAD_SIZE
// v2.0: keep this for backwards-compatibility, but this is largely superseded by setPacketCfgPayloadSize // v2.0: keep this for backwards-compatibility, but this is largely superseded by setPacketCfgPayloadSize
#define MAX_PAYLOAD_SIZE 256 //We need ~220 bytes for getProtocolVersion on most ublox modules #define MAX_PAYLOAD_SIZE 256 //We need ~220 bytes for getProtocolVersion on most ublox modules
@@ -683,6 +704,13 @@ public:
// Default to using a restart between transmissions. But processors like ESP32 seem to need a stop (#30). Set stop to true to use a stop instead. // Default to using a restart between transmissions. But processors like ESP32 seem to need a stop (#30). Set stop to true to use a stop instead.
bool pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool stop = false); bool pushRawData(uint8_t *dataBytes, size_t numDataBytes, bool stop = false);
// Push MGA AssistNow data to the module
// Check for UBX-MGA-ACK responses if required (if mgaAck is YES or ENQUIRE)
// Wait for maxWait millis after sending each packet (if mgaAck is NO)
// Return how many MGA packets were pushed successfully
#define defaultMGAdelay 10 // Default to waiting for 10ms between each MGA message
uint16_t pushAssistNowData(uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck = SFE_UBLOX_MGA_ASSIST_ACK_NO, uint16_t maxWait = defaultMGAdelay);
// Support for data logging // Support for data logging
void setFileBufferSize(uint16_t bufferSize); // Set the size of the file buffer. This must be called _before_ .begin. void setFileBufferSize(uint16_t bufferSize); // Set the size of the file buffer. This must be called _before_ .begin.
uint16_t getFileBufferSize(void); // Return the size of the file buffer uint16_t getFileBufferSize(void); // Return the size of the file buffer
@@ -785,6 +813,10 @@ public:
bool getTimePulseParameters(UBX_CFG_TP5_data_t *data = NULL, uint16_t maxWait = defaultMaxWait); // Get the time pulse parameters using UBX_CFG_TP5 bool getTimePulseParameters(UBX_CFG_TP5_data_t *data = NULL, uint16_t maxWait = defaultMaxWait); // Get the time pulse parameters using UBX_CFG_TP5
bool setTimePulseParameters(UBX_CFG_TP5_data_t *data = NULL, uint16_t maxWait = defaultMaxWait); // Set the time pulse parameters using UBX_CFG_TP5 bool setTimePulseParameters(UBX_CFG_TP5_data_t *data = NULL, uint16_t maxWait = defaultMaxWait); // Set the time pulse parameters using UBX_CFG_TP5
//UBX-CFG-NAVX5 - get/set the ackAiding byte. If ackAiding is 1, UBX-MGA-ACK messages will be sent by the module to acknowledge the MGA data
uint8_t getAckAiding(uint16_t maxWait = defaultMaxWait); // Get the ackAiding byte - returns 255 if the sendCommand fails
bool setAckAiding(uint8_t ackAiding, uint16_t maxWait = defaultMaxWait); // Set the ackAiding byte
//General configuration (used only on protocol v27 and higher - ie, ZED-F9P) //General configuration (used only on protocol v27 and higher - ie, ZED-F9P)
//It is probably safe to assume that users of the ZED-F9P will be using I2C / Qwiic. //It is probably safe to assume that users of the ZED-F9P will be using I2C / Qwiic.
@@ -1242,6 +1274,8 @@ public:
UBX_HNR_ATT_t *packetUBXHNRATT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_HNR_ATT_t *packetUBXHNRATT = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary
UBX_HNR_INS_t *packetUBXHNRINS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary UBX_HNR_INS_t *packetUBXHNRINS = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary
UBX_MGA_ACK_DATA0_t *packetUBXMGAACK = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary
uint16_t rtcmFrameCounter = 0; //Tracks the type of incoming byte inside RTCM frame uint16_t rtcmFrameCounter = 0; //Tracks the type of incoming byte inside RTCM frame
private: private:
@@ -1313,6 +1347,7 @@ private:
bool initPacketUBXHNRATT(); // Allocate RAM for packetUBXHNRATT and initialize it bool initPacketUBXHNRATT(); // Allocate RAM for packetUBXHNRATT and initialize it
bool initPacketUBXHNRINS(); // Allocate RAM for packetUBXHNRINS and initialize it bool initPacketUBXHNRINS(); // Allocate RAM for packetUBXHNRINS and initialize it
bool initPacketUBXHNRPVT(); // Allocate RAM for packetUBXHNRPVT and initialize it bool initPacketUBXHNRPVT(); // Allocate RAM for packetUBXHNRPVT and initialize it
bool initPacketUBXMGAACK(); // Allocate RAM for packetUBXMGAACK and initialize it
//Variables //Variables
TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware
+25
View File
@@ -1656,6 +1656,31 @@ typedef struct
UBX_ESF_STATUS_data_t *callbackData; UBX_ESF_STATUS_data_t *callbackData;
} UBX_ESF_STATUS_t; } UBX_ESF_STATUS_t;
// MGA-specific structs
// UBX-MGA-ACK-DATA0 (0x13 0x60): Multiple GNSS acknowledge message
const uint16_t UBX_MGA_ACK_DATA0_LEN = 8;
typedef struct
{
uint8_t type; // Type of acknowledgment:
// 0: The message was not used by the receiver (see infoCode field for an indication of why)
// 1: The message was accepted for use by the receiver (the infoCode field will be 0)
uint8_t version; // Message version
uint8_t infoCode; // Provides greater information on what the receiver chose to do with the message contents
// See sfe_ublox_mga_ack_infocode_e
uint8_t msgId; // UBX message ID of the acknowledged message
uint8_t msgPayloadStart[4]; // The first 4 bytes of the acknowledged message's payload
} UBX_MGA_ACK_DATA0_data_t;
#define UBX_MGA_ACK_DATA0_RINGBUFFER_LEN 16 // Provide storage for 16 MGA ACK packets
typedef struct
{
uint8_t head;
uint8_t tail;
UBX_MGA_ACK_DATA0_data_t data[UBX_MGA_ACK_DATA0_RINGBUFFER_LEN]; // Create a storage array for the MGA ACK packets
} UBX_MGA_ACK_DATA0_t;
// HNR-specific structs // HNR-specific structs
// UBX-HNR-PVT (0x28 0x00): High rate output of PVT solution // UBX-HNR-PVT (0x28 0x00): High rate output of PVT solution