This commit is contained in:
brentru 2025-07-21 10:52:34 -04:00
parent 8f6b59b218
commit 5eb550766a
6 changed files with 477 additions and 430 deletions

View file

@ -1,32 +1,32 @@
/*! /*!
* @file Adafruit_UBX.cpp * @file Adafruit_UBX.cpp
* *
* @mainpage Arduino library for UBX protocol from u-blox GPS/RTK modules * @mainpage Arduino library for UBX protocol from u-blox GPS/RTK modules
* *
* @section intro_sec Introduction * @section intro_sec Introduction
* *
* This is a library for parsing UBX protocol messages from u-blox GPS/RTK modules. * This is a library for parsing UBX protocol messages from u-blox GPS/RTK
* It works with any Stream-based interface including UART and DDC (I2C). * modules. It works with any Stream-based interface including UART and DDC
* * (I2C).
* Designed specifically to work with u-blox GPS/RTK modules *
* Designed specifically to work with u-blox GPS/RTK modules
* like NEO-M8P, ZED-F9P, etc. * like NEO-M8P, ZED-F9P, etc.
* *
* @section author Author * @section author Author
* *
* Written by Limor Fried/Ladyada for Adafruit Industries. * Written by Limor Fried/Ladyada for Adafruit Industries.
* *
* @section license License * @section license License
* *
* MIT license, all text above must be included in any redistribution * MIT license, all text above must be included in any redistribution
*/ */
#include "Adafruit_UBX.h" #include "Adafruit_UBX.h"
/*! /*!
* @brief Constructor * @brief Constructor
* @param stream Reference to a Stream object (Serial, Adafruit_UBloxDDC, etc.) * @param stream Reference to a Stream object (Serial, Adafruit_UBloxDDC,
* etc.)
*/ */
Adafruit_UBX::Adafruit_UBX(Stream &stream) { Adafruit_UBX::Adafruit_UBX(Stream &stream) {
_stream = &stream; _stream = &stream;
@ -42,9 +42,6 @@ bool Adafruit_UBX::begin() {
return true; return true;
} }
/*! /*!
* @brief Configure the GPS module to output only UBX protocol (disables NMEA) * @brief Configure the GPS module to output only UBX protocol (disables NMEA)
* @param portID Port identifier (UBX_PORT_DDC, UBX_PORT_UART1, etc.) * @param portID Port identifier (UBX_PORT_DDC, UBX_PORT_UART1, etc.)
@ -52,58 +49,60 @@ bool Adafruit_UBX::begin() {
* @param timeout_ms Maximum time to wait for acknowledgment in milliseconds * @param timeout_ms Maximum time to wait for acknowledgment in milliseconds
* @return UBXSendStatus indicating success, failure, or timeout * @return UBXSendStatus indicating success, failure, or timeout
*/ */
UBXSendStatus Adafruit_UBX::setUBXOnly(UBXPortId portID, bool checkAck, uint16_t timeout_ms) { UBXSendStatus Adafruit_UBX::setUBXOnly(UBXPortId portID, bool checkAck,
uint16_t timeout_ms) {
UBX_CFG_PRT_t cfgPrt; UBX_CFG_PRT_t cfgPrt;
// Zero out the structure // Zero out the structure
memset(&cfgPrt, 0, sizeof(cfgPrt)); memset(&cfgPrt, 0, sizeof(cfgPrt));
// Set the port ID // Set the port ID
cfgPrt.fields.portID = portID; cfgPrt.fields.portID = portID;
// Configure the port appropriately // Configure the port appropriately
switch (portID) { switch (portID) {
case UBX_PORT_DDC: // I2C/DDC port case UBX_PORT_DDC: // I2C/DDC port
// Set the I2C address to 0x42 (the default) // Set the I2C address to 0x42 (the default)
// For DDC, the mode field contains the I2C address in bits 7:1 // For DDC, the mode field contains the I2C address in bits 7:1
cfgPrt.fields.mode = 0x42 << 1; // 0x84 cfgPrt.fields.mode = 0x42 << 1; // 0x84
// Set protocol masks to UBX only // Set protocol masks to UBX only
cfgPrt.fields.inProtoMask = UBX_PROTOCOL_UBX; cfgPrt.fields.inProtoMask = UBX_PROTOCOL_UBX;
cfgPrt.fields.outProtoMask = UBX_PROTOCOL_UBX; cfgPrt.fields.outProtoMask = UBX_PROTOCOL_UBX;
break; break;
case UBX_PORT_UART1: // Fall through case UBX_PORT_UART1: // Fall through
case UBX_PORT_UART2: // UART ports case UBX_PORT_UART2: // UART ports
// Keep current baud rate (baudRate = 0 keeps current setting) // Keep current baud rate (baudRate = 0 keeps current setting)
// Set 8N1 mode for binary protocol // Set 8N1 mode for binary protocol
cfgPrt.fields.mode = UBX_UART_MODE_8N1; cfgPrt.fields.mode = UBX_UART_MODE_8N1;
// Set protocol masks to UBX only // Set protocol masks to UBX only
cfgPrt.fields.inProtoMask = UBX_PROTOCOL_UBX; cfgPrt.fields.inProtoMask = UBX_PROTOCOL_UBX;
cfgPrt.fields.outProtoMask = UBX_PROTOCOL_UBX; cfgPrt.fields.outProtoMask = UBX_PROTOCOL_UBX;
break; break;
case UBX_PORT_USB: // USB port case UBX_PORT_USB: // USB port
// Set protocol masks to UBX only // Set protocol masks to UBX only
cfgPrt.fields.inProtoMask = UBX_PROTOCOL_UBX; cfgPrt.fields.inProtoMask = UBX_PROTOCOL_UBX;
cfgPrt.fields.outProtoMask = UBX_PROTOCOL_UBX; cfgPrt.fields.outProtoMask = UBX_PROTOCOL_UBX;
break; break;
case UBX_PORT_SPI: // SPI port case UBX_PORT_SPI: // SPI port
// Set protocol masks to UBX only // Set protocol masks to UBX only
cfgPrt.fields.outProtoMask = UBX_PROTOCOL_UBX; cfgPrt.fields.outProtoMask = UBX_PROTOCOL_UBX;
break; break;
default: default:
if (verbose_debug > 0) { if (verbose_debug > 0) {
Serial.println(F("UBX: Invalid port ID")); Serial.println(F("UBX: Invalid port ID"));
} }
return UBX_SEND_FAIL; // Invalid port ID return UBX_SEND_FAIL; // Invalid port ID
} }
// Send the message and wait for acknowledgment if requested // Send the message and wait for acknowledgment if requested
if (checkAck) { if (checkAck) {
return sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_PRT, cfgPrt.raw, sizeof(cfgPrt), timeout_ms); return sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_PRT, cfgPrt.raw,
sizeof(cfgPrt), timeout_ms);
} else { } else {
if (sendMessage(UBX_CLASS_CFG, UBX_CFG_PRT, cfgPrt.raw, sizeof(cfgPrt))) { if (sendMessage(UBX_CLASS_CFG, UBX_CFG_PRT, cfgPrt.raw, sizeof(cfgPrt))) {
return UBX_SEND_SUCCESS; return UBX_SEND_SUCCESS;
@ -113,12 +112,10 @@ UBXSendStatus Adafruit_UBX::setUBXOnly(UBXPortId portID, bool checkAck, uint16_t
} }
} }
/*! /*!
* @brief Sets the callback function for UBX messages * @brief Sets the callback function for UBX messages
* @param callback Function pointer to call when a complete UBX message is received * @param callback Function pointer to call when a complete UBX message is
* received
*/ */
void Adafruit_UBX::setMessageCallback(UBXMessageCallback callback) { void Adafruit_UBX::setMessageCallback(UBXMessageCallback callback) {
onUBXMessage = callback; onUBXMessage = callback;
@ -140,10 +137,11 @@ void Adafruit_UBX::resetParser() {
* @param checksumA Reference to store the first checksum byte * @param checksumA Reference to store the first checksum byte
* @param checksumB Reference to store the second checksum byte * @param checksumB Reference to store the second checksum byte
*/ */
void Adafruit_UBX::calculateChecksum(uint8_t *buffer, uint16_t len, uint8_t &checksumA, uint8_t &checksumB) { void Adafruit_UBX::calculateChecksum(uint8_t *buffer, uint16_t len,
uint8_t &checksumA, uint8_t &checksumB) {
checksumA = 0; checksumA = 0;
checksumB = 0; checksumB = 0;
for (uint16_t i = 0; i < len; i++) { for (uint16_t i = 0; i < len; i++) {
checksumA += buffer[i]; checksumA += buffer[i];
checksumB += checksumA; checksumB += checksumA;
@ -156,150 +154,158 @@ void Adafruit_UBX::calculateChecksum(uint8_t *buffer, uint16_t len, uint8_t &che
*/ */
bool Adafruit_UBX::checkMessages() { bool Adafruit_UBX::checkMessages() {
bool messageReceived = false; bool messageReceived = false;
// Process all available bytes // Process all available bytes
while (_stream->available()) { while (_stream->available()) {
uint8_t incomingByte = _stream->read(); uint8_t incomingByte = _stream->read();
// State machine for UBX protocol parsing // State machine for UBX protocol parsing
switch (_parserState) { switch (_parserState) {
case WAIT_SYNC_1: case WAIT_SYNC_1:
if (incomingByte == UBX_SYNC_CHAR_1) { if (incomingByte == UBX_SYNC_CHAR_1) {
_parserState = WAIT_SYNC_2; _parserState = WAIT_SYNC_2;
_buffer[0] = incomingByte; // Store for checksum calculation _buffer[0] = incomingByte; // Store for checksum calculation
} }
break; break;
case WAIT_SYNC_2:
if (incomingByte == UBX_SYNC_CHAR_2) {
_parserState = GET_CLASS;
_buffer[1] = incomingByte; // Store for checksum calculation
} else {
resetParser(); // Invalid sync char, reset
}
break;
case GET_CLASS:
_msgClass = incomingByte;
_buffer[2] = incomingByte; // Store for checksum calculation
_parserState = GET_ID;
break;
case GET_ID:
_msgId = incomingByte;
_buffer[3] = incomingByte; // Store for checksum calculation
_parserState = GET_LENGTH_1;
break;
case GET_LENGTH_1:
_payloadLength = incomingByte;
_buffer[4] = incomingByte; // Store for checksum calculation
_parserState = GET_LENGTH_2;
break;
case GET_LENGTH_2:
_payloadLength |= (incomingByte << 8);
_buffer[5] = incomingByte; // Store for checksum calculation
if (_payloadLength > MAX_PAYLOAD_SIZE) {
resetParser(); // Payload too large, reset
} else {
_payloadCounter = 0;
_parserState = GET_PAYLOAD;
}
break;
case GET_PAYLOAD:
if (_payloadCounter < _payloadLength) {
_buffer[6 + _payloadCounter] = incomingByte;
_payloadCounter++;
if (_payloadCounter == _payloadLength) {
_parserState = GET_CHECKSUM_A;
}
}
break;
case GET_CHECKSUM_A:
// Calculate expected checksum
calculateChecksum(_buffer + 2, _payloadLength + 4, _checksumA, _checksumB);
if (incomingByte == _checksumA) {
_parserState = GET_CHECKSUM_B; // Checksum A matches
} else {
resetParser(); // Invalid checksum, reset
}
break;
case GET_CHECKSUM_B:
if (incomingByte == _checksumB) {
// We have a valid message!
if (onUBXMessage != NULL) {
onUBXMessage(_msgClass, _msgId, _payloadLength, _buffer + 6); // Call the callback with the message
}
messageReceived = true;
_lastMsgClass = _msgClass; case WAIT_SYNC_2:
_lastMsgId = _msgId; if (incomingByte == UBX_SYNC_CHAR_2) {
_lastPayloadLength = _payloadLength; _parserState = GET_CLASS;
_buffer[1] = incomingByte; // Store for checksum calculation
// Store a small copy of the payload if it's within size limits } else {
if (_payloadLength <= sizeof(_lastPayload)) { resetParser(); // Invalid sync char, reset
memcpy(_lastPayload, _buffer + 6, _payloadLength); }
} break;
if (verbose_debug > 0) { case GET_CLASS:
Serial.print("UBX RX: "); _msgClass = incomingByte;
_buffer[2] = incomingByte; // Store for checksum calculation
// Print header (sync chars, class, id, length) _parserState = GET_ID;
Serial.print("HDR[B5 62 "); break;
if (_msgClass < 0x10) Serial.print("0");
Serial.print(_msgClass, HEX); case GET_ID:
Serial.print(" "); _msgId = incomingByte;
if (_msgId < 0x10) Serial.print("0"); _buffer[3] = incomingByte; // Store for checksum calculation
Serial.print(_msgId, HEX); _parserState = GET_LENGTH_1;
Serial.print(" "); break;
uint8_t lenLSB = _payloadLength & 0xFF; case GET_LENGTH_1:
uint8_t lenMSB = (_payloadLength >> 8) & 0xFF; _payloadLength = incomingByte;
if (lenLSB < 0x10) Serial.print("0"); _buffer[4] = incomingByte; // Store for checksum calculation
Serial.print(lenLSB, HEX); _parserState = GET_LENGTH_2;
Serial.print(" "); break;
if (lenMSB < 0x10) Serial.print("0");
Serial.print(lenMSB, HEX); case GET_LENGTH_2:
Serial.print("] "); _payloadLength |= (incomingByte << 8);
_buffer[5] = incomingByte; // Store for checksum calculation
// Print payload if verbose debug is enabled
if (verbose_debug > 1 && _payloadLength > 0) { if (_payloadLength > MAX_PAYLOAD_SIZE) {
Serial.print("PL["); resetParser(); // Payload too large, reset
for (uint16_t i = 0; i < _payloadLength; i++) { } else {
if (_buffer[6 + i] < 0x10) Serial.print("0"); _payloadCounter = 0;
Serial.print(_buffer[6 + i], HEX); _parserState = GET_PAYLOAD;
Serial.print(" "); }
} break;
Serial.print("] ");
case GET_PAYLOAD:
if (_payloadCounter < _payloadLength) {
_buffer[6 + _payloadCounter] = incomingByte;
_payloadCounter++;
if (_payloadCounter == _payloadLength) {
_parserState = GET_CHECKSUM_A;
}
}
break;
case GET_CHECKSUM_A:
// Calculate expected checksum
calculateChecksum(_buffer + 2, _payloadLength + 4, _checksumA,
_checksumB);
if (incomingByte == _checksumA) {
_parserState = GET_CHECKSUM_B; // Checksum A matches
} else {
resetParser(); // Invalid checksum, reset
}
break;
case GET_CHECKSUM_B:
if (incomingByte == _checksumB) {
// We have a valid message!
if (onUBXMessage != NULL) {
onUBXMessage(_msgClass, _msgId, _payloadLength,
_buffer + 6); // Call the callback with the message
}
messageReceived = true;
_lastMsgClass = _msgClass;
_lastMsgId = _msgId;
_lastPayloadLength = _payloadLength;
// Store a small copy of the payload if it's within size limits
if (_payloadLength <= sizeof(_lastPayload)) {
memcpy(_lastPayload, _buffer + 6, _payloadLength);
}
if (verbose_debug > 0) {
Serial.print("UBX RX: ");
// Print header (sync chars, class, id, length)
Serial.print("HDR[B5 62 ");
if (_msgClass < 0x10)
Serial.print("0");
Serial.print(_msgClass, HEX);
Serial.print(" ");
if (_msgId < 0x10)
Serial.print("0");
Serial.print(_msgId, HEX);
Serial.print(" ");
uint8_t lenLSB = _payloadLength & 0xFF;
uint8_t lenMSB = (_payloadLength >> 8) & 0xFF;
if (lenLSB < 0x10)
Serial.print("0");
Serial.print(lenLSB, HEX);
Serial.print(" ");
if (lenMSB < 0x10)
Serial.print("0");
Serial.print(lenMSB, HEX);
Serial.print("] ");
// Print payload if verbose debug is enabled
if (verbose_debug > 1 && _payloadLength > 0) {
Serial.print("PL[");
for (uint16_t i = 0; i < _payloadLength; i++) {
if (_buffer[6 + i] < 0x10)
Serial.print("0");
Serial.print(_buffer[6 + i], HEX);
Serial.print(" ");
} }
Serial.print("] ");
// Print checksum
Serial.print("CS[");
if (_checksumA < 0x10) Serial.print("0");
Serial.print(_checksumA, HEX);
Serial.print(" ");
if (_checksumB < 0x10) Serial.print("0");
Serial.print(_checksumB, HEX);
Serial.println("]");
} }
// Print checksum
Serial.print("CS[");
if (_checksumA < 0x10)
Serial.print("0");
Serial.print(_checksumA, HEX);
Serial.print(" ");
if (_checksumB < 0x10)
Serial.print("0");
Serial.print(_checksumB, HEX);
Serial.println("]");
} }
}
resetParser(); // Reset for next message
break; resetParser(); // Reset for next message
break;
} }
} }
return messageReceived; return messageReceived;
} }
/*! /*!
* @brief Send a UBX message and wait for acknowledgment * @brief Send a UBX message and wait for acknowledgment
* @param msgClass Message class * @param msgClass Message class
@ -309,7 +315,10 @@ bool Adafruit_UBX::checkMessages() {
* @param timeout_ms Maximum time to wait for acknowledgment * @param timeout_ms Maximum time to wait for acknowledgment
* @return UBXSendStatus indicating success, failure, or timeout * @return UBXSendStatus indicating success, failure, or timeout
*/ */
UBXSendStatus Adafruit_UBX::sendMessageWithAck(uint8_t msgClass, uint8_t msgId, uint8_t *payload, uint16_t length, uint16_t timeout_ms = 500) { UBXSendStatus Adafruit_UBX::sendMessageWithAck(uint8_t msgClass, uint8_t msgId,
uint8_t *payload,
uint16_t length,
uint16_t timeout_ms = 500) {
// First send the message // First send the message
if (!sendMessage(msgClass, msgId, payload, length)) { if (!sendMessage(msgClass, msgId, payload, length)) {
if (verbose_debug > 0) { if (verbose_debug > 0) {
@ -317,9 +326,9 @@ UBXSendStatus Adafruit_UBX::sendMessageWithAck(uint8_t msgClass, uint8_t msgId,
} }
return UBX_SEND_FAIL; return UBX_SEND_FAIL;
} }
uint32_t startTime = millis(); uint32_t startTime = millis();
// Check for messages until timeout // Check for messages until timeout
while ((millis() - startTime) < timeout_ms) { while ((millis() - startTime) < timeout_ms) {
// Process incoming bytes // Process incoming bytes
@ -332,10 +341,12 @@ UBXSendStatus Adafruit_UBX::sendMessageWithAck(uint8_t msgClass, uint8_t msgId,
if (_lastPayload[0] == msgClass && _lastPayload[1] == msgId) { if (_lastPayload[0] == msgClass && _lastPayload[1] == msgId) {
if (verbose_debug > 0) { if (verbose_debug > 0) {
Serial.print(F("UBX ACK: SUCCESS for message class 0x")); Serial.print(F("UBX ACK: SUCCESS for message class 0x"));
if (msgClass < 0x10) Serial.print("0"); if (msgClass < 0x10)
Serial.print("0");
Serial.print(msgClass, HEX); Serial.print(msgClass, HEX);
Serial.print(" ID 0x"); Serial.print(" ID 0x");
if (msgId < 0x10) Serial.print("0"); if (msgId < 0x10)
Serial.print("0");
Serial.println(msgId, HEX); Serial.println(msgId, HEX);
} }
return UBX_SEND_SUCCESS; return UBX_SEND_SUCCESS;
@ -345,10 +356,12 @@ UBXSendStatus Adafruit_UBX::sendMessageWithAck(uint8_t msgClass, uint8_t msgId,
if (_lastPayload[0] == msgClass && _lastPayload[1] == msgId) { if (_lastPayload[0] == msgClass && _lastPayload[1] == msgId) {
if (verbose_debug > 0) { if (verbose_debug > 0) {
Serial.print(F("UBX ACK: NAK for message class 0x")); Serial.print(F("UBX ACK: NAK for message class 0x"));
if (msgClass < 0x10) Serial.print("0"); if (msgClass < 0x10)
Serial.print("0");
Serial.print(msgClass, HEX); Serial.print(msgClass, HEX);
Serial.print(" ID 0x"); Serial.print(" ID 0x");
if (msgId < 0x10) Serial.print("0"); if (msgId < 0x10)
Serial.print("0");
Serial.println(msgId, HEX); Serial.println(msgId, HEX);
} }
return UBX_SEND_NAK; return UBX_SEND_NAK;
@ -356,96 +369,105 @@ UBXSendStatus Adafruit_UBX::sendMessageWithAck(uint8_t msgClass, uint8_t msgId,
} }
} }
} }
// Short delay // Short delay
delay(1); delay(1);
} }
if (verbose_debug > 0) { if (verbose_debug > 0) {
Serial.print(F("UBX ACK: TIMEOUT waiting for ACK/NAK for message class 0x")); Serial.print(
if (msgClass < 0x10) Serial.print("0"); F("UBX ACK: TIMEOUT waiting for ACK/NAK for message class 0x"));
if (msgClass < 0x10)
Serial.print("0");
Serial.print(msgClass, HEX); Serial.print(msgClass, HEX);
Serial.print(" ID 0x"); Serial.print(" ID 0x");
if (msgId < 0x10) Serial.print("0"); if (msgId < 0x10)
Serial.print("0");
Serial.println(msgId, HEX); Serial.println(msgId, HEX);
} }
return UBX_SEND_TIMEOUT; return UBX_SEND_TIMEOUT;
} }
/*! /*!
* @brief Send a UBX message to the GPS module * @brief Send a UBX message to the GPS module
* @param msgClass Message class * @param msgClass Message class
* @param msgId Message ID * @param msgId Message ID
* @param payload Pointer to the payload data (can be NULL for zero-length payload) * @param payload Pointer to the payload data (can be NULL for zero-length
* payload)
* @param length Length of payload * @param length Length of payload
* @return True if message was sent successfully * @return True if message was sent successfully
*/ */
bool Adafruit_UBX::sendMessage(uint8_t msgClass, uint8_t msgId, uint8_t *payload, uint16_t length) { bool Adafruit_UBX::sendMessage(uint8_t msgClass, uint8_t msgId,
// Buffer for message (2 sync chars + class + id + 2 length bytes + payload + 2 checksum bytes) uint8_t *payload, uint16_t length) {
// Buffer for message (2 sync chars + class + id + 2 length bytes + payload +
// 2 checksum bytes)
uint8_t msgBuffer[length + 8]; uint8_t msgBuffer[length + 8];
// Sync characters // Sync characters
msgBuffer[0] = UBX_SYNC_CHAR_1; msgBuffer[0] = UBX_SYNC_CHAR_1;
msgBuffer[1] = UBX_SYNC_CHAR_2; msgBuffer[1] = UBX_SYNC_CHAR_2;
// Message class and ID // Message class and ID
msgBuffer[2] = msgClass; msgBuffer[2] = msgClass;
msgBuffer[3] = msgId; msgBuffer[3] = msgId;
// Length (little endian) // Length (little endian)
msgBuffer[4] = length & 0xFF; msgBuffer[4] = length & 0xFF;
msgBuffer[5] = (length >> 8) & 0xFF; msgBuffer[5] = (length >> 8) & 0xFF;
// Payload // Payload
if (payload != NULL && length > 0) { if (payload != NULL && length > 0) {
memcpy(&msgBuffer[6], payload, length); memcpy(&msgBuffer[6], payload, length);
} }
// Calculate checksum // Calculate checksum
uint8_t checksumA, checksumB; uint8_t checksumA, checksumB;
calculateChecksum(&msgBuffer[2], length + 4, checksumA, checksumB); calculateChecksum(&msgBuffer[2], length + 4, checksumA, checksumB);
msgBuffer[6 + length] = checksumA; msgBuffer[6 + length] = checksumA;
msgBuffer[7 + length] = checksumB; msgBuffer[7 + length] = checksumB;
// Debug output // Debug output
if (verbose_debug > 0) { if (verbose_debug > 0) {
Serial.print("UBX TX: "); Serial.print("UBX TX: ");
// Print header (sync chars, class, id, length) // Print header (sync chars, class, id, length)
Serial.print("HDR["); Serial.print("HDR[");
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
if (msgBuffer[i] < 0x10) Serial.print("0"); if (msgBuffer[i] < 0x10)
Serial.print("0");
Serial.print(msgBuffer[i], HEX); Serial.print(msgBuffer[i], HEX);
Serial.print(" "); Serial.print(" ");
} }
Serial.print("] "); Serial.print("] ");
// Print payload if verbose debug is enabled // Print payload if verbose debug is enabled
if (verbose_debug > 1 && length > 0) { if (verbose_debug > 1 && length > 0) {
Serial.print("PL["); Serial.print("PL[");
for (uint16_t i = 0; i < length; i++) { for (uint16_t i = 0; i < length; i++) {
if (msgBuffer[6 + i] < 0x10) Serial.print("0"); if (msgBuffer[6 + i] < 0x10)
Serial.print("0");
Serial.print(msgBuffer[6 + i], HEX); Serial.print(msgBuffer[6 + i], HEX);
Serial.print(" "); Serial.print(" ");
} }
Serial.print("] "); Serial.print("] ");
} }
// Print checksum // Print checksum
Serial.print("CS["); Serial.print("CS[");
if (checksumA < 0x10) Serial.print("0"); if (checksumA < 0x10)
Serial.print("0");
Serial.print(checksumA, HEX); Serial.print(checksumA, HEX);
Serial.print(" "); Serial.print(" ");
if (checksumB < 0x10) Serial.print("0"); if (checksumB < 0x10)
Serial.print("0");
Serial.print(checksumB, HEX); Serial.print(checksumB, HEX);
Serial.println("]"); Serial.println("]");
} }
// Send the message // Send the message
size_t written = _stream->write(msgBuffer, length + 8); size_t written = _stream->write(msgBuffer, length + 8);
return (written == length + 8); return (written == length + 8);
} }

View file

@ -1,98 +1,105 @@
/*! /*!
* @file Adafruit_UBX.h * @file Adafruit_UBX.h
* *
* Arduino library for parsing UBX protocol from u-blox GPS/RTK modules. * Arduino library for parsing UBX protocol from u-blox GPS/RTK modules.
* *
* This library can use any Stream object as input (UART, DDC, or other). * This library can use any Stream object as input (UART, DDC, or other).
* *
* Adafruit invests time and resources providing this open source code, * Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing * please support Adafruit and open-source hardware by purchasing
* products from Adafruit! * products from Adafruit!
* *
* Written by Limor Fried/Ladyada for Adafruit Industries. * Written by Limor Fried/Ladyada for Adafruit Industries.
* *
* MIT license, all text here must be included in any redistribution. * MIT license, all text here must be included in any redistribution.
*/ */
#ifndef ADAFRUIT_UBX_H #ifndef ADAFRUIT_UBX_H
#define ADAFRUIT_UBX_H #define ADAFRUIT_UBX_H
#include "Adafruit_uBlox_typedef.h"
#include <Arduino.h> #include <Arduino.h>
#include <Stream.h> #include <Stream.h>
#include "Adafruit_uBlox_typedef.h"
// UBX protocol constants // UBX protocol constants
#define UBX_SYNC_CHAR_1 0xB5 // First UBX protocol sync char (<28>) #define UBX_SYNC_CHAR_1 0xB5 // First UBX protocol sync char (<28>)
#define UBX_SYNC_CHAR_2 0x62 // Second UBX protocol sync char (b) #define UBX_SYNC_CHAR_2 0x62 // Second UBX protocol sync char (b)
// UBX ACK Message IDs // UBX ACK Message IDs
#define UBX_ACK_NAK 0x00 // Message Not Acknowledged #define UBX_ACK_NAK 0x00 // Message Not Acknowledged
#define UBX_ACK_ACK 0x01 // Message Acknowledged #define UBX_ACK_ACK 0x01 // Message Acknowledged
// Callback function type for UBX messages - defined at global scope so other classes can use it
typedef void (*UBXMessageCallback)(uint8_t msgClass, uint8_t msgId, uint16_t payloadLen, uint8_t *payload);
// Callback function type for UBX messages - defined at global scope so other
// classes can use it
typedef void (*UBXMessageCallback)(uint8_t msgClass, uint8_t msgId,
uint16_t payloadLen, uint8_t *payload);
/*! /*!
* @brief Class for parsing UBX protocol messages from u-blox GPS/RTK modules * @brief Class for parsing UBX protocol messages from u-blox GPS/RTK modules
*/ */
class Adafruit_UBX { class Adafruit_UBX {
public: public:
// Constructor // Constructor
Adafruit_UBX(Stream &stream); Adafruit_UBX(Stream &stream);
uint8_t verbose_debug = 0; // 0=off, 1=basic, 2=verbose uint8_t verbose_debug = 0; // 0=off, 1=basic, 2=verbose
// Basic methods // Basic methods
bool begin(); bool begin();
bool checkMessages(); // Message parsing
bool sendMessage(uint8_t msgClass, uint8_t msgId, uint8_t *payload, uint16_t length); // Send a UBX message
UBXSendStatus sendMessageWithAck(uint8_t msgClass, uint8_t msgId, uint8_t *payload, uint16_t length, uint16_t timeout_ms = 500);
// Configure port to use UBX protocol only (disable NMEA) bool checkMessages(); // Message parsing
UBXSendStatus setUBXOnly(UBXPortId portID, bool checkAck = true, uint16_t timeout_ms = 500); bool sendMessage(uint8_t msgClass, uint8_t msgId, uint8_t *payload,
uint16_t length); // Send a UBX message
UBXSendStatus sendMessageWithAck(uint8_t msgClass, uint8_t msgId,
uint8_t *payload, uint16_t length,
uint16_t timeout_ms = 500);
void setMessageCallback(UBXMessageCallback callback); // Set callback function // Configure port to use UBX protocol only (disable NMEA)
UBXMessageCallback onUBXMessage; // Callback for message received UBXSendStatus setUBXOnly(UBXPortId portID, bool checkAck = true,
uint16_t timeout_ms = 500);
private: void setMessageCallback(UBXMessageCallback callback); // Set callback function
Stream *_stream; // Stream interface for reading data UBXMessageCallback onUBXMessage; // Callback for message received
// Buffer for reading messages
static const uint16_t MAX_PAYLOAD_SIZE = 64; // Maximum UBX payload size
uint8_t _buffer[MAX_PAYLOAD_SIZE + 8]; // Buffer for message (header, payload, checksum)
// Parser state machine
enum ParserState {
WAIT_SYNC_1, // Waiting for first sync char (0xB5)
WAIT_SYNC_2, // Waiting for second sync char (0x62)
GET_CLASS, // Reading message class
GET_ID, // Reading message ID
GET_LENGTH_1, // Reading length LSB
GET_LENGTH_2, // Reading length MSB
GET_PAYLOAD, // Reading payload
GET_CHECKSUM_A, // Reading checksum A
GET_CHECKSUM_B // Reading checksum B
};
ParserState _parserState = WAIT_SYNC_1; // Current state of the parser
uint8_t _msgClass; // Message class of current message
uint8_t _msgId; // Message ID of current message
uint16_t _payloadLength; // Length of current message payload
uint16_t _payloadCounter; // Counter for payload bytes received
uint8_t _checksumA; // Running checksum A
uint8_t _checksumB; // Running checksum B
// Calculate checksum for a block of data
void calculateChecksum(uint8_t *buffer, uint16_t len, uint8_t &checksumA, uint8_t &checksumB);
// Reset parser state
void resetParser();
// Add to private section of Adafruit_UBX.h private:
uint8_t _lastMsgClass; // Class of last message Stream *_stream; // Stream interface for reading data
uint8_t _lastMsgId; // ID of last message
uint16_t _lastPayloadLength; // Length of last message payload // Buffer for reading messages
uint8_t _lastPayload[8]; // Buffer for small payloads (like ACK messages) static const uint16_t MAX_PAYLOAD_SIZE = 64; // Maximum UBX payload size
uint8_t _buffer[MAX_PAYLOAD_SIZE +
8]; // Buffer for message (header, payload, checksum)
// Parser state machine
enum ParserState {
WAIT_SYNC_1, // Waiting for first sync char (0xB5)
WAIT_SYNC_2, // Waiting for second sync char (0x62)
GET_CLASS, // Reading message class
GET_ID, // Reading message ID
GET_LENGTH_1, // Reading length LSB
GET_LENGTH_2, // Reading length MSB
GET_PAYLOAD, // Reading payload
GET_CHECKSUM_A, // Reading checksum A
GET_CHECKSUM_B // Reading checksum B
};
ParserState _parserState = WAIT_SYNC_1; // Current state of the parser
uint8_t _msgClass; // Message class of current message
uint8_t _msgId; // Message ID of current message
uint16_t _payloadLength; // Length of current message payload
uint16_t _payloadCounter; // Counter for payload bytes received
uint8_t _checksumA; // Running checksum A
uint8_t _checksumB; // Running checksum B
// Calculate checksum for a block of data
void calculateChecksum(uint8_t *buffer, uint16_t len, uint8_t &checksumA,
uint8_t &checksumB);
// Reset parser state
void resetParser();
// Add to private section of Adafruit_UBX.h
uint8_t _lastMsgClass; // Class of last message
uint8_t _lastMsgId; // ID of last message
uint16_t _lastPayloadLength; // Length of last message payload
uint8_t _lastPayload[8]; // Buffer for small payloads (like ACK messages)
}; };
#endif // ADAFRUIT_UBX_H #endif // ADAFRUIT_UBX_H

View file

@ -1,26 +1,26 @@
/*! /*!
* @file Adafruit_UBloxDDC.cpp * @file Adafruit_UBloxDDC.cpp
* *
* @mainpage Arduino library for u-blox GPS/RTK modules over DDC (I2C) * @mainpage Arduino library for u-blox GPS/RTK modules over DDC (I2C)
* *
* @section intro_sec Introduction * @section intro_sec Introduction
* *
* This is a library for the u-blox GPS/RTK modules using I2C interface (DDC) * This is a library for the u-blox GPS/RTK modules using I2C interface (DDC)
* *
* Designed specifically to work with u-blox GPS/RTK modules * Designed specifically to work with u-blox GPS/RTK modules
* like NEO-M8P, ZED-F9P, etc. * like NEO-M8P, ZED-F9P, etc.
* *
* @section dependencies Dependencies * @section dependencies Dependencies
* *
* This library depends on: * This library depends on:
* <a href="https://github.com/adafruit/Adafruit_BusIO">Adafruit_BusIO</a> * <a href="https://github.com/adafruit/Adafruit_BusIO">Adafruit_BusIO</a>
* *
* @section author Author * @section author Author
* *
* Written by Limor Fried/Ladyada for Adafruit Industries. * Written by Limor Fried/Ladyada for Adafruit Industries.
* *
* @section license License * @section license License
* *
* MIT license, all text above must be included in any redistribution * MIT license, all text above must be included in any redistribution
*/ */
@ -50,9 +50,7 @@ Adafruit_UBloxDDC::~Adafruit_UBloxDDC() {
* @brief Initializes the GPS module and I2C interface * @brief Initializes the GPS module and I2C interface
* @return True if GPS module responds, false on any failure * @return True if GPS module responds, false on any failure
*/ */
bool Adafruit_UBloxDDC::begin() { bool Adafruit_UBloxDDC::begin() { return _i2cDevice->begin(); }
return _i2cDevice->begin();
}
/*! /*!
* @brief Gets the number of bytes available for reading * @brief Gets the number of bytes available for reading
@ -60,17 +58,18 @@ bool Adafruit_UBloxDDC::begin() {
*/ */
int Adafruit_UBloxDDC::available() { int Adafruit_UBloxDDC::available() {
uint8_t buffer[2]; uint8_t buffer[2];
// Create a register for reading bytes available // Create a register for reading bytes available
Adafruit_BusIO_Register bytesAvailableReg = Adafruit_BusIO_Register(_i2cDevice, REG_BYTES_AVAILABLE_MSB, 2); Adafruit_BusIO_Register bytesAvailableReg =
Adafruit_BusIO_Register(_i2cDevice, REG_BYTES_AVAILABLE_MSB, 2);
if (!bytesAvailableReg.read(buffer, 2)) { if (!bytesAvailableReg.read(buffer, 2)) {
return 0; return 0;
} }
uint16_t bytesAvailable = (uint16_t)buffer[0] << 8; uint16_t bytesAvailable = (uint16_t)buffer[0] << 8;
bytesAvailable |= buffer[1]; bytesAvailable |= buffer[1];
return bytesAvailable; return bytesAvailable;
} }
@ -84,16 +83,17 @@ int Adafruit_UBloxDDC::read() {
_hasPeeked = false; _hasPeeked = false;
return _lastByte; return _lastByte;
} }
uint8_t value; uint8_t value;
// Create a register for the data stream // Create a register for the data stream
Adafruit_BusIO_Register dataStreamReg = Adafruit_BusIO_Register(_i2cDevice, REG_DATA_STREAM, 1); Adafruit_BusIO_Register dataStreamReg =
Adafruit_BusIO_Register(_i2cDevice, REG_DATA_STREAM, 1);
if (!dataStreamReg.read(&value, 1)) { if (!dataStreamReg.read(&value, 1)) {
return -1; return -1;
} }
return value; return value;
} }
@ -106,13 +106,13 @@ int Adafruit_UBloxDDC::peek() {
if (_hasPeeked) { if (_hasPeeked) {
return _lastByte; return _lastByte;
} }
// Otherwise, read a byte and store it // Otherwise, read a byte and store it
_lastByte = read(); _lastByte = read();
if (_lastByte != -1) { if (_lastByte != -1) {
_hasPeeked = true; _hasPeeked = true;
} }
return _lastByte; return _lastByte;
} }
@ -139,7 +139,7 @@ size_t Adafruit_UBloxDDC::write(const uint8_t *buffer, size_t size) {
// Single-byte writes aren't supported // Single-byte writes aren't supported
return 0; return 0;
} }
// Use Adafruit_BusIO to handle the I2C transaction // Use Adafruit_BusIO to handle the I2C transaction
if (_i2cDevice->write(buffer, size)) { if (_i2cDevice->write(buffer, size)) {
return size; return size;
@ -153,42 +153,43 @@ size_t Adafruit_UBloxDDC::write(const uint8_t *buffer, size_t size) {
* @param length Maximum number of bytes to read * @param length Maximum number of bytes to read
* @return Number of bytes actually read, which may be less than requested * @return Number of bytes actually read, which may be less than requested
*/ */
uint16_t Adafruit_UBloxDDC::readBytes(uint8_t* buffer, uint16_t length) { uint16_t Adafruit_UBloxDDC::readBytes(uint8_t *buffer, uint16_t length) {
if (buffer == nullptr || length == 0) { if (buffer == nullptr || length == 0) {
return 0; return 0;
} }
uint16_t bytesRead = 0; uint16_t bytesRead = 0;
uint16_t bytesAvailable = available(); uint16_t bytesAvailable = available();
// Don't try to read more bytes than are available // Don't try to read more bytes than are available
length = min(length, bytesAvailable); length = min(length, bytesAvailable);
// Handle any peeked byte first // Handle any peeked byte first
if (_hasPeeked && length > 0) { if (_hasPeeked && length > 0) {
buffer[0] = _lastByte; buffer[0] = _lastByte;
_hasPeeked = false; _hasPeeked = false;
bytesRead = 1; bytesRead = 1;
} }
if (bytesRead >= length) { if (bytesRead >= length) {
return bytesRead; return bytesRead;
} }
// Create a register for the data stream // Create a register for the data stream
Adafruit_BusIO_Register dataStreamReg = Adafruit_BusIO_Register(_i2cDevice, REG_DATA_STREAM, 1); Adafruit_BusIO_Register dataStreamReg =
Adafruit_BusIO_Register(_i2cDevice, REG_DATA_STREAM, 1);
while (bytesRead < length) { while (bytesRead < length) {
// Calculate chunk size (I2C has a limit on bytes per transfer) // Calculate chunk size (I2C has a limit on bytes per transfer)
uint16_t chunkSize = min(length - bytesRead, (uint16_t)32); uint16_t chunkSize = min(length - bytesRead, (uint16_t)32);
if (!dataStreamReg.read(&buffer[bytesRead], chunkSize)) { if (!dataStreamReg.read(&buffer[bytesRead], chunkSize)) {
break; break;
} }
bytesRead += chunkSize; bytesRead += chunkSize;
} }
return bytesRead; return bytesRead;
} }
@ -198,13 +199,13 @@ uint16_t Adafruit_UBloxDDC::readBytes(uint8_t* buffer, uint16_t length) {
* @param maxLength Maximum length of buffer * @param maxLength Maximum length of buffer
* @return Number of bytes read into the buffer * @return Number of bytes read into the buffer
*/ */
uint16_t Adafruit_UBloxDDC::readMessage(uint8_t* buffer, uint16_t maxLength) { uint16_t Adafruit_UBloxDDC::readMessage(uint8_t *buffer, uint16_t maxLength) {
uint16_t bytesAvailable = available(); uint16_t bytesAvailable = available();
if (bytesAvailable == 0) { if (bytesAvailable == 0) {
return 0; return 0;
} }
// Limit to buffer size // Limit to buffer size
uint16_t bytesToRead = min(bytesAvailable, maxLength); uint16_t bytesToRead = min(bytesAvailable, maxLength);
return readBytes(buffer, bytesToRead); return readBytes(buffer, bytesToRead);
@ -215,8 +216,7 @@ uint16_t Adafruit_UBloxDDC::readMessage(uint8_t* buffer, uint16_t maxLength) {
* @param messageLength Pointer to variable to store message length * @param messageLength Pointer to variable to store message length
* @return Pointer to internal buffer containing the message * @return Pointer to internal buffer containing the message
*/ */
uint8_t* Adafruit_UBloxDDC::readMessage(uint16_t* messageLength) { uint8_t *Adafruit_UBloxDDC::readMessage(uint16_t *messageLength) {
*messageLength = readMessage(_buffer, MAX_BUFFER_SIZE); *messageLength = readMessage(_buffer, MAX_BUFFER_SIZE);
return _buffer; return _buffer;
} }

View file

@ -1,68 +1,72 @@
/*! /*!
* @file Adafruit_UBloxDDC.h * @file Adafruit_UBloxDDC.h
* *
* Arduino library for interfacing with u-blox GPS/RTK modules over I2C (DDC). * Arduino library for interfacing with u-blox GPS/RTK modules over I2C (DDC).
* *
* This library implements the Stream interface, allowing it to be used with * This library implements the Stream interface, allowing it to be used with
* existing GPS parsing libraries like TinyGPS++. * existing GPS parsing libraries like TinyGPS++.
* *
* Adafruit invests time and resources providing this open source code, * Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing * please support Adafruit and open-source hardware by purchasing
* products from Adafruit! * products from Adafruit!
* *
* Written by Limor Fried/Ladyada for Adafruit Industries. * Written by Limor Fried/Ladyada for Adafruit Industries.
* *
* MIT license, all text here must be included in any redistribution. * MIT license, all text here must be included in any redistribution.
*/ */
#ifndef ADAFRUIT_UBLOXDDC_H #ifndef ADAFRUIT_UBLOXDDC_H
#define ADAFRUIT_UBLOXDDC_H #define ADAFRUIT_UBLOXDDC_H
#include <Arduino.h>
#include <Stream.h>
#include <Adafruit_BusIO_Register.h> #include <Adafruit_BusIO_Register.h>
#include <Adafruit_I2CDevice.h> #include <Adafruit_I2CDevice.h>
#include <Arduino.h>
#include <Stream.h>
/*! /*!
* @brief Arduino library for interfacing with u-blox GPS/RTK modules over I2C * @brief Arduino library for interfacing with u-blox GPS/RTK modules over I2C
*/ */
class Adafruit_UBloxDDC : public Stream { class Adafruit_UBloxDDC : public Stream {
private: private:
Adafruit_I2CDevice *_i2cDevice; ///< Underlying I2C device Adafruit_I2CDevice *_i2cDevice; ///< Underlying I2C device
// Register addresses
static const uint8_t REG_DATA_STREAM = 0xFF; ///< Register for reading data stream
static const uint8_t REG_BYTES_AVAILABLE_MSB = 0xFD; ///< MSB of bytes available
static const uint8_t REG_BYTES_AVAILABLE_LSB = 0xFE; ///< LSB of bytes available
// Buffer for reading messages
static const uint16_t MAX_BUFFER_SIZE = 128; ///< Maximum buffer size for messages
uint8_t _buffer[MAX_BUFFER_SIZE]; ///< Internal buffer for messages
// Last byte read for peek() implementation
int _lastByte = -1; ///< Last byte read by peek()
bool _hasPeeked = false; ///< Indicates if we have a peeked byte waiting
public: // Register addresses
// Constructor & destructor static const uint8_t REG_DATA_STREAM =
Adafruit_UBloxDDC(uint8_t address = 0x42, TwoWire *wire = &Wire); 0xFF; ///< Register for reading data stream
~Adafruit_UBloxDDC(); static const uint8_t REG_BYTES_AVAILABLE_MSB =
0xFD; ///< MSB of bytes available
// Basic methods static const uint8_t REG_BYTES_AVAILABLE_LSB =
bool begin(); 0xFE; ///< LSB of bytes available
// Stream interface implementation // Buffer for reading messages
virtual int available() override; static const uint16_t MAX_BUFFER_SIZE =
virtual int read() override; 128; ///< Maximum buffer size for messages
virtual int peek() override; uint8_t _buffer[MAX_BUFFER_SIZE]; ///< Internal buffer for messages
// Stream interface implementation
virtual size_t write(uint8_t) override; // Last byte read for peek() implementation
virtual size_t write(const uint8_t *buffer, size_t size) override; int _lastByte = -1; ///< Last byte read by peek()
bool _hasPeeked = false; ///< Indicates if we have a peeked byte waiting
// Additional methods
uint16_t readBytes(uint8_t* buffer, uint16_t length); public:
uint16_t readMessage(uint8_t* buffer, uint16_t maxLength); // Constructor & destructor
uint8_t* readMessage(uint16_t* messageLength); Adafruit_UBloxDDC(uint8_t address = 0x42, TwoWire *wire = &Wire);
~Adafruit_UBloxDDC();
// Basic methods
bool begin();
// Stream interface implementation
virtual int available() override;
virtual int read() override;
virtual int peek() override;
// Stream interface implementation
virtual size_t write(uint8_t) override;
virtual size_t write(const uint8_t *buffer, size_t size) override;
// Additional methods
uint16_t readBytes(uint8_t *buffer, uint16_t length);
uint16_t readMessage(uint8_t *buffer, uint16_t maxLength);
uint8_t *readMessage(uint16_t *messageLength);
}; };
#endif // ADAFRUIT_UBLOXDDC_H #endif // ADAFRUIT_UBLOXDDC_H

View file

@ -1,14 +1,14 @@
/*! /*!
* @file Adafruit_uBlox_Ubx_Messages.h * @file Adafruit_uBlox_Ubx_Messages.h
* *
* Pre-built UBX message payloads for common tasks * Pre-built UBX message payloads for common tasks
* *
* Adafruit invests time and resources providing this open source code, * Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing * please support Adafruit and open-source hardware by purchasing
* products from Adafruit! * products from Adafruit!
* *
* Written by Brent Rubell for Adafruit Industries. * Written by Brent Rubell for Adafruit Industries.
* *
* MIT license, all text here must be included in any redistribution. * MIT license, all text here must be included in any redistribution.
*/ */
@ -18,28 +18,41 @@
#include <Arduino.h> #include <Arduino.h>
// NMEA Message Configuration Commands (CFG-MSG) // NMEA Message Configuration Commands (CFG-MSG)
// Format: {msgClass, msgID, rate_I2C, rate_UART1, rate_UART2, rate_USB, rate_SPI, reserved} // Format: {msgClass, msgID, rate_I2C, rate_UART1, rate_UART2, rate_USB,
// rate_SPI, reserved}
// Enable specific NMEA message sentences to output on the DDC interface // Enable specific NMEA message sentences to output on the DDC interface
static uint8_t UBX_CFG_MSG_NMEA_GGA_ENABLE[] = {0xF0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; static uint8_t UBX_CFG_MSG_NMEA_GGA_ENABLE[] = {0xF0, 0x00, 0x01, 0x00,
static uint8_t UBX_CFG_MSG_NMEA_GLL_ENABLE[] = {0xF0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; 0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_GSA_ENABLE[] = {0xF0, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; static uint8_t UBX_CFG_MSG_NMEA_GLL_ENABLE[] = {0xF0, 0x01, 0x01, 0x00,
static uint8_t UBX_CFG_MSG_NMEA_GSV_ENABLE[] = {0xF0, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; 0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_RMC_ENABLE[] = {0xF0, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; static uint8_t UBX_CFG_MSG_NMEA_GSA_ENABLE[] = {0xF0, 0x02, 0x01, 0x00,
static uint8_t UBX_CFG_MSG_NMEA_VTG_ENABLE[] = {0xF0, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; 0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_GSV_ENABLE[] = {0xF0, 0x03, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_RMC_ENABLE[] = {0xF0, 0x04, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_VTG_ENABLE[] = {0xF0, 0x05, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00};
// Disable specific NMEA message sentences from outputting on the DDC interface // Disable specific NMEA message sentences from outputting on the DDC interface
static uint8_t UBX_CFG_MSG_NMEA_GGA_DISABLE[] = {0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static uint8_t UBX_CFG_MSG_NMEA_GGA_DISABLE[] = {0xF0, 0x00, 0x00, 0x00,
static uint8_t UBX_CFG_MSG_NMEA_GLL_DISABLE[] = {0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_GSA_DISABLE[] = {0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static uint8_t UBX_CFG_MSG_NMEA_GLL_DISABLE[] = {0xF0, 0x01, 0x00, 0x00,
static uint8_t UBX_CFG_MSG_NMEA_GSV_DISABLE[] = {0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_RMC_DISABLE[] = {0xF0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static uint8_t UBX_CFG_MSG_NMEA_GSA_DISABLE[] = {0xF0, 0x02, 0x00, 0x00,
static uint8_t UBX_CFG_MSG_NMEA_VTG_DISABLE[] = {0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_GSV_DISABLE[] = {0xF0, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_RMC_DISABLE[] = {0xF0, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_VTG_DISABLE[] = {0xF0, 0x05, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
// Navigation Rate Configuration Commands (CFG-RATE) // Navigation Rate Configuration Commands (CFG-RATE)
// Format: {measRate_ms (2 bytes), navRate, timeRef} // Format: {measRate_ms (2 bytes), navRate, timeRef}
static uint8_t UBX_CFG_RATE_1HZ[] = {0xE8, 0x03, 0x01, 0x00, 0x01, 0x00}; static uint8_t UBX_CFG_RATE_1HZ[] = {0xE8, 0x03, 0x01, 0x00, 0x01, 0x00};
static uint8_t UBX_CFG_RATE_2HZ[] = {0xF4, 0x01, 0x01, 0x00, 0x01, 0x00}; static uint8_t UBX_CFG_RATE_2HZ[] = {0xF4, 0x01, 0x01, 0x00, 0x01, 0x00};
static uint8_t UBX_CFG_RATE_5HZ[] = {0xC8, 0x00, 0x01, 0x00, 0x01, 0x00}; static uint8_t UBX_CFG_RATE_5HZ[] = {0xC8, 0x00, 0x01, 0x00, 0x01, 0x00};
static uint8_t UBX_CFG_RATE_10HZ[] = {0x64, 0x00, 0x01, 0x00, 0x01, 0x00}; static uint8_t UBX_CFG_RATE_10HZ[] = {0x64, 0x00, 0x01, 0x00, 0x01, 0x00};
#endif // ADAFRUIT_UBLOX_UBX_MESSAGES #endif // ADAFRUIT_UBLOX_UBX_MESSAGES

View file

@ -1,14 +1,14 @@
/*! /*!
* @file Adafruit_uBlox_typedef.h * @file Adafruit_uBlox_typedef.h
* *
* Type definitions for u-blox GPS/RTK module messages * Type definitions for u-blox GPS/RTK module messages
* *
* Adafruit invests time and resources providing this open source code, * Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing * please support Adafruit and open-source hardware by purchasing
* products from Adafruit! * products from Adafruit!
* *
* Written by Limor Fried/Ladyada for Adafruit Industries. * Written by Limor Fried/Ladyada for Adafruit Industries.
* *
* MIT license, all text here must be included in any redistribution. * MIT license, all text here must be included in any redistribution.
*/ */
@ -19,41 +19,41 @@
// UBX Message Classes // UBX Message Classes
typedef enum { typedef enum {
UBX_CLASS_NAV = 0x01, // Navigation Results UBX_CLASS_NAV = 0x01, // Navigation Results
UBX_CLASS_RXM = 0x02, // Receiver Manager Messages UBX_CLASS_RXM = 0x02, // Receiver Manager Messages
UBX_CLASS_INF = 0x04, // Information Messages UBX_CLASS_INF = 0x04, // Information Messages
UBX_CLASS_ACK = 0x05, // Acknowledgements UBX_CLASS_ACK = 0x05, // Acknowledgements
UBX_CLASS_CFG = 0x06, // Configuration UBX_CLASS_CFG = 0x06, // Configuration
UBX_CLASS_UPD = 0x09, // Firmware Update UBX_CLASS_UPD = 0x09, // Firmware Update
UBX_CLASS_MON = 0x0A, // Monitoring UBX_CLASS_MON = 0x0A, // Monitoring
UBX_CLASS_AID = 0x0B, // AssistNow Aiding UBX_CLASS_AID = 0x0B, // AssistNow Aiding
UBX_CLASS_TIM = 0x0D, // Timing UBX_CLASS_TIM = 0x0D, // Timing
UBX_CLASS_ESF = 0x10, // External Sensor Fusion UBX_CLASS_ESF = 0x10, // External Sensor Fusion
UBX_CLASS_MGA = 0x13, // Multiple GNSS Assistance UBX_CLASS_MGA = 0x13, // Multiple GNSS Assistance
UBX_CLASS_LOG = 0x21, // Logging UBX_CLASS_LOG = 0x21, // Logging
UBX_CLASS_SEC = 0x27, // Security UBX_CLASS_SEC = 0x27, // Security
UBX_CLASS_HNR = 0x28, // High Rate Navigation UBX_CLASS_HNR = 0x28, // High Rate Navigation
UBX_CLASS_NMEA = 0xF0 // NMEA Standard Messages UBX_CLASS_NMEA = 0xF0 // NMEA Standard Messages
} UBXMessageClass; } UBXMessageClass;
// UBX CFG Message IDs // UBX CFG Message IDs
typedef enum { typedef enum {
UBX_CFG_PRT = 0x00, // Port Configuration UBX_CFG_PRT = 0x00, // Port Configuration
UBX_CFG_MSG = 0x01, // Message Configuration UBX_CFG_MSG = 0x01, // Message Configuration
UBX_CFG_RST = 0x04, // Reset Receiver UBX_CFG_RST = 0x04, // Reset Receiver
UBX_CFG_RATE = 0x08, // Navigation/Measurement Rate Settings UBX_CFG_RATE = 0x08, // Navigation/Measurement Rate Settings
UBX_CFG_CFG = 0x09, // Clear, Save, and Load Configurations UBX_CFG_CFG = 0x09, // Clear, Save, and Load Configurations
UBX_CFG_NAVX5 = 0x23, // Navigation Engine Settings UBX_CFG_NAVX5 = 0x23, // Navigation Engine Settings
UBX_CFG_GNSS = 0x3E, // GNSS Configuration UBX_CFG_GNSS = 0x3E, // GNSS Configuration
UBX_CFG_PMS = 0x86 // Power Mode Setup UBX_CFG_PMS = 0x86 // Power Mode Setup
} UBXCfgMessageId; } UBXCfgMessageId;
// Return values for functions that wait for acknowledgment // Return values for functions that wait for acknowledgment
typedef enum { typedef enum {
UBX_SEND_SUCCESS = 0, // Message was acknowledged (ACK) UBX_SEND_SUCCESS = 0, // Message was acknowledged (ACK)
UBX_SEND_NAK, // Message was not acknowledged (NAK) UBX_SEND_NAK, // Message was not acknowledged (NAK)
UBX_SEND_FAIL, // Failed to send the message UBX_SEND_FAIL, // Failed to send the message
UBX_SEND_TIMEOUT // Timed out waiting for ACK/NAK UBX_SEND_TIMEOUT // Timed out waiting for ACK/NAK
} UBXSendStatus; } UBXSendStatus;
// Port ID enum for different interfaces // Port ID enum for different interfaces
@ -82,20 +82,21 @@ typedef enum {
} UBXUARTMode; } UBXUARTMode;
// Protocol flags for inProtoMask and outProtoMask // Protocol flags for inProtoMask and outProtoMask
#define UBX_PROTOCOL_UBX 0x0001 // UBX protocol #define UBX_PROTOCOL_UBX 0x0001 // UBX protocol
#define UBX_PROTOCOL_NMEA 0x0002 // NMEA protocol #define UBX_PROTOCOL_NMEA 0x0002 // NMEA protocol
#define UBX_PROTOCOL_RTCM 0x0004 // RTCM2 protocol (only for inProtoMask) #define UBX_PROTOCOL_RTCM 0x0004 // RTCM2 protocol (only for inProtoMask)
#define UBX_PROTOCOL_RTCM3 0x0020 // RTCM3 protocol #define UBX_PROTOCOL_RTCM3 0x0020 // RTCM3 protocol
// CFG-PRT (Port Configuration) Message // CFG-PRT (Port Configuration) Message
// Total size: 20 bytes // Total size: 20 bytes
typedef union { typedef union {
struct { struct {
uint8_t portID; // Port identifier (0=DDC/I2C, 1=UART1, 2=UART2, 3=USB, 4=SPI) uint8_t
uint8_t reserved1; // Reserved portID; // Port identifier (0=DDC/I2C, 1=UART1, 2=UART2, 3=USB, 4=SPI)
uint16_t txReady; // TX ready PIN configuration uint8_t reserved1; // Reserved
uint32_t mode; // UART mode (bit field) or Reserved for non-UART ports uint16_t txReady; // TX ready PIN configuration
uint32_t baudRate; // Baudrate in bits/second (UART only) uint32_t mode; // UART mode (bit field) or Reserved for non-UART ports
uint32_t baudRate; // Baudrate in bits/second (UART only)
uint16_t inProtoMask; // Input protocol mask uint16_t inProtoMask; // Input protocol mask
uint16_t outProtoMask; // Output protocol mask uint16_t outProtoMask; // Output protocol mask
uint16_t flags; // Flags bit field uint16_t flags; // Flags bit field