Add ring buffer for incoming MGA ACKs
This commit is contained in:
+58
-25
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user