From f1f7d0cd07ebd4df15b22696d312fe33a7771179 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Tue, 13 Feb 2024 11:54:57 -0800 Subject: [PATCH 01/52] add WIP gps drivers --- gps/gps.cpp | 91 ++++++++++++++++++++++++++++++++++++++ gps/gps.h | 33 ++++++++++++++ gps/ubxHelpers.cpp | 108 +++++++++++++++++++++++++++++++++++++++++++++ gps/ubxHelpers.h | 11 +++++ gps/ubxMessages.h | 99 +++++++++++++++++++++++++++++++++++++++++ gps/ubxPacket.cpp | 81 ++++++++++++++++++++++++++++++++++ gps/ubxPacket.h | 33 ++++++++++++++ 7 files changed, 456 insertions(+) create mode 100644 gps/gps.cpp create mode 100644 gps/gps.h create mode 100644 gps/ubxHelpers.cpp create mode 100644 gps/ubxHelpers.h create mode 100644 gps/ubxMessages.h create mode 100644 gps/ubxPacket.cpp create mode 100644 gps/ubxPacket.h diff --git a/gps/gps.cpp b/gps/gps.cpp new file mode 100644 index 0000000..56e700e --- /dev/null +++ b/gps/gps.cpp @@ -0,0 +1,91 @@ +#include "ubxHelpers.h" +#include "ubxPacket.h" +#include "ubxMessages.h" +#include "gps.h" + +#define I2C_BUFFER_SIZE 1024 + +GPS::GPS() { + packetReader = UBXPacketReader(); + state = GPSState::REQUEST_NOT_SENT; +} + +const GPSState GPS::getState() { + return state; +} + +const GPSPollResult GPS::pollUpdate(I2C_HandleTypeDef* i2c) { + if(state == GPSState::REQUEST_NOT_SENT) { + uint8_t message[4] = {0x01, 0x06, 0x00, 0x00}; + sendUBX(message, 4, &hi2c3); + state = GPSState::POLLING_RESPONSE; + } + + if(state == GPSState::POLLING_RESPONSE) { + uint8_t lenBytes[2]; + uint16_t dataLen = 0; + uint8_t buffer[I2C_BUFFER_SIZE]; + + HAL_StatusTypeDef dataLenReadStatus = HAL_I2C_Mem_Read(i2c, 0x42 << 1, 0xFD, 1, lenBytes, 2, 100); + if(dataLenReadStatus != HAL_OK) { + return GPSPollResult::DATA_LEN_POLL_FAILED; + } + + dataLen = lenBytes[0] << 8 | lenBytes[1]; + if(dataLen==0) { + return GPSPollResult::NO_DATA; + } + + if(dataLen > I2C_BUFFER_SIZE) { + dataLen = I2C_BUFFER_SIZE; + } + HAL_StatusTypeDef rcvStatus = HAL_I2C_Master_Receive(i2c, 0x42 << 1, buffer, dataLen, 100); + if(rcvStatus != HAL_OK) { + return GPSPollResult::DATA_RECEIVE_I2C_FAILED; + } + + if(packetReader.isInProgress()) { + for(uint16_t i = 0; i + +enum class GPSState { + REQUEST_NOT_SENT, + POLLING_RESPONSE, + RESPONSE_READY +}; + +enum class GPSPollResult { + POLL_OK, + NO_DATA, + DATA_LEN_POLL_FAILED, + DATA_RECEIVE_I2C_FAILED, + DATA_RECEIVE_CHECKSUM_FAILED +}; + +class GPS { + public: + GPS(); + const GPSState getState(); + const GPSPollResult pollUpdate(I2C_HandleTypeDef* i2c); + const UBX_NAV_SOL_PAYLOAD getSolution(); + void reset(); + + private: + UBXPacketReader packetReader; + GPSState state; +}; + diff --git a/gps/ubxHelpers.cpp b/gps/ubxHelpers.cpp new file mode 100644 index 0000000..807a19e --- /dev/null +++ b/gps/ubxHelpers.cpp @@ -0,0 +1,108 @@ +#include "ubxHelpers.h" +#include "ubxPacket.h" +#include "ubxMessages.h" + +#define I2C_BUFFER_SIZE 1024 + +static uint8_t magicBytes[2] = {0xB5, 0x62}; + +bool sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c) { + uint8_t CK_A{0}, CK_B{0}; + + HAL_StatusTypeDef status; + status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, magicBytes, 2, 100); + if (status != HAL_OK) { + return false; + } + + for(uint16_t i=0;i +bool pollUBXPacket(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c, PayloadType* payloadBuffer) { + if(!sendUBX(message, len, i2c)) { + return false; + } + + uint8_t lenBytes[2]; + uint16_t dataLen = 0; + uint8_t buffer[I2C_BUFFER_SIZE]; + + while(dataLen<1) { + HAL_StatusTypeDef dataLenReadStatus = HAL_I2C_Mem_Read(i2c, 0x42 << 1, 0xFD, 1, lenBytes, 2, 100); + if(dataLenReadStatus != HAL_OK) { + return false; + } + + dataLen = lenBytes[0] << 8 | lenBytes[1]; + if(dataLen==0) { + HAL_Delay(100); + continue; + } + + if(dataLen > I2C_BUFFER_SIZE) { + dataLen = I2C_BUFFER_SIZE; + } + HAL_StatusTypeDef rcvStatus = HAL_I2C_Master_Receive(i2c, 0x42 << 1, buffer, dataLen, 100); + if(rcvStatus != HAL_OK) { + return false; + } + } + + for(uint16_t i = 0; i + +#pragma pack(push, 1) +struct UBX_NAV_PVT_PAYLOAD { + uint32_t iTOW; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t min; + uint8_t sec; + uint8_t valid; + uint32_t tAcc; + int32_t nano; + uint8_t fixType; + uint8_t flags; + uint8_t flags2; + uint8_t numSV; + int32_t lon; + int32_t lat; + int32_t height; + int32_t hMSL; + uint32_t hAcc; + uint32_t vAcc; + int32_t velN; + int32_t velE; + int32_t velD; + int32_t gSpeed; + int32_t headMot; + uint32_t sAcc; + uint32_t headAcc; + uint16_t pDOP; + uint8_t reserved1[6]; + int32_t headVeh; + int16_t magDec; + uint16_t magAcc; +}; +#pragma pack(pop) + +enum class GPSFixType { + NO_FIX, + DEAD_RECKONING, + FIX_2D, + FIX_3D, + GNSS_AND_DEAD_RECKONING, + TIME_ONLY_FIX +}; + +#pragma pack(push, 1) +struct UBX_NAV_STATUS_PAYLOAD { + uint32_t iTOW; + uint8_t gpsFix; // GPSFixType, but IDK if the enum will pack to 1 byte consistently + uint8_t flags; + uint8_t fixStat; + uint8_t flags2; + uint32_t ttff; + uint32_t msss; +}; +#pragma pack(pop) + +#pragma pack(push, 1) +struct UBX_NAV_SAT_PAYLOAD { + uint32_t iTOW; + uint8_t version; + uint8_t numSvs; + uint8_t reserved1[2]; + struct { + uint8_t gnssId; + uint8_t svId; + uint8_t cno; + int8_t elev; + int16_t azim; + int16_t prRes; + } sats[16]; +}; +#pragma pack(pop) + +#pragma pack(push, 1) +struct UBX_NAV_SOL_PAYLOAD { // 0x01 0x06 + uint32_t iTOW; + int32_t fTOW; + int16_t week; + uint8_t gpsFix; // GPSFixType, but IDK if the enum will pack to 1 byte consistently + uint8_t flags; + int32_t ecefX; + int32_t ecefY; + int32_t ecefZ; + uint32_t pAcc; + int32_t ecefVX; + int32_t ecefVY; + int32_t ecefVZ; + uint32_t sAcc; + uint16_t pDOP; + uint8_t reserved1; + uint8_t numSV; + uint8_t reserved2[4]; +}; +#pragma pack(pop) \ No newline at end of file diff --git a/gps/ubxPacket.cpp b/gps/ubxPacket.cpp new file mode 100644 index 0000000..adb6919 --- /dev/null +++ b/gps/ubxPacket.cpp @@ -0,0 +1,81 @@ +#include "ubxPacket.h" + +// make a ubxPacket class that has a method to update one byte at a time +UBXPacketReader::UBXPacketReader() { + payloadLength = 0; + packetIndex = 0; + ckA = 0; + ckB = 0; + complete = false; + inProgress = false; +} + +UBXPacketUpdateResult UBXPacketReader::update(uint8_t newByte) { + if(complete) { + return UBXPacketUpdateResult::PACKET_ALREADY_COMPLETE; + } + inProgress = true; + int currentPacketIndex = packetIndex; + packetIndex++; + if(currentPacketIndex==0) { + messageClass = newByte; + } else if(currentPacketIndex==1) { + messageId = newByte; + } else if(currentPacketIndex==2) { + payloadLength = newByte; + } else if(currentPacketIndex==3) { + payloadLength |= (uint16_t)newByte << 8; + } else if(currentPacketIndex>=4+payloadLength && currentPacketIndex<6+payloadLength) { + if(currentPacketIndex==4+payloadLength) { + if(ckA != newByte) { + return UBXPacketUpdateResult::CHECKSUM_FAILED; + } + } else { + if(ckB != newByte) { + return UBXPacketUpdateResult::CHECKSUM_FAILED; + } else { + complete = true; + inProgress = false; + } + } + return UBXPacketUpdateResult::UPDATE_OK; // return early to avoid updating checksums + } else { + payload[currentPacketIndex-4] = newByte; + } + ckA = ckA + newByte; + ckB = ckB + ckA; + return UBXPacketUpdateResult::UPDATE_OK; +} + +void* UBXPacketReader::getPayload() { + return (void*)payload; +} + +uint8_t UBXPacketReader::getPayloadLength() { + return payloadLength; +} + +uint8_t UBXPacketReader::getMessageClass() { + return messageClass; +} + +uint8_t UBXPacketReader::getMessageId() { + return messageId; +} + +bool UBXPacketReader::isComplete() { + return complete; +} + +bool UBXPacketReader::isInProgress() { + return inProgress; +} + +void UBXPacketReader::reset() { + payloadLength = 0; + packetIndex = 0; + ckA = 0; + ckB = 0; + complete = false; + inProgress = false; +} diff --git a/gps/ubxPacket.h b/gps/ubxPacket.h new file mode 100644 index 0000000..98408ad --- /dev/null +++ b/gps/ubxPacket.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +enum class UBXPacketUpdateResult { + UPDATE_OK, + CHECKSUM_FAILED, + PACKET_ALREADY_COMPLETE +}; + +class UBXPacketReader { + public: + UBXPacketReader(); + UBXPacketUpdateResult update(uint8_t byte); + bool isComplete(); + bool isInProgress(); + void* getPayload(); + uint8_t getPayloadLength(); + uint8_t getMessageClass(); + uint8_t getMessageId(); + void reset(); + + private: + uint8_t payload[512]; + uint8_t payloadLength; + uint8_t packetIndex; + uint8_t messageClass; + uint8_t messageId; + uint8_t ckA; + uint8_t ckB; + bool complete; + bool inProgress; +}; From 946f8d2ee73ba516ed4054c65b417c937ab007e3 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Tue, 13 Feb 2024 12:11:15 -0800 Subject: [PATCH 02/52] rename folder to be more specific --- {gps => gps_ubxm8_i2c}/gps.cpp | 0 {gps => gps_ubxm8_i2c}/gps.h | 0 {gps => gps_ubxm8_i2c}/ubxHelpers.cpp | 0 {gps => gps_ubxm8_i2c}/ubxHelpers.h | 0 {gps => gps_ubxm8_i2c}/ubxMessages.h | 0 {gps => gps_ubxm8_i2c}/ubxPacket.cpp | 0 {gps => gps_ubxm8_i2c}/ubxPacket.h | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename {gps => gps_ubxm8_i2c}/gps.cpp (100%) rename {gps => gps_ubxm8_i2c}/gps.h (100%) rename {gps => gps_ubxm8_i2c}/ubxHelpers.cpp (100%) rename {gps => gps_ubxm8_i2c}/ubxHelpers.h (100%) rename {gps => gps_ubxm8_i2c}/ubxMessages.h (100%) rename {gps => gps_ubxm8_i2c}/ubxPacket.cpp (100%) rename {gps => gps_ubxm8_i2c}/ubxPacket.h (100%) diff --git a/gps/gps.cpp b/gps_ubxm8_i2c/gps.cpp similarity index 100% rename from gps/gps.cpp rename to gps_ubxm8_i2c/gps.cpp diff --git a/gps/gps.h b/gps_ubxm8_i2c/gps.h similarity index 100% rename from gps/gps.h rename to gps_ubxm8_i2c/gps.h diff --git a/gps/ubxHelpers.cpp b/gps_ubxm8_i2c/ubxHelpers.cpp similarity index 100% rename from gps/ubxHelpers.cpp rename to gps_ubxm8_i2c/ubxHelpers.cpp diff --git a/gps/ubxHelpers.h b/gps_ubxm8_i2c/ubxHelpers.h similarity index 100% rename from gps/ubxHelpers.h rename to gps_ubxm8_i2c/ubxHelpers.h diff --git a/gps/ubxMessages.h b/gps_ubxm8_i2c/ubxMessages.h similarity index 100% rename from gps/ubxMessages.h rename to gps_ubxm8_i2c/ubxMessages.h diff --git a/gps/ubxPacket.cpp b/gps_ubxm8_i2c/ubxPacket.cpp similarity index 100% rename from gps/ubxPacket.cpp rename to gps_ubxm8_i2c/ubxPacket.cpp diff --git a/gps/ubxPacket.h b/gps_ubxm8_i2c/ubxPacket.h similarity index 100% rename from gps/ubxPacket.h rename to gps_ubxm8_i2c/ubxPacket.h From 8d2b2d0e3ab61e56d134fc7f267ce849fe6c2b73 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Tue, 13 Feb 2024 12:12:50 -0800 Subject: [PATCH 03/52] switch to pvt I tested the ECEF polling on EVE and it didn't work, but PVT did. --- gps_ubxm8_i2c/gps.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cpp b/gps_ubxm8_i2c/gps.cpp index 56e700e..b8de234 100644 --- a/gps_ubxm8_i2c/gps.cpp +++ b/gps_ubxm8_i2c/gps.cpp @@ -16,7 +16,7 @@ const GPSState GPS::getState() { const GPSPollResult GPS::pollUpdate(I2C_HandleTypeDef* i2c) { if(state == GPSState::REQUEST_NOT_SENT) { - uint8_t message[4] = {0x01, 0x06, 0x00, 0x00}; + uint8_t message[4] = {0x01, 0x07, 0x00, 0x00}; sendUBX(message, 4, &hi2c3); state = GPSState::POLLING_RESPONSE; } @@ -81,8 +81,8 @@ const GPSPollResult GPS::pollUpdate(I2C_HandleTypeDef* i2c) { return GPSPollResult::POLL_OK; } -const UBX_NAV_SOL_PAYLOAD GPS::getSolution() { - return *(UBX_NAV_SOL_PAYLOAD*)packetReader.getPayload(); +const UBX_NAV_PVT_PAYLOAD GPS::getSolution() { + return *(UBX_NAV_PVT_PAYLOAD*)packetReader.getPayload(); } void GPS::reset() { From 6150e71369a381058e93437a4cb1f92d942eef81 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Tue, 13 Feb 2024 12:13:14 -0800 Subject: [PATCH 04/52] remove unnecessary files --- gps_ubxm8_i2c/ubxHelpers.cpp | 75 ------------------------------------ gps_ubxm8_i2c/ubxMessages.h | 53 +------------------------ 2 files changed, 1 insertion(+), 127 deletions(-) diff --git a/gps_ubxm8_i2c/ubxHelpers.cpp b/gps_ubxm8_i2c/ubxHelpers.cpp index 807a19e..6ed266e 100644 --- a/gps_ubxm8_i2c/ubxHelpers.cpp +++ b/gps_ubxm8_i2c/ubxHelpers.cpp @@ -31,78 +31,3 @@ bool sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c) { } return true; } - -UBXPacketReader packet; - -template -bool pollUBXPacket(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c, PayloadType* payloadBuffer) { - if(!sendUBX(message, len, i2c)) { - return false; - } - - uint8_t lenBytes[2]; - uint16_t dataLen = 0; - uint8_t buffer[I2C_BUFFER_SIZE]; - - while(dataLen<1) { - HAL_StatusTypeDef dataLenReadStatus = HAL_I2C_Mem_Read(i2c, 0x42 << 1, 0xFD, 1, lenBytes, 2, 100); - if(dataLenReadStatus != HAL_OK) { - return false; - } - - dataLen = lenBytes[0] << 8 | lenBytes[1]; - if(dataLen==0) { - HAL_Delay(100); - continue; - } - - if(dataLen > I2C_BUFFER_SIZE) { - dataLen = I2C_BUFFER_SIZE; - } - HAL_StatusTypeDef rcvStatus = HAL_I2C_Master_Receive(i2c, 0x42 << 1, buffer, dataLen, 100); - if(rcvStatus != HAL_OK) { - return false; - } - } - - for(uint16_t i = 0; i Date: Tue, 13 Feb 2024 12:19:52 -0800 Subject: [PATCH 05/52] fix errors with incomplete removal of old code --- gps_ubxm8_i2c/gps.h | 2 +- gps_ubxm8_i2c/ubxHelpers.h | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index f7c03a6..8be515c 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -23,7 +23,7 @@ class GPS { GPS(); const GPSState getState(); const GPSPollResult pollUpdate(I2C_HandleTypeDef* i2c); - const UBX_NAV_SOL_PAYLOAD getSolution(); + const UBX_NAV_PVT_PAYLOAD getSolution(); void reset(); private: diff --git a/gps_ubxm8_i2c/ubxHelpers.h b/gps_ubxm8_i2c/ubxHelpers.h index c4f3f03..4d86de1 100644 --- a/gps_ubxm8_i2c/ubxHelpers.h +++ b/gps_ubxm8_i2c/ubxHelpers.h @@ -3,9 +3,3 @@ #include "ubxMessages.h" bool sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c); - -bool checkGPSFullNavInfo(UBX_NAV_PVT_PAYLOAD* pvt, I2C_HandleTypeDef* i2c); - -bool checkGPSNavStatus(UBX_NAV_STATUS_PAYLOAD* status, I2C_HandleTypeDef* i2c); - -bool checkGPSNavSatellites(UBX_NAV_SAT_PAYLOAD* sat, I2C_HandleTypeDef* i2c); \ No newline at end of file From 9a58e82225c8d62a1c1428df7968882c55c1f356 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Tue, 13 Feb 2024 23:03:24 -0800 Subject: [PATCH 06/52] move enums into class and add more specific poll results --- gps_ubxm8_i2c/gps.cpp | 34 +++++++++++++++++----------------- gps_ubxm8_i2c/gps.h | 31 ++++++++++++++++--------------- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cpp b/gps_ubxm8_i2c/gps.cpp index b8de234..681a5ad 100644 --- a/gps_ubxm8_i2c/gps.cpp +++ b/gps_ubxm8_i2c/gps.cpp @@ -7,33 +7,33 @@ GPS::GPS() { packetReader = UBXPacketReader(); - state = GPSState::REQUEST_NOT_SENT; + state = GPS::State::REQUEST_NOT_SENT; } -const GPSState GPS::getState() { +const GPS::State GPS::getState() { return state; } -const GPSPollResult GPS::pollUpdate(I2C_HandleTypeDef* i2c) { - if(state == GPSState::REQUEST_NOT_SENT) { +const GPS::PollResult GPS::pollUpdate(I2C_HandleTypeDef* i2c) { + if(state == GPS::State::REQUEST_NOT_SENT) { uint8_t message[4] = {0x01, 0x07, 0x00, 0x00}; sendUBX(message, 4, &hi2c3); - state = GPSState::POLLING_RESPONSE; + state = GPS::State::POLLING_RESPONSE; } - if(state == GPSState::POLLING_RESPONSE) { + if(state == GPS::State::POLLING_RESPONSE) { uint8_t lenBytes[2]; uint16_t dataLen = 0; uint8_t buffer[I2C_BUFFER_SIZE]; HAL_StatusTypeDef dataLenReadStatus = HAL_I2C_Mem_Read(i2c, 0x42 << 1, 0xFD, 1, lenBytes, 2, 100); if(dataLenReadStatus != HAL_OK) { - return GPSPollResult::DATA_LEN_POLL_FAILED; + return GPS::PollResult::DATA_LEN_POLL_FAILED; } dataLen = lenBytes[0] << 8 | lenBytes[1]; if(dataLen==0) { - return GPSPollResult::NO_DATA; + return GPS::PollResult::NO_DATA; } if(dataLen > I2C_BUFFER_SIZE) { @@ -41,7 +41,7 @@ const GPSPollResult GPS::pollUpdate(I2C_HandleTypeDef* i2c) { } HAL_StatusTypeDef rcvStatus = HAL_I2C_Master_Receive(i2c, 0x42 << 1, buffer, dataLen, 100); if(rcvStatus != HAL_OK) { - return GPSPollResult::DATA_RECEIVE_I2C_FAILED; + return GPS::PollResult::DATA_RECEIVE_I2C_FAILED; } if(packetReader.isInProgress()) { @@ -49,11 +49,11 @@ const GPSPollResult GPS::pollUpdate(I2C_HandleTypeDef* i2c) { UBXPacketUpdateResult res = packetReader.update(buffer[i]); if(res == UBXPacketUpdateResult::CHECKSUM_FAILED) { packetReader.reset(); - return GPSPollResult::DATA_RECEIVE_CHECKSUM_FAILED; + return GPS::PollResult::DATA_RECEIVE_CHECKSUM_FAILED; } if(packetReader.isComplete()) { - state = GPSState::RESPONSE_READY; - return GPSPollResult::POLL_OK; + state = GPS::State::RESPONSE_READY; + return GPS::PollResult::POLL_FINISHED; } } } else { @@ -64,7 +64,7 @@ const GPSPollResult GPS::pollUpdate(I2C_HandleTypeDef* i2c) { UBXPacketUpdateResult res = packetReader.update(buffer[i]); if(res != UBXPacketUpdateResult::UPDATE_OK) { packetReader.reset(); - return GPSPollResult::DATA_RECEIVE_CHECKSUM_FAILED; + return GPS::PollResult::DATA_RECEIVE_CHECKSUM_FAILED; } i++; } @@ -72,13 +72,13 @@ const GPSPollResult GPS::pollUpdate(I2C_HandleTypeDef* i2c) { } if(packetReader.isComplete()) { - state = GPSState::RESPONSE_READY; - return GPSPollResult::POLL_OK; + state = GPS::State::RESPONSE_READY; + return GPS::PollResult::POLL_FINISHED; } } } - return GPSPollResult::POLL_OK; + return GPS::PollResult::RECEIVE_IN_PROGRESS; } const UBX_NAV_PVT_PAYLOAD GPS::getSolution() { @@ -86,6 +86,6 @@ const UBX_NAV_PVT_PAYLOAD GPS::getSolution() { } void GPS::reset() { - state = GPSState::REQUEST_NOT_SENT; + state = GPS::State::REQUEST_NOT_SENT; packetReader.reset(); } \ No newline at end of file diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 8be515c..7fa5502 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -4,30 +4,31 @@ #include "ubxMessages.h" #include -enum class GPSState { - REQUEST_NOT_SENT, - POLLING_RESPONSE, - RESPONSE_READY -}; -enum class GPSPollResult { - POLL_OK, - NO_DATA, - DATA_LEN_POLL_FAILED, - DATA_RECEIVE_I2C_FAILED, - DATA_RECEIVE_CHECKSUM_FAILED -}; class GPS { public: + enum class State { + REQUEST_NOT_SENT, + POLLING_RESPONSE, + RESPONSE_READY + }; + enum class PollResult { + POLL_FINISHED, + NO_DATA, + DATA_LEN_POLL_FAILED, + DATA_RECEIVE_I2C_FAILED, + DATA_RECEIVE_CHECKSUM_FAILED, + RECEIVE_IN_PROGRESS + }; GPS(); - const GPSState getState(); - const GPSPollResult pollUpdate(I2C_HandleTypeDef* i2c); + const State getState(); + const PollResult pollUpdate(I2C_HandleTypeDef* i2c); const UBX_NAV_PVT_PAYLOAD getSolution(); void reset(); private: UBXPacketReader packetReader; - GPSState state; + State state; }; From 228d3883434394e36599887bca31585f3f6a3a02 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Tue, 13 Feb 2024 23:27:21 -0800 Subject: [PATCH 07/52] add verbose comments and more specific enum types --- gps_ubxm8_i2c/gps.cpp | 36 +++++++++++++++++++++++++++++++++--- gps_ubxm8_i2c/gps.h | 32 ++++++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cpp b/gps_ubxm8_i2c/gps.cpp index 681a5ad..059c4ff 100644 --- a/gps_ubxm8_i2c/gps.cpp +++ b/gps_ubxm8_i2c/gps.cpp @@ -14,6 +14,17 @@ const GPS::State GPS::getState() { return state; } +/** + * Sends a request for position data if none are currently pending. + * Then, checks if there is data available from the GPS. If there is none, + * it just returns a NO_DATA response. If there is data, it reads up to 1024 bytes (configurable at the top of gps.cpp) + * After reading, it will return one of these: + * - RECEIVE_IN_PROGRESS: it found a valid header for the data we're looking for (UBX packet) but hasn't read all of it yet. + * - NO_UBX_DATA: it successfully read data but there was no header for the data we're looking for (UBX packet) + * - POLL_JUST_FINISHED: it got data. Now you can read it with GPS::getSolution. + * + * There are also special return types for different types of error, that are hopefully verbose enough to explain themselves. +*/ const GPS::PollResult GPS::pollUpdate(I2C_HandleTypeDef* i2c) { if(state == GPS::State::REQUEST_NOT_SENT) { uint8_t message[4] = {0x01, 0x07, 0x00, 0x00}; @@ -53,9 +64,10 @@ const GPS::PollResult GPS::pollUpdate(I2C_HandleTypeDef* i2c) { } if(packetReader.isComplete()) { state = GPS::State::RESPONSE_READY; - return GPS::PollResult::POLL_FINISHED; + return GPS::PollResult::POLL_JUST_FINISHED; } } + return GPS::PollResult::RECEIVE_IN_PROGRESS; } else { for(uint16_t i = 0; i - +/** + * Class for interfacing over i2c with any M8 GPS. + * Before this class is used, the GPS reset pin needs to be pulled high. + * + * This class keeps its own finite state machine for abstracting away polling data availability and retrying requests. + * An example usage is as follows: + * ``` + * GPS myGPS; + * while(1) { + * if(myGPS.pollUpdate(&i2c1) == GPS::PollResult::POLL_FINISHED) { + * UBX_NAV_PVT_PAYLOAD pvtData = myGPS.getSolution(); + * myGPS.reset(); + * } + * } + * ``` + * + * After a packet is received, you _need_ to call the reset method. + * If you don't, `pollUpdate` will just do nothing and return a `POLL_ALREADY_FINISHED` response. + * + * The datasheet is here: https://content.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_UBX-13003221.pdf + * The most relevant parts are "UBX Protocol" (section 32) and "DDC Port" (section 15). + * +*/ class GPS { public: enum class State { @@ -14,12 +36,14 @@ class GPS { RESPONSE_READY }; enum class PollResult { - POLL_FINISHED, + POLL_JUST_FINISHED, + POLL_ALREADY_FINISHED, + RECEIVE_IN_PROGRESS, NO_DATA, + NO_UBX_DATA, DATA_LEN_POLL_FAILED, DATA_RECEIVE_I2C_FAILED, - DATA_RECEIVE_CHECKSUM_FAILED, - RECEIVE_IN_PROGRESS + DATA_RECEIVE_CHECKSUM_FAILED }; GPS(); const State getState(); From 5832e5284161aa558fa6f8b83e2a50740cebe01d Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Tue, 13 Feb 2024 23:38:05 -0800 Subject: [PATCH 08/52] add line to not mess up enum formatting --- .clang-format | 1 + 1 file changed, 1 insertion(+) diff --git a/.clang-format b/.clang-format index b23dcb9..c9b0aa7 100644 --- a/.clang-format +++ b/.clang-format @@ -2,3 +2,4 @@ BasedOnStyle: Google AccessModifierOffset: -2 ColumnLimit: 200 IndentWidth: 4 +AllowShortEnumsOnASingleLine: false From 6a962f88fe241451db6ca060c2489007b8ddf6be Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Tue, 13 Feb 2024 23:38:32 -0800 Subject: [PATCH 09/52] ran clang-format --- gps_ubxm8_i2c/gps.cpp | 64 ++++++++++++++++------------------ gps_ubxm8_i2c/gps.h | 67 ++++++++++++++++++------------------ gps_ubxm8_i2c/ubxHelpers.cpp | 7 ++-- gps_ubxm8_i2c/ubxMessages.h | 6 ++-- gps_ubxm8_i2c/ubxPacket.cpp | 46 +++++++++---------------- gps_ubxm8_i2c/ubxPacket.h | 40 ++++++++++----------- 6 files changed, 107 insertions(+), 123 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cpp b/gps_ubxm8_i2c/gps.cpp index 059c4ff..74e17ac 100644 --- a/gps_ubxm8_i2c/gps.cpp +++ b/gps_ubxm8_i2c/gps.cpp @@ -1,7 +1,8 @@ +#include "gps.h" + #include "ubxHelpers.h" -#include "ubxPacket.h" #include "ubxMessages.h" -#include "gps.h" +#include "ubxPacket.h" #define I2C_BUFFER_SIZE 1024 @@ -10,9 +11,7 @@ GPS::GPS() { state = GPS::State::REQUEST_NOT_SENT; } -const GPS::State GPS::getState() { - return state; -} +const GPS::State GPS::getState() { return state; } /** * Sends a request for position data if none are currently pending. @@ -21,60 +20,60 @@ const GPS::State GPS::getState() { * After reading, it will return one of these: * - RECEIVE_IN_PROGRESS: it found a valid header for the data we're looking for (UBX packet) but hasn't read all of it yet. * - NO_UBX_DATA: it successfully read data but there was no header for the data we're looking for (UBX packet) - * - POLL_JUST_FINISHED: it got data. Now you can read it with GPS::getSolution. - * + * - POLL_JUST_FINISHED: it got data. Now you can read it with GPS::getSolution. + * * There are also special return types for different types of error, that are hopefully verbose enough to explain themselves. -*/ + */ const GPS::PollResult GPS::pollUpdate(I2C_HandleTypeDef* i2c) { - if(state == GPS::State::REQUEST_NOT_SENT) { + if (state == GPS::State::REQUEST_NOT_SENT) { uint8_t message[4] = {0x01, 0x07, 0x00, 0x00}; sendUBX(message, 4, &hi2c3); state = GPS::State::POLLING_RESPONSE; } - if(state == GPS::State::POLLING_RESPONSE) { + if (state == GPS::State::POLLING_RESPONSE) { uint8_t lenBytes[2]; - uint16_t dataLen = 0; + uint16_t dataLen = 0; uint8_t buffer[I2C_BUFFER_SIZE]; HAL_StatusTypeDef dataLenReadStatus = HAL_I2C_Mem_Read(i2c, 0x42 << 1, 0xFD, 1, lenBytes, 2, 100); - if(dataLenReadStatus != HAL_OK) { + if (dataLenReadStatus != HAL_OK) { return GPS::PollResult::DATA_LEN_POLL_FAILED; } dataLen = lenBytes[0] << 8 | lenBytes[1]; - if(dataLen==0) { + if (dataLen == 0) { return GPS::PollResult::NO_DATA; } - if(dataLen > I2C_BUFFER_SIZE) { + if (dataLen > I2C_BUFFER_SIZE) { dataLen = I2C_BUFFER_SIZE; } HAL_StatusTypeDef rcvStatus = HAL_I2C_Master_Receive(i2c, 0x42 << 1, buffer, dataLen, 100); - if(rcvStatus != HAL_OK) { + if (rcvStatus != HAL_OK) { return GPS::PollResult::DATA_RECEIVE_I2C_FAILED; } - if(packetReader.isInProgress()) { - for(uint16_t i = 0; i +#include "ubxMessages.h" +#include "ubxPacket.h" /** - * Class for interfacing over i2c with any M8 GPS. + * Class for interfacing over i2c with any M8 GPS. * Before this class is used, the GPS reset pin needs to be pulled high. - * + * * This class keeps its own finite state machine for abstracting away polling data availability and retrying requests. * An example usage is as follows: * ``` @@ -20,39 +20,38 @@ * } * } * ``` - * - * After a packet is received, you _need_ to call the reset method. + * + * After a packet is received, you _need_ to call the reset method. * If you don't, `pollUpdate` will just do nothing and return a `POLL_ALREADY_FINISHED` response. - * + * * The datasheet is here: https://content.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_UBX-13003221.pdf * The most relevant parts are "UBX Protocol" (section 32) and "DDC Port" (section 15). - * -*/ + * + */ class GPS { - public: - enum class State { - REQUEST_NOT_SENT, - POLLING_RESPONSE, - RESPONSE_READY - }; - enum class PollResult { - POLL_JUST_FINISHED, - POLL_ALREADY_FINISHED, - RECEIVE_IN_PROGRESS, - NO_DATA, - NO_UBX_DATA, - DATA_LEN_POLL_FAILED, - DATA_RECEIVE_I2C_FAILED, - DATA_RECEIVE_CHECKSUM_FAILED - }; - GPS(); - const State getState(); - const PollResult pollUpdate(I2C_HandleTypeDef* i2c); - const UBX_NAV_PVT_PAYLOAD getSolution(); - void reset(); + public: + enum class State { + REQUEST_NOT_SENT, + POLLING_RESPONSE, + RESPONSE_READY + }; + enum class PollResult { + POLL_JUST_FINISHED, + POLL_ALREADY_FINISHED, + RECEIVE_IN_PROGRESS, + NO_DATA, + NO_UBX_DATA, + DATA_LEN_POLL_FAILED, + DATA_RECEIVE_I2C_FAILED, + DATA_RECEIVE_CHECKSUM_FAILED + }; + GPS(); + const State getState(); + const PollResult pollUpdate(I2C_HandleTypeDef* i2c); + const UBX_NAV_PVT_PAYLOAD getSolution(); + void reset(); - private: - UBXPacketReader packetReader; - State state; + private: + UBXPacketReader packetReader; + State state; }; - diff --git a/gps_ubxm8_i2c/ubxHelpers.cpp b/gps_ubxm8_i2c/ubxHelpers.cpp index 6ed266e..6766b46 100644 --- a/gps_ubxm8_i2c/ubxHelpers.cpp +++ b/gps_ubxm8_i2c/ubxHelpers.cpp @@ -1,6 +1,7 @@ #include "ubxHelpers.h" -#include "ubxPacket.h" + #include "ubxMessages.h" +#include "ubxPacket.h" #define I2C_BUFFER_SIZE 1024 @@ -15,7 +16,7 @@ bool sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c) { return false; } - for(uint16_t i=0;i=4+payloadLength && currentPacketIndex<6+payloadLength) { - if(currentPacketIndex==4+payloadLength) { - if(ckA != newByte) { + } else if (currentPacketIndex >= 4 + payloadLength && currentPacketIndex < 6 + payloadLength) { + if (currentPacketIndex == 4 + payloadLength) { + if (ckA != newByte) { return UBXPacketUpdateResult::CHECKSUM_FAILED; } } else { - if(ckB != newByte) { + if (ckB != newByte) { return UBXPacketUpdateResult::CHECKSUM_FAILED; } else { complete = true; inProgress = false; } } - return UBXPacketUpdateResult::UPDATE_OK; // return early to avoid updating checksums + return UBXPacketUpdateResult::UPDATE_OK; // return early to avoid updating checksums } else { - payload[currentPacketIndex-4] = newByte; + payload[currentPacketIndex - 4] = newByte; } ckA = ckA + newByte; ckB = ckB + ckA; return UBXPacketUpdateResult::UPDATE_OK; } -void* UBXPacketReader::getPayload() { - return (void*)payload; -} +void* UBXPacketReader::getPayload() { return (void*)payload; } -uint8_t UBXPacketReader::getPayloadLength() { - return payloadLength; -} +uint8_t UBXPacketReader::getPayloadLength() { return payloadLength; } -uint8_t UBXPacketReader::getMessageClass() { - return messageClass; -} +uint8_t UBXPacketReader::getMessageClass() { return messageClass; } -uint8_t UBXPacketReader::getMessageId() { - return messageId; -} +uint8_t UBXPacketReader::getMessageId() { return messageId; } -bool UBXPacketReader::isComplete() { - return complete; -} +bool UBXPacketReader::isComplete() { return complete; } -bool UBXPacketReader::isInProgress() { - return inProgress; -} +bool UBXPacketReader::isInProgress() { return inProgress; } void UBXPacketReader::reset() { payloadLength = 0; diff --git a/gps_ubxm8_i2c/ubxPacket.h b/gps_ubxm8_i2c/ubxPacket.h index 98408ad..f55159d 100644 --- a/gps_ubxm8_i2c/ubxPacket.h +++ b/gps_ubxm8_i2c/ubxPacket.h @@ -9,25 +9,25 @@ enum class UBXPacketUpdateResult { }; class UBXPacketReader { - public: - UBXPacketReader(); - UBXPacketUpdateResult update(uint8_t byte); - bool isComplete(); - bool isInProgress(); - void* getPayload(); - uint8_t getPayloadLength(); - uint8_t getMessageClass(); - uint8_t getMessageId(); - void reset(); + public: + UBXPacketReader(); + UBXPacketUpdateResult update(uint8_t byte); + bool isComplete(); + bool isInProgress(); + void* getPayload(); + uint8_t getPayloadLength(); + uint8_t getMessageClass(); + uint8_t getMessageId(); + void reset(); - private: - uint8_t payload[512]; - uint8_t payloadLength; - uint8_t packetIndex; - uint8_t messageClass; - uint8_t messageId; - uint8_t ckA; - uint8_t ckB; - bool complete; - bool inProgress; + private: + uint8_t payload[512]; + uint8_t payloadLength; + uint8_t packetIndex; + uint8_t messageClass; + uint8_t messageId; + uint8_t ckA; + uint8_t ckB; + bool complete; + bool inProgress; }; From 8ec2a0787e4892bcae0165777e9b96dedf66f008 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 18 Feb 2024 13:31:19 -0800 Subject: [PATCH 10/52] refactor conditional logic in ubxPacket --- gps_ubxm8_i2c/ubxPacket.cpp | 27 +++++++++++++++------------ gps_ubxm8_i2c/ubxPacket.h | 3 ++- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/gps_ubxm8_i2c/ubxPacket.cpp b/gps_ubxm8_i2c/ubxPacket.cpp index b8bd295..9992fa0 100644 --- a/gps_ubxm8_i2c/ubxPacket.cpp +++ b/gps_ubxm8_i2c/ubxPacket.cpp @@ -25,23 +25,26 @@ UBXPacketUpdateResult UBXPacketReader::update(uint8_t newByte) { payloadLength = newByte; } else if (currentPacketIndex == 3) { payloadLength |= (uint16_t)newByte << 8; - } else if (currentPacketIndex >= 4 + payloadLength && currentPacketIndex < 6 + payloadLength) { - if (currentPacketIndex == 4 + payloadLength) { - if (ckA != newByte) { - return UBXPacketUpdateResult::CHECKSUM_FAILED; - } + } else if (currentPacketIndex < 4 + payloadLength) { + payload[currentPacketIndex - 4] = newByte; + } else if (currentPacketIndex == 4 + payloadLength) { + if (ckA != newByte) { + return UBXPacketUpdateResult::CHECKSUM_FAILED; + } + return UBXPacketUpdateResult::UPDATE_OK; // return early to avoid updating checksums + } else if (currentPacketIndex == 5 + payloadLength) { + if (ckB != newByte) { + return UBXPacketUpdateResult::CHECKSUM_FAILED; } else { - if (ckB != newByte) { - return UBXPacketUpdateResult::CHECKSUM_FAILED; - } else { - complete = true; - inProgress = false; - } + complete = true; + inProgress = false; } return UBXPacketUpdateResult::UPDATE_OK; // return early to avoid updating checksums } else { - payload[currentPacketIndex - 4] = newByte; + // should never get here, but return a unique value for debugging just in case + return UBXPacketUpdateResult::PACKET_INDEX_OVERFLOW; } + ckA = ckA + newByte; ckB = ckB + ckA; return UBXPacketUpdateResult::UPDATE_OK; diff --git a/gps_ubxm8_i2c/ubxPacket.h b/gps_ubxm8_i2c/ubxPacket.h index f55159d..3b72bd5 100644 --- a/gps_ubxm8_i2c/ubxPacket.h +++ b/gps_ubxm8_i2c/ubxPacket.h @@ -5,7 +5,8 @@ enum class UBXPacketUpdateResult { UPDATE_OK, CHECKSUM_FAILED, - PACKET_ALREADY_COMPLETE + PACKET_ALREADY_COMPLETE, + PACKET_INDEX_OVERFLOW // indicates internal error with packet reader }; class UBXPacketReader { From c10d3fbc1217ed31fa8f4c30428de5355532035c Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 18 Feb 2024 13:37:24 -0800 Subject: [PATCH 11/52] rename files to .cc --- gps_ubxm8_i2c/{gps.cpp => gps.cc} | 0 gps_ubxm8_i2c/{ubxHelpers.cpp => ubxHelpers.cc} | 0 gps_ubxm8_i2c/{ubxPacket.cpp => ubxPacket.cc} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename gps_ubxm8_i2c/{gps.cpp => gps.cc} (100%) rename gps_ubxm8_i2c/{ubxHelpers.cpp => ubxHelpers.cc} (100%) rename gps_ubxm8_i2c/{ubxPacket.cpp => ubxPacket.cc} (100%) diff --git a/gps_ubxm8_i2c/gps.cpp b/gps_ubxm8_i2c/gps.cc similarity index 100% rename from gps_ubxm8_i2c/gps.cpp rename to gps_ubxm8_i2c/gps.cc diff --git a/gps_ubxm8_i2c/ubxHelpers.cpp b/gps_ubxm8_i2c/ubxHelpers.cc similarity index 100% rename from gps_ubxm8_i2c/ubxHelpers.cpp rename to gps_ubxm8_i2c/ubxHelpers.cc diff --git a/gps_ubxm8_i2c/ubxPacket.cpp b/gps_ubxm8_i2c/ubxPacket.cc similarity index 100% rename from gps_ubxm8_i2c/ubxPacket.cpp rename to gps_ubxm8_i2c/ubxPacket.cc From d32e5c087e9d217ff6a827b2ed38cbfa26c58067 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 18 Feb 2024 13:40:48 -0800 Subject: [PATCH 12/52] change functions to PascalCase --- gps_ubxm8_i2c/gps.cc | 8 ++++---- gps_ubxm8_i2c/gps.h | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 74e17ac..83c92a8 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -11,7 +11,7 @@ GPS::GPS() { state = GPS::State::REQUEST_NOT_SENT; } -const GPS::State GPS::getState() { return state; } +const GPS::State GPS::GetState() { return state; } /** * Sends a request for position data if none are currently pending. @@ -24,7 +24,7 @@ const GPS::State GPS::getState() { return state; } * * There are also special return types for different types of error, that are hopefully verbose enough to explain themselves. */ -const GPS::PollResult GPS::pollUpdate(I2C_HandleTypeDef* i2c) { +const GPS::PollResult GPS::PollUpdate(I2C_HandleTypeDef* i2c) { if (state == GPS::State::REQUEST_NOT_SENT) { uint8_t message[4] = {0x01, 0x07, 0x00, 0x00}; sendUBX(message, 4, &hi2c3); @@ -105,13 +105,13 @@ const GPS::PollResult GPS::pollUpdate(I2C_HandleTypeDef* i2c) { * After calling this and using the info returned, getting the next * packet requires you to call `reset` and `pollUpdate` again. */ -const UBX_NAV_PVT_PAYLOAD GPS::getSolution() { return *(UBX_NAV_PVT_PAYLOAD*)packetReader.getPayload(); } +const UBX_NAV_PVT_PAYLOAD GPS::GetSolution() { return *(UBX_NAV_PVT_PAYLOAD*)packetReader.getPayload(); } /** * Puts the GPS state back to its initial value so that `pollUpdate` knows * it needs to send a new data request. */ -void GPS::reset() { +void GPS::Reset() { state = GPS::State::REQUEST_NOT_SENT; packetReader.reset(); } diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 61d439d..00b41b0 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -14,9 +14,9 @@ * ``` * GPS myGPS; * while(1) { - * if(myGPS.pollUpdate(&i2c1) == GPS::PollResult::POLL_FINISHED) { - * UBX_NAV_PVT_PAYLOAD pvtData = myGPS.getSolution(); - * myGPS.reset(); + * if(myGPS.PollUpdate(&i2c1) == GPS::PollResult::POLL_FINISHED) { + * UBX_NAV_PVT_PAYLOAD pvtData = myGPS.GetSolution(); + * myGPS.Reset(); * } * } * ``` @@ -46,10 +46,10 @@ class GPS { DATA_RECEIVE_CHECKSUM_FAILED }; GPS(); - const State getState(); - const PollResult pollUpdate(I2C_HandleTypeDef* i2c); - const UBX_NAV_PVT_PAYLOAD getSolution(); - void reset(); + const State GetState(); + const PollResult PollUpdate(I2C_HandleTypeDef* i2c); + const UBX_NAV_PVT_PAYLOAD GetSolution(); + void Reset(); private: UBXPacketReader packetReader; From 050647a65c8a1ae442222ec0f6cc2a4afba0097f Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 18 Feb 2024 13:47:42 -0800 Subject: [PATCH 13/52] put enum definition before reference --- gps_ubxm8_i2c/ubxMessages.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/gps_ubxm8_i2c/ubxMessages.h b/gps_ubxm8_i2c/ubxMessages.h index 931bbab..5d408a0 100644 --- a/gps_ubxm8_i2c/ubxMessages.h +++ b/gps_ubxm8_i2c/ubxMessages.h @@ -1,6 +1,15 @@ #pragma once #include +enum class GPSFixType : uint8_t { + NO_FIX, + DEAD_RECKONING, + FIX_2D, + FIX_3D, + GNSS_AND_DEAD_RECKONING, + TIME_ONLY_FIX +}; + #pragma pack(push, 1) struct UBX_NAV_PVT_PAYLOAD { uint32_t iTOW; @@ -37,12 +46,3 @@ struct UBX_NAV_PVT_PAYLOAD { uint16_t magAcc; }; #pragma pack(pop) - -enum class GPSFixType : uint8_t { - NO_FIX, - DEAD_RECKONING, - FIX_2D, - FIX_3D, - GNSS_AND_DEAD_RECKONING, - TIME_ONLY_FIX -}; From 7e7e00505792993cf38f7a61468c98c92e8496cd Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 18 Feb 2024 13:47:55 -0800 Subject: [PATCH 14/52] replace i2c header include --- gps_ubxm8_i2c/gps.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 00b41b0..2008783 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -1,6 +1,10 @@ #pragma once -#include +// if this is shitting itself, just locally replace it with whatever +// header on your machine that can get you `I2C_HandleTypeDef` +#if defined(STM32F1) +#include "stm32f1xx_hal.h" +#endif #include "ubxMessages.h" #include "ubxPacket.h" From df9ed0e2f99e18195e868bae83eb7c5db6f2a5fb Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 18 Feb 2024 14:13:30 -0800 Subject: [PATCH 15/52] rename gps class to include full info and pull reset pin in constructor --- gps_ubxm8_i2c/gps.cc | 49 ++++++++++++++++++++++---------------------- gps_ubxm8_i2c/gps.h | 4 ++-- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 83c92a8..b73042a 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -6,12 +6,13 @@ #define I2C_BUFFER_SIZE 1024 -GPS::GPS() { +GpsUbxM8I2c::GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin) { + HAL_GPIO_WritePin(gpioResetPort, gpioResetPin, GPIO_PIN_SET); packetReader = UBXPacketReader(); - state = GPS::State::REQUEST_NOT_SENT; + state = GpsUbxM8I2c::State::REQUEST_NOT_SENT; } -const GPS::State GPS::GetState() { return state; } +const GpsUbxM8I2c::State GpsUbxM8I2c::GetState() { return state; } /** * Sends a request for position data if none are currently pending. @@ -20,30 +21,30 @@ const GPS::State GPS::GetState() { return state; } * After reading, it will return one of these: * - RECEIVE_IN_PROGRESS: it found a valid header for the data we're looking for (UBX packet) but hasn't read all of it yet. * - NO_UBX_DATA: it successfully read data but there was no header for the data we're looking for (UBX packet) - * - POLL_JUST_FINISHED: it got data. Now you can read it with GPS::getSolution. + * - POLL_JUST_FINISHED: it got data. Now you can read it with GpsUbxM8I2c::getSolution. * * There are also special return types for different types of error, that are hopefully verbose enough to explain themselves. */ -const GPS::PollResult GPS::PollUpdate(I2C_HandleTypeDef* i2c) { - if (state == GPS::State::REQUEST_NOT_SENT) { +const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate(I2C_HandleTypeDef* i2c) { + if (state == GpsUbxM8I2c::State::REQUEST_NOT_SENT) { uint8_t message[4] = {0x01, 0x07, 0x00, 0x00}; sendUBX(message, 4, &hi2c3); - state = GPS::State::POLLING_RESPONSE; + state = GpsUbxM8I2c::State::POLLING_RESPONSE; } - if (state == GPS::State::POLLING_RESPONSE) { + if (state == GpsUbxM8I2c::State::POLLING_RESPONSE) { uint8_t lenBytes[2]; uint16_t dataLen = 0; uint8_t buffer[I2C_BUFFER_SIZE]; HAL_StatusTypeDef dataLenReadStatus = HAL_I2C_Mem_Read(i2c, 0x42 << 1, 0xFD, 1, lenBytes, 2, 100); if (dataLenReadStatus != HAL_OK) { - return GPS::PollResult::DATA_LEN_POLL_FAILED; + return GpsUbxM8I2c::PollResult::DATA_LEN_POLL_FAILED; } dataLen = lenBytes[0] << 8 | lenBytes[1]; if (dataLen == 0) { - return GPS::PollResult::NO_DATA; + return GpsUbxM8I2c::PollResult::NO_DATA; } if (dataLen > I2C_BUFFER_SIZE) { @@ -51,7 +52,7 @@ const GPS::PollResult GPS::PollUpdate(I2C_HandleTypeDef* i2c) { } HAL_StatusTypeDef rcvStatus = HAL_I2C_Master_Receive(i2c, 0x42 << 1, buffer, dataLen, 100); if (rcvStatus != HAL_OK) { - return GPS::PollResult::DATA_RECEIVE_I2C_FAILED; + return GpsUbxM8I2c::PollResult::DATA_RECEIVE_I2C_FAILED; } if (packetReader.isInProgress()) { @@ -59,14 +60,14 @@ const GPS::PollResult GPS::PollUpdate(I2C_HandleTypeDef* i2c) { UBXPacketUpdateResult res = packetReader.update(buffer[i]); if (res == UBXPacketUpdateResult::CHECKSUM_FAILED) { packetReader.reset(); - return GPS::PollResult::DATA_RECEIVE_CHECKSUM_FAILED; + return GpsUbxM8I2c::PollResult::DATA_RECEIVE_CHECKSUM_FAILED; } if (packetReader.isComplete()) { - state = GPS::State::RESPONSE_READY; - return GPS::PollResult::POLL_JUST_FINISHED; + state = GpsUbxM8I2c::State::RESPONSE_READY; + return GpsUbxM8I2c::PollResult::POLL_JUST_FINISHED; } } - return GPS::PollResult::RECEIVE_IN_PROGRESS; + return GpsUbxM8I2c::PollResult::RECEIVE_IN_PROGRESS; } else { for (uint16_t i = 0; i < dataLen; i++) { if (buffer[i] == 0xB5 && buffer[i + 1] == 0x62) { @@ -75,7 +76,7 @@ const GPS::PollResult GPS::PollUpdate(I2C_HandleTypeDef* i2c) { UBXPacketUpdateResult res = packetReader.update(buffer[i]); if (res != UBXPacketUpdateResult::UPDATE_OK) { packetReader.reset(); - return GPS::PollResult::DATA_RECEIVE_CHECKSUM_FAILED; + return GpsUbxM8I2c::PollResult::DATA_RECEIVE_CHECKSUM_FAILED; } i++; } @@ -83,17 +84,17 @@ const GPS::PollResult GPS::PollUpdate(I2C_HandleTypeDef* i2c) { } if (!packetReader.isInProgress()) { - return GPS::PollResult::NO_UBX_DATA; + return GpsUbxM8I2c::PollResult::NO_UBX_DATA; } if (packetReader.isComplete()) { - state = GPS::State::RESPONSE_READY; - return GPS::PollResult::POLL_JUST_FINISHED; + state = GpsUbxM8I2c::State::RESPONSE_READY; + return GpsUbxM8I2c::PollResult::POLL_JUST_FINISHED; } - return GPS::PollResult::RECEIVE_IN_PROGRESS; + return GpsUbxM8I2c::PollResult::RECEIVE_IN_PROGRESS; } } - return GPS::PollResult::POLL_ALREADY_FINISHED; + return GpsUbxM8I2c::PollResult::POLL_ALREADY_FINISHED; } /** @@ -105,13 +106,13 @@ const GPS::PollResult GPS::PollUpdate(I2C_HandleTypeDef* i2c) { * After calling this and using the info returned, getting the next * packet requires you to call `reset` and `pollUpdate` again. */ -const UBX_NAV_PVT_PAYLOAD GPS::GetSolution() { return *(UBX_NAV_PVT_PAYLOAD*)packetReader.getPayload(); } +const UBX_NAV_PVT_PAYLOAD GpsUbxM8I2c::GetSolution() { return *(UBX_NAV_PVT_PAYLOAD*)packetReader.getPayload(); } /** * Puts the GPS state back to its initial value so that `pollUpdate` knows * it needs to send a new data request. */ -void GPS::Reset() { - state = GPS::State::REQUEST_NOT_SENT; +void GpsUbxM8I2c::Reset() { + state = GpsUbxM8I2c::State::REQUEST_NOT_SENT; packetReader.reset(); } diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 2008783..e3ba058 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -32,7 +32,7 @@ * The most relevant parts are "UBX Protocol" (section 32) and "DDC Port" (section 15). * */ -class GPS { +class GpsUbxM8I2c { public: enum class State { REQUEST_NOT_SENT, @@ -49,7 +49,7 @@ class GPS { DATA_RECEIVE_I2C_FAILED, DATA_RECEIVE_CHECKSUM_FAILED }; - GPS(); + GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin); const State GetState(); const PollResult PollUpdate(I2C_HandleTypeDef* i2c); const UBX_NAV_PVT_PAYLOAD GetSolution(); From 5a561fe99d32b5d4a1f815e09fa9f97dffa3ebc2 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 18 Feb 2024 14:16:07 -0800 Subject: [PATCH 16/52] move ubxHelpers to private methods of gps class --- gps_ubxm8_i2c/gps.cc | 29 ++++++++++++++++++++++++++++- gps_ubxm8_i2c/gps.h | 9 +++++---- gps_ubxm8_i2c/ubxHelpers.cc | 34 ---------------------------------- gps_ubxm8_i2c/ubxHelpers.h | 5 ----- 4 files changed, 33 insertions(+), 44 deletions(-) delete mode 100644 gps_ubxm8_i2c/ubxHelpers.cc delete mode 100644 gps_ubxm8_i2c/ubxHelpers.h diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index b73042a..908adbf 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -1,11 +1,38 @@ #include "gps.h" -#include "ubxHelpers.h" #include "ubxMessages.h" #include "ubxPacket.h" #define I2C_BUFFER_SIZE 1024 +static uint8_t magicBytes[2] = {0xB5, 0x62}; + +bool GpsUbxM8I2c::sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c) { + uint8_t CK_A{0}, CK_B{0}; + + HAL_StatusTypeDef status; + status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, magicBytes, 2, 100); + if (status != HAL_OK) { + return false; + } + + for (uint16_t i = 0; i < len; i++) { + CK_A = CK_A + message[i]; + CK_B = CK_B + CK_A; + } + + uint8_t CK[2] = {CK_A, CK_B}; + status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, message, len, 100); + if (status != HAL_OK) { + return false; + } + status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, CK, 2, 100); + if (status != HAL_OK) { + return false; + } + return true; +} + GpsUbxM8I2c::GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin) { HAL_GPIO_WritePin(gpioResetPort, gpioResetPin, GPIO_PIN_SET); packetReader = UBXPacketReader(); diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index e3ba058..8e0ae42 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -2,10 +2,10 @@ // if this is shitting itself, just locally replace it with whatever // header on your machine that can get you `I2C_HandleTypeDef` -#if defined(STM32F1) -#include "stm32f1xx_hal.h" -#endif - +// #if defined(STM32F1) +// #include "stm32f1xx_hal.h" +// #endif +#include "i2c.h" #include "ubxMessages.h" #include "ubxPacket.h" @@ -58,4 +58,5 @@ class GpsUbxM8I2c { private: UBXPacketReader packetReader; State state; + bool sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c); }; diff --git a/gps_ubxm8_i2c/ubxHelpers.cc b/gps_ubxm8_i2c/ubxHelpers.cc deleted file mode 100644 index 6766b46..0000000 --- a/gps_ubxm8_i2c/ubxHelpers.cc +++ /dev/null @@ -1,34 +0,0 @@ -#include "ubxHelpers.h" - -#include "ubxMessages.h" -#include "ubxPacket.h" - -#define I2C_BUFFER_SIZE 1024 - -static uint8_t magicBytes[2] = {0xB5, 0x62}; - -bool sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c) { - uint8_t CK_A{0}, CK_B{0}; - - HAL_StatusTypeDef status; - status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, magicBytes, 2, 100); - if (status != HAL_OK) { - return false; - } - - for (uint16_t i = 0; i < len; i++) { - CK_A = CK_A + message[i]; - CK_B = CK_B + CK_A; - } - - uint8_t CK[2] = {CK_A, CK_B}; - status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, message, len, 100); - if (status != HAL_OK) { - return false; - } - status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, CK, 2, 100); - if (status != HAL_OK) { - return false; - } - return true; -} diff --git a/gps_ubxm8_i2c/ubxHelpers.h b/gps_ubxm8_i2c/ubxHelpers.h deleted file mode 100644 index 4d86de1..0000000 --- a/gps_ubxm8_i2c/ubxHelpers.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -#include "i2c.h" -#include "ubxMessages.h" - -bool sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c); From cb0b67f2c1c5270f0110aca2e6fa81ce011df6ec Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 18 Feb 2024 14:29:09 -0800 Subject: [PATCH 17/52] add formatting to comments --- gps_ubxm8_i2c/gps.cc | 28 ++++++++++++++++++---------- gps_ubxm8_i2c/gps.h | 16 ++++++++-------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 908adbf..149948d 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -7,6 +7,17 @@ static uint8_t magicBytes[2] = {0xB5, 0x62}; +/** + * @brief Sends a UBX protocol message over i2c + * + * @param message Array containing + * {messageClass, messageID, payloadLenHighBits, payloadLenLowBits}, + * and if the payload length >0, all the payload bytes. Note: you don't need to + * include the UBX start sequence in this or the checksums. + * + * @param len Length of `message` + * @param i2c The HAL i2c handle to use for transmission. + */ bool GpsUbxM8I2c::sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c) { uint8_t CK_A{0}, CK_B{0}; @@ -42,15 +53,10 @@ GpsUbxM8I2c::GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin) { const GpsUbxM8I2c::State GpsUbxM8I2c::GetState() { return state; } /** - * Sends a request for position data if none are currently pending. - * Then, checks if there is data available from the GPS. If there is none, - * it just returns a NO_DATA response. If there is data, it reads up to 1024 bytes (configurable at the top of gps.cpp) - * After reading, it will return one of these: - * - RECEIVE_IN_PROGRESS: it found a valid header for the data we're looking for (UBX packet) but hasn't read all of it yet. - * - NO_UBX_DATA: it successfully read data but there was no header for the data we're looking for (UBX packet) - * - POLL_JUST_FINISHED: it got data. Now you can read it with GpsUbxM8I2c::getSolution. + * @brief Sends a request for position data if none are currently pending, checks data available, + * and returns a status indicator. * - * There are also special return types for different types of error, that are hopefully verbose enough to explain themselves. + * @return a GpsUbxM8I2c::PollResult object. See the definition of that enum for details. */ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate(I2C_HandleTypeDef* i2c) { if (state == GpsUbxM8I2c::State::REQUEST_NOT_SENT) { @@ -125,18 +131,20 @@ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate(I2C_HandleTypeDef* i2c) { } /** - * Returns GPS position solution info. This will only give valid data + * @brief Returns GPS position solution info. This will only give valid data * if it's called after `pollUpdate` returns a POLL_JUST_FINISHED response, * which will put the GPS's state in RESPONSE_READY mode. If you call this before that, * the data in the struct is undefined. * * After calling this and using the info returned, getting the next * packet requires you to call `reset` and `pollUpdate` again. + * + * @retval UBX_NAV_PVT_PAYLOAD struct */ const UBX_NAV_PVT_PAYLOAD GpsUbxM8I2c::GetSolution() { return *(UBX_NAV_PVT_PAYLOAD*)packetReader.getPayload(); } /** - * Puts the GPS state back to its initial value so that `pollUpdate` knows + * @brief Puts the GPS state back to its initial value so that `pollUpdate` knows * it needs to send a new data request. */ void GpsUbxM8I2c::Reset() { diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 8e0ae42..800be74 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -40,14 +40,14 @@ class GpsUbxM8I2c { RESPONSE_READY }; enum class PollResult { - POLL_JUST_FINISHED, - POLL_ALREADY_FINISHED, - RECEIVE_IN_PROGRESS, - NO_DATA, - NO_UBX_DATA, - DATA_LEN_POLL_FAILED, - DATA_RECEIVE_I2C_FAILED, - DATA_RECEIVE_CHECKSUM_FAILED + POLL_JUST_FINISHED, // the ubx data has been received on this invocation, and is now ready to be retrieved + POLL_ALREADY_FINISHED, // the ubx data was already ready after a previous PollUpdate call + RECEIVE_IN_PROGRESS, // we found the UBX start bytes in the incoming stream but haven't read the entire message + NO_DATA, // no data from GPS available + NO_UBX_DATA, // data read successfulyl but no UBX start bytes found + DATA_LEN_POLL_FAILED, // there was a failure in the I2C mem read for getting the quantity of data available + DATA_RECEIVE_I2C_FAILED, // there was a failure in the I2C receive to read the available data from the GPS + DATA_RECEIVE_CHECKSUM_FAILED // we received UBX data but the checksum didn't match the message. }; GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin); const State GetState(); From 130b5b9875458259edaa445daecafcb69937aba1 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 18 Feb 2024 14:33:05 -0800 Subject: [PATCH 18/52] refactor i2c timeout to a macro --- gps_ubxm8_i2c/gps.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 149948d..096660e 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -4,6 +4,7 @@ #include "ubxPacket.h" #define I2C_BUFFER_SIZE 1024 +#define GPS_I2C_TIMEOUT 100 static uint8_t magicBytes[2] = {0xB5, 0x62}; @@ -22,7 +23,7 @@ bool GpsUbxM8I2c::sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c uint8_t CK_A{0}, CK_B{0}; HAL_StatusTypeDef status; - status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, magicBytes, 2, 100); + status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, magicBytes, 2, GPS_I2C_TIMEOUT); if (status != HAL_OK) { return false; } @@ -33,11 +34,11 @@ bool GpsUbxM8I2c::sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c } uint8_t CK[2] = {CK_A, CK_B}; - status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, message, len, 100); + status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, message, len, GPS_I2C_TIMEOUT); if (status != HAL_OK) { return false; } - status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, CK, 2, 100); + status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, CK, 2, GPS_I2C_TIMEOUT); if (status != HAL_OK) { return false; } @@ -70,7 +71,7 @@ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate(I2C_HandleTypeDef* i2c) { uint16_t dataLen = 0; uint8_t buffer[I2C_BUFFER_SIZE]; - HAL_StatusTypeDef dataLenReadStatus = HAL_I2C_Mem_Read(i2c, 0x42 << 1, 0xFD, 1, lenBytes, 2, 100); + HAL_StatusTypeDef dataLenReadStatus = HAL_I2C_Mem_Read(i2c, 0x42 << 1, 0xFD, 1, lenBytes, 2, GPS_I2C_TIMEOUT); if (dataLenReadStatus != HAL_OK) { return GpsUbxM8I2c::PollResult::DATA_LEN_POLL_FAILED; } @@ -83,7 +84,7 @@ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate(I2C_HandleTypeDef* i2c) { if (dataLen > I2C_BUFFER_SIZE) { dataLen = I2C_BUFFER_SIZE; } - HAL_StatusTypeDef rcvStatus = HAL_I2C_Master_Receive(i2c, 0x42 << 1, buffer, dataLen, 100); + HAL_StatusTypeDef rcvStatus = HAL_I2C_Master_Receive(i2c, 0x42 << 1, buffer, dataLen, GPS_I2C_TIMEOUT); if (rcvStatus != HAL_OK) { return GpsUbxM8I2c::PollResult::DATA_RECEIVE_I2C_FAILED; } From e1780264d7861e560d243663e4ce02a863fd6c23 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Wed, 21 Feb 2024 00:32:41 -0800 Subject: [PATCH 19/52] refactor: move private helper to end of file --- gps_ubxm8_i2c/gps.cc | 78 ++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 096660e..b5a3793 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -6,45 +6,6 @@ #define I2C_BUFFER_SIZE 1024 #define GPS_I2C_TIMEOUT 100 -static uint8_t magicBytes[2] = {0xB5, 0x62}; - -/** - * @brief Sends a UBX protocol message over i2c - * - * @param message Array containing - * {messageClass, messageID, payloadLenHighBits, payloadLenLowBits}, - * and if the payload length >0, all the payload bytes. Note: you don't need to - * include the UBX start sequence in this or the checksums. - * - * @param len Length of `message` - * @param i2c The HAL i2c handle to use for transmission. - */ -bool GpsUbxM8I2c::sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c) { - uint8_t CK_A{0}, CK_B{0}; - - HAL_StatusTypeDef status; - status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, magicBytes, 2, GPS_I2C_TIMEOUT); - if (status != HAL_OK) { - return false; - } - - for (uint16_t i = 0; i < len; i++) { - CK_A = CK_A + message[i]; - CK_B = CK_B + CK_A; - } - - uint8_t CK[2] = {CK_A, CK_B}; - status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, message, len, GPS_I2C_TIMEOUT); - if (status != HAL_OK) { - return false; - } - status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, CK, 2, GPS_I2C_TIMEOUT); - if (status != HAL_OK) { - return false; - } - return true; -} - GpsUbxM8I2c::GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin) { HAL_GPIO_WritePin(gpioResetPort, gpioResetPin, GPIO_PIN_SET); packetReader = UBXPacketReader(); @@ -152,3 +113,42 @@ void GpsUbxM8I2c::Reset() { state = GpsUbxM8I2c::State::REQUEST_NOT_SENT; packetReader.reset(); } + + +/** + * @brief Sends a UBX protocol message over i2c + * + * @param message Array containing + * {messageClass, messageID, payloadLenHighBits, payloadLenLowBits}, + * and if the payload length >0, all the payload bytes. Note: you don't need to + * include the UBX start sequence in this or the checksums. + * + * @param len Length of `message` + * @param i2c The HAL i2c handle to use for transmission. + */ +bool GpsUbxM8I2c::sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c) { + static uint8_t magicBytes[2] = {0xB5, 0x62}; + uint8_t CK_A{0}, CK_B{0}; + + HAL_StatusTypeDef status; + status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, magicBytes, 2, GPS_I2C_TIMEOUT); + if (status != HAL_OK) { + return false; + } + + for (uint16_t i = 0; i < len; i++) { + CK_A = CK_A + message[i]; + CK_B = CK_B + CK_A; + } + + uint8_t CK[2] = {CK_A, CK_B}; + status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, message, len, GPS_I2C_TIMEOUT); + if (status != HAL_OK) { + return false; + } + status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, CK, 2, GPS_I2C_TIMEOUT); + if (status != HAL_OK) { + return false; + } + return true; +} \ No newline at end of file From 5739f12476217d0098f7ccf47c8030f992af5f8f Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Wed, 21 Feb 2024 00:33:44 -0800 Subject: [PATCH 20/52] move pin reset to Init method --- gps_ubxm8_i2c/gps.cc | 5 ++++- gps_ubxm8_i2c/gps.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index b5a3793..84862a2 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -7,11 +7,14 @@ #define GPS_I2C_TIMEOUT 100 GpsUbxM8I2c::GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin) { - HAL_GPIO_WritePin(gpioResetPort, gpioResetPin, GPIO_PIN_SET); packetReader = UBXPacketReader(); state = GpsUbxM8I2c::State::REQUEST_NOT_SENT; } +GpsUbxM8I2c::Init(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin) { + HAL_GPIO_WritePin(gpioResetPort, gpioResetPin, GPIO_PIN_SET); +} + const GpsUbxM8I2c::State GpsUbxM8I2c::GetState() { return state; } /** diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 800be74..7a40325 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -50,6 +50,7 @@ class GpsUbxM8I2c { DATA_RECEIVE_CHECKSUM_FAILED // we received UBX data but the checksum didn't match the message. }; GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin); + void Init(); const State GetState(); const PollResult PollUpdate(I2C_HandleTypeDef* i2c); const UBX_NAV_PVT_PAYLOAD GetSolution(); From 6388ca835df1842a71bce1c8fdfe035e8f1b819e Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Wed, 21 Feb 2024 00:34:18 -0800 Subject: [PATCH 21/52] fix comments --- gps_ubxm8_i2c/gps.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 7a40325..b132add 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -17,6 +17,7 @@ * An example usage is as follows: * ``` * GPS myGPS; + * myGPS.Init(); * while(1) { * if(myGPS.PollUpdate(&i2c1) == GPS::PollResult::POLL_FINISHED) { * UBX_NAV_PVT_PAYLOAD pvtData = myGPS.GetSolution(); @@ -44,7 +45,7 @@ class GpsUbxM8I2c { POLL_ALREADY_FINISHED, // the ubx data was already ready after a previous PollUpdate call RECEIVE_IN_PROGRESS, // we found the UBX start bytes in the incoming stream but haven't read the entire message NO_DATA, // no data from GPS available - NO_UBX_DATA, // data read successfulyl but no UBX start bytes found + NO_UBX_DATA, // data read successfully but no UBX start bytes found DATA_LEN_POLL_FAILED, // there was a failure in the I2C mem read for getting the quantity of data available DATA_RECEIVE_I2C_FAILED, // there was a failure in the I2C receive to read the available data from the GPS DATA_RECEIVE_CHECKSUM_FAILED // we received UBX data but the checksum didn't match the message. From 106088d30f4cbf96f21cefa8d10da51f16267d78 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Wed, 21 Feb 2024 00:35:20 -0800 Subject: [PATCH 22/52] add newline --- gps_ubxm8_i2c/gps.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 84862a2..d3cdc22 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -154,4 +154,4 @@ bool GpsUbxM8I2c::sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c return false; } return true; -} \ No newline at end of file +} From 3a5fe53f48cba58acf1c5e8eea82a55f0dda67cc Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Wed, 21 Feb 2024 00:40:01 -0800 Subject: [PATCH 23/52] decrease column limit without doing this, it tried putting `Init` in gps.cc on a single line, which was really dumb. --- .clang-format | 2 +- gps_ubxm8_i2c/gps.cc | 1 - gps_ubxm8_i2c/gps.h | 17 +++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.clang-format b/.clang-format index c9b0aa7..64a4c37 100644 --- a/.clang-format +++ b/.clang-format @@ -1,5 +1,5 @@ BasedOnStyle: Google AccessModifierOffset: -2 -ColumnLimit: 200 +ColumnLimit: 120 IndentWidth: 4 AllowShortEnumsOnASingleLine: false diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index d3cdc22..1ba5f26 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -117,7 +117,6 @@ void GpsUbxM8I2c::Reset() { packetReader.reset(); } - /** * @brief Sends a UBX protocol message over i2c * diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index b132add..7e3cff0 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -29,7 +29,8 @@ * After a packet is received, you _need_ to call the reset method. * If you don't, `pollUpdate` will just do nothing and return a `POLL_ALREADY_FINISHED` response. * - * The datasheet is here: https://content.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_UBX-13003221.pdf + * The datasheet is here: + * https://content.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_UBX-13003221.pdf * The most relevant parts are "UBX Protocol" (section 32) and "DDC Port" (section 15). * */ @@ -41,13 +42,13 @@ class GpsUbxM8I2c { RESPONSE_READY }; enum class PollResult { - POLL_JUST_FINISHED, // the ubx data has been received on this invocation, and is now ready to be retrieved - POLL_ALREADY_FINISHED, // the ubx data was already ready after a previous PollUpdate call - RECEIVE_IN_PROGRESS, // we found the UBX start bytes in the incoming stream but haven't read the entire message - NO_DATA, // no data from GPS available - NO_UBX_DATA, // data read successfully but no UBX start bytes found - DATA_LEN_POLL_FAILED, // there was a failure in the I2C mem read for getting the quantity of data available - DATA_RECEIVE_I2C_FAILED, // there was a failure in the I2C receive to read the available data from the GPS + POLL_JUST_FINISHED, // the ubx data has been received on this invocation, and is now ready to be retrieved + POLL_ALREADY_FINISHED, // the ubx data was already ready after a previous PollUpdate call + RECEIVE_IN_PROGRESS, // we found the UBX start bytes in the incoming stream but haven't read the entire message + NO_DATA, // no data from GPS available + NO_UBX_DATA, // data read successfully but no UBX start bytes found + DATA_LEN_POLL_FAILED, // there was a failure in the I2C mem read for getting the quantity of data available + DATA_RECEIVE_I2C_FAILED, // there was a failure in the I2C receive to read the available data from the GPS DATA_RECEIVE_CHECKSUM_FAILED // we received UBX data but the checksum didn't match the message. }; GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin); From 1bd56a72ca1139b8181fd2585909f62bebdde377 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Wed, 21 Feb 2024 00:41:25 -0800 Subject: [PATCH 24/52] make private variables prefixed with underscore --- gps_ubxm8_i2c/gps.cc | 42 +++++++++++++++++++++--------------------- gps_ubxm8_i2c/gps.h | 4 ++-- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 1ba5f26..e6fdebc 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -7,15 +7,15 @@ #define GPS_I2C_TIMEOUT 100 GpsUbxM8I2c::GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin) { - packetReader = UBXPacketReader(); - state = GpsUbxM8I2c::State::REQUEST_NOT_SENT; + _packetReader = UBXPacketReader(); + _state = GpsUbxM8I2c::State::REQUEST_NOT_SENT; } -GpsUbxM8I2c::Init(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin) { +GpsUbxM8I2c::Init() { HAL_GPIO_WritePin(gpioResetPort, gpioResetPin, GPIO_PIN_SET); } -const GpsUbxM8I2c::State GpsUbxM8I2c::GetState() { return state; } +const GpsUbxM8I2c::State GpsUbxM8I2c::GetState() { return _state; } /** * @brief Sends a request for position data if none are currently pending, checks data available, @@ -24,13 +24,13 @@ const GpsUbxM8I2c::State GpsUbxM8I2c::GetState() { return state; } * @return a GpsUbxM8I2c::PollResult object. See the definition of that enum for details. */ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate(I2C_HandleTypeDef* i2c) { - if (state == GpsUbxM8I2c::State::REQUEST_NOT_SENT) { + if (_state == GpsUbxM8I2c::State::REQUEST_NOT_SENT) { uint8_t message[4] = {0x01, 0x07, 0x00, 0x00}; sendUBX(message, 4, &hi2c3); - state = GpsUbxM8I2c::State::POLLING_RESPONSE; + _state = GpsUbxM8I2c::State::POLLING_RESPONSE; } - if (state == GpsUbxM8I2c::State::POLLING_RESPONSE) { + if (_state == GpsUbxM8I2c::State::POLLING_RESPONSE) { uint8_t lenBytes[2]; uint16_t dataLen = 0; uint8_t buffer[I2C_BUFFER_SIZE]; @@ -53,15 +53,15 @@ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate(I2C_HandleTypeDef* i2c) { return GpsUbxM8I2c::PollResult::DATA_RECEIVE_I2C_FAILED; } - if (packetReader.isInProgress()) { + if (_packetReader.isInProgress()) { for (uint16_t i = 0; i < dataLen; i++) { - UBXPacketUpdateResult res = packetReader.update(buffer[i]); + UBXPacketUpdateResult res = _packetReader.update(buffer[i]); if (res == UBXPacketUpdateResult::CHECKSUM_FAILED) { - packetReader.reset(); + _packetReader.reset(); return GpsUbxM8I2c::PollResult::DATA_RECEIVE_CHECKSUM_FAILED; } - if (packetReader.isComplete()) { - state = GpsUbxM8I2c::State::RESPONSE_READY; + if (_packetReader.isComplete()) { + _state = GpsUbxM8I2c::State::RESPONSE_READY; return GpsUbxM8I2c::PollResult::POLL_JUST_FINISHED; } } @@ -70,10 +70,10 @@ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate(I2C_HandleTypeDef* i2c) { for (uint16_t i = 0; i < dataLen; i++) { if (buffer[i] == 0xB5 && buffer[i + 1] == 0x62) { i += 2; // skip the header - while (i < dataLen && !packetReader.isComplete()) { - UBXPacketUpdateResult res = packetReader.update(buffer[i]); + while (i < dataLen && !_packetReader.isComplete()) { + UBXPacketUpdateResult res = _packetReader.update(buffer[i]); if (res != UBXPacketUpdateResult::UPDATE_OK) { - packetReader.reset(); + _packetReader.reset(); return GpsUbxM8I2c::PollResult::DATA_RECEIVE_CHECKSUM_FAILED; } i++; @@ -81,12 +81,12 @@ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate(I2C_HandleTypeDef* i2c) { } } - if (!packetReader.isInProgress()) { + if (!_packetReader.isInProgress()) { return GpsUbxM8I2c::PollResult::NO_UBX_DATA; } - if (packetReader.isComplete()) { - state = GpsUbxM8I2c::State::RESPONSE_READY; + if (_packetReader.isComplete()) { + _state = GpsUbxM8I2c::State::RESPONSE_READY; return GpsUbxM8I2c::PollResult::POLL_JUST_FINISHED; } return GpsUbxM8I2c::PollResult::RECEIVE_IN_PROGRESS; @@ -106,15 +106,15 @@ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate(I2C_HandleTypeDef* i2c) { * * @retval UBX_NAV_PVT_PAYLOAD struct */ -const UBX_NAV_PVT_PAYLOAD GpsUbxM8I2c::GetSolution() { return *(UBX_NAV_PVT_PAYLOAD*)packetReader.getPayload(); } +const UBX_NAV_PVT_PAYLOAD GpsUbxM8I2c::GetSolution() { return *(UBX_NAV_PVT_PAYLOAD*)_packetReader.getPayload(); } /** * @brief Puts the GPS state back to its initial value so that `pollUpdate` knows * it needs to send a new data request. */ void GpsUbxM8I2c::Reset() { - state = GpsUbxM8I2c::State::REQUEST_NOT_SENT; - packetReader.reset(); + _state = GpsUbxM8I2c::State::REQUEST_NOT_SENT; + _packetReader.reset(); } /** diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 7e3cff0..b55d12e 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -59,7 +59,7 @@ class GpsUbxM8I2c { void Reset(); private: - UBXPacketReader packetReader; - State state; + UBXPacketReader _packetReader; + State _state; bool sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c); }; From d0c32bddf6300652a6f0a0be05ba624aad771c48 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Wed, 21 Feb 2024 00:42:28 -0800 Subject: [PATCH 25/52] make reset pin and port private members --- gps_ubxm8_i2c/gps.cc | 4 +++- gps_ubxm8_i2c/gps.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index e6fdebc..f38bf0e 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -9,10 +9,12 @@ GpsUbxM8I2c::GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin) { _packetReader = UBXPacketReader(); _state = GpsUbxM8I2c::State::REQUEST_NOT_SENT; + _gpioResetPin = gpioResetPin; + _gpioResetPort = gpioResetPort; } GpsUbxM8I2c::Init() { - HAL_GPIO_WritePin(gpioResetPort, gpioResetPin, GPIO_PIN_SET); + HAL_GPIO_WritePin(_gpioResetPort, _gpioResetPin, GPIO_PIN_SET); } const GpsUbxM8I2c::State GpsUbxM8I2c::GetState() { return _state; } diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index b55d12e..15d410a 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -61,5 +61,7 @@ class GpsUbxM8I2c { private: UBXPacketReader _packetReader; State _state; + GPIO_TypeDef* _gpioResetPort; + uint16_t _gpioResetPin bool sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c); }; From a747683bd6abc701387ecb7b7d5faf8bb41c584e Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Wed, 21 Feb 2024 00:43:08 -0800 Subject: [PATCH 26/52] replace hard-coded i2c header with macros --- gps_ubxm8_i2c/gps.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 15d410a..595c483 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -2,10 +2,13 @@ // if this is shitting itself, just locally replace it with whatever // header on your machine that can get you `I2C_HandleTypeDef` -// #if defined(STM32F1) -// #include "stm32f1xx_hal.h" -// #endif -#include "i2c.h" +#if defined(STM32F1) +#include "stm32f1xx_hal.h" +#endif +#if defined(STM32F4XX) +#include "stm32f4xx_hal.h" +#endif + #include "ubxMessages.h" #include "ubxPacket.h" From 4015ee31885cf50803ff0f88b03969c1fed3fad8 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Wed, 21 Feb 2024 00:45:14 -0800 Subject: [PATCH 27/52] succumb to function squashing removing args form Init made it shorter than 120 and I just gave up on trying to make it not squash --- .clang-format | 2 +- gps_ubxm8_i2c/gps.cc | 6 ++---- gps_ubxm8_i2c/gps.h | 16 ++++++++-------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/.clang-format b/.clang-format index 64a4c37..c9b0aa7 100644 --- a/.clang-format +++ b/.clang-format @@ -1,5 +1,5 @@ BasedOnStyle: Google AccessModifierOffset: -2 -ColumnLimit: 120 +ColumnLimit: 200 IndentWidth: 4 AllowShortEnumsOnASingleLine: false diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index f38bf0e..18e3b9c 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -10,12 +10,10 @@ GpsUbxM8I2c::GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin) { _packetReader = UBXPacketReader(); _state = GpsUbxM8I2c::State::REQUEST_NOT_SENT; _gpioResetPin = gpioResetPin; - _gpioResetPort = gpioResetPort; + _gpioResetPort = gpioResetPort; } -GpsUbxM8I2c::Init() { - HAL_GPIO_WritePin(_gpioResetPort, _gpioResetPin, GPIO_PIN_SET); -} +GpsUbxM8I2c::Init() { HAL_GPIO_WritePin(_gpioResetPort, _gpioResetPin, GPIO_PIN_SET); } const GpsUbxM8I2c::State GpsUbxM8I2c::GetState() { return _state; } diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 595c483..3fa8494 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -45,13 +45,13 @@ class GpsUbxM8I2c { RESPONSE_READY }; enum class PollResult { - POLL_JUST_FINISHED, // the ubx data has been received on this invocation, and is now ready to be retrieved - POLL_ALREADY_FINISHED, // the ubx data was already ready after a previous PollUpdate call - RECEIVE_IN_PROGRESS, // we found the UBX start bytes in the incoming stream but haven't read the entire message - NO_DATA, // no data from GPS available - NO_UBX_DATA, // data read successfully but no UBX start bytes found - DATA_LEN_POLL_FAILED, // there was a failure in the I2C mem read for getting the quantity of data available - DATA_RECEIVE_I2C_FAILED, // there was a failure in the I2C receive to read the available data from the GPS + POLL_JUST_FINISHED, // the ubx data has been received on this invocation, and is now ready to be retrieved + POLL_ALREADY_FINISHED, // the ubx data was already ready after a previous PollUpdate call + RECEIVE_IN_PROGRESS, // we found the UBX start bytes in the incoming stream but haven't read the entire message + NO_DATA, // no data from GPS available + NO_UBX_DATA, // data read successfully but no UBX start bytes found + DATA_LEN_POLL_FAILED, // there was a failure in the I2C mem read for getting the quantity of data available + DATA_RECEIVE_I2C_FAILED, // there was a failure in the I2C receive to read the available data from the GPS DATA_RECEIVE_CHECKSUM_FAILED // we received UBX data but the checksum didn't match the message. }; GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin); @@ -65,6 +65,6 @@ class GpsUbxM8I2c { UBXPacketReader _packetReader; State _state; GPIO_TypeDef* _gpioResetPort; - uint16_t _gpioResetPin + uint16_t _gpioResetPin; bool sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c); }; From 38d1f2afada8cdba2e2954037400c4a5bc09f335 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Wed, 21 Feb 2024 16:26:51 -0800 Subject: [PATCH 28/52] add ecef payload back to messages --- gps_ubxm8_i2c/ubxMessages.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/gps_ubxm8_i2c/ubxMessages.h b/gps_ubxm8_i2c/ubxMessages.h index 5d408a0..1cb4560 100644 --- a/gps_ubxm8_i2c/ubxMessages.h +++ b/gps_ubxm8_i2c/ubxMessages.h @@ -46,3 +46,25 @@ struct UBX_NAV_PVT_PAYLOAD { uint16_t magAcc; }; #pragma pack(pop) + +#pragma pack(push, 1) +struct UBX_NAV_SOL_PAYLOAD { // 0x01 0x06 + uint32_t iTOW; + int32_t fTOW; + int16_t week; + GPSFixType gpsFix; + uint8_t flags; + int32_t ecefX; + int32_t ecefY; + int32_t ecefZ; + uint32_t pAcc; + int32_t ecefVX; + int32_t ecefVY; + int32_t ecefVZ; + uint32_t sAcc; + uint16_t pDOP; + uint8_t reserved1; + uint8_t numSV; + uint8_t reserved2[4]; +}; +#pragma pack(pop) From 04d50aca790b674b27dcb65156eedab24dbae0fb Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Wed, 21 Feb 2024 16:47:39 -0800 Subject: [PATCH 29/52] un-hardcode what message the GPS is sending. --- gps_ubxm8_i2c/gps.cc | 27 +++++++++++++++------------ gps_ubxm8_i2c/gps.h | 10 ++++++---- gps_ubxm8_i2c/ubxMessages.h | 4 ++++ gps_ubxm8_i2c/ubxPacket.h | 10 +++++++++- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 18e3b9c..529d3be 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -6,11 +6,13 @@ #define I2C_BUFFER_SIZE 1024 #define GPS_I2C_TIMEOUT 100 -GpsUbxM8I2c::GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin) { +GpsUbxM8I2c::GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin, I2C_HandleTypeDef* i2c, uint8_t* ubxMessage) { _packetReader = UBXPacketReader(); _state = GpsUbxM8I2c::State::REQUEST_NOT_SENT; _gpioResetPin = gpioResetPin; _gpioResetPort = gpioResetPort; + _i2c = i2c; + _ubxMessage = ubxMessage; } GpsUbxM8I2c::Init() { HAL_GPIO_WritePin(_gpioResetPort, _gpioResetPin, GPIO_PIN_SET); } @@ -23,10 +25,9 @@ const GpsUbxM8I2c::State GpsUbxM8I2c::GetState() { return _state; } * * @return a GpsUbxM8I2c::PollResult object. See the definition of that enum for details. */ -const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate(I2C_HandleTypeDef* i2c) { +const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate() { if (_state == GpsUbxM8I2c::State::REQUEST_NOT_SENT) { - uint8_t message[4] = {0x01, 0x07, 0x00, 0x00}; - sendUBX(message, 4, &hi2c3); + sendUBX(_ubxMessage, 4); _state = GpsUbxM8I2c::State::POLLING_RESPONSE; } @@ -35,7 +36,7 @@ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate(I2C_HandleTypeDef* i2c) { uint16_t dataLen = 0; uint8_t buffer[I2C_BUFFER_SIZE]; - HAL_StatusTypeDef dataLenReadStatus = HAL_I2C_Mem_Read(i2c, 0x42 << 1, 0xFD, 1, lenBytes, 2, GPS_I2C_TIMEOUT); + HAL_StatusTypeDef dataLenReadStatus = HAL_I2C_Mem_Read(_i2c, 0x42 << 1, 0xFD, 1, lenBytes, 2, GPS_I2C_TIMEOUT); if (dataLenReadStatus != HAL_OK) { return GpsUbxM8I2c::PollResult::DATA_LEN_POLL_FAILED; } @@ -48,7 +49,7 @@ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate(I2C_HandleTypeDef* i2c) { if (dataLen > I2C_BUFFER_SIZE) { dataLen = I2C_BUFFER_SIZE; } - HAL_StatusTypeDef rcvStatus = HAL_I2C_Master_Receive(i2c, 0x42 << 1, buffer, dataLen, GPS_I2C_TIMEOUT); + HAL_StatusTypeDef rcvStatus = HAL_I2C_Master_Receive(_i2c, 0x42 << 1, buffer, dataLen, GPS_I2C_TIMEOUT); if (rcvStatus != HAL_OK) { return GpsUbxM8I2c::PollResult::DATA_RECEIVE_I2C_FAILED; } @@ -104,9 +105,9 @@ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate(I2C_HandleTypeDef* i2c) { * After calling this and using the info returned, getting the next * packet requires you to call `reset` and `pollUpdate` again. * - * @retval UBX_NAV_PVT_PAYLOAD struct + * @retval pointer to payload. Can be casted to a struct in ubxMessages. */ -const UBX_NAV_PVT_PAYLOAD GpsUbxM8I2c::GetSolution() { return *(UBX_NAV_PVT_PAYLOAD*)_packetReader.getPayload(); } +const void* GpsUbxM8I2c::GetSolution() { return _packetReader.getPayload(); } /** * @brief Puts the GPS state back to its initial value so that `pollUpdate` knows @@ -128,12 +129,14 @@ void GpsUbxM8I2c::Reset() { * @param len Length of `message` * @param i2c The HAL i2c handle to use for transmission. */ -bool GpsUbxM8I2c::sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c) { +bool GpsUbxM8I2c::sendUBX(uint8_t* message) { static uint8_t magicBytes[2] = {0xB5, 0x62}; + uint16_t len = 4+(uint16_t)message[2]<<8 + message[3]; + uint8_t CK_A{0}, CK_B{0}; HAL_StatusTypeDef status; - status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, magicBytes, 2, GPS_I2C_TIMEOUT); + status = HAL_I2C_Master_Transmit(_i2c, 0x42 << 1, magicBytes, 2, GPS_I2C_TIMEOUT); if (status != HAL_OK) { return false; } @@ -144,11 +147,11 @@ bool GpsUbxM8I2c::sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c } uint8_t CK[2] = {CK_A, CK_B}; - status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, message, len, GPS_I2C_TIMEOUT); + status = HAL_I2C_Master_Transmit(_i2c, 0x42 << 1, message, len, GPS_I2C_TIMEOUT); if (status != HAL_OK) { return false; } - status = HAL_I2C_Master_Transmit(i2c, 0x42 << 1, CK, 2, GPS_I2C_TIMEOUT); + status = HAL_I2C_Master_Transmit(_i2c, 0x42 << 1, CK, 2, GPS_I2C_TIMEOUT); if (status != HAL_OK) { return false; } diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 3fa8494..1ad8629 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -19,10 +19,10 @@ * This class keeps its own finite state machine for abstracting away polling data availability and retrying requests. * An example usage is as follows: * ``` - * GPS myGPS; + * GPS myGPS(GPS_RESET_PORT, GPS_RESET_PIN, &hi2c3, PVT_MESSAGE); * myGPS.Init(); * while(1) { - * if(myGPS.PollUpdate(&i2c1) == GPS::PollResult::POLL_FINISHED) { + * if(myGPS.PollUpdate() == GPS::PollResult::POLL_FINISHED) { * UBX_NAV_PVT_PAYLOAD pvtData = myGPS.GetSolution(); * myGPS.Reset(); * } @@ -58,7 +58,7 @@ class GpsUbxM8I2c { void Init(); const State GetState(); const PollResult PollUpdate(I2C_HandleTypeDef* i2c); - const UBX_NAV_PVT_PAYLOAD GetSolution(); + const void* GetSolution(); void Reset(); private: @@ -66,5 +66,7 @@ class GpsUbxM8I2c { State _state; GPIO_TypeDef* _gpioResetPort; uint16_t _gpioResetPin; - bool sendUBX(uint8_t* message, uint16_t len, I2C_HandleTypeDef* i2c); + I2C_HandleTypeDef* _i2c; + uint8_t* _ubxMessage; + bool sendUBX(uint8_t* message); }; diff --git a/gps_ubxm8_i2c/ubxMessages.h b/gps_ubxm8_i2c/ubxMessages.h index 1cb4560..75ab33a 100644 --- a/gps_ubxm8_i2c/ubxMessages.h +++ b/gps_ubxm8_i2c/ubxMessages.h @@ -10,6 +10,8 @@ enum class GPSFixType : uint8_t { TIME_ONLY_FIX }; +const static uint8_t PVT_MESSAGE[4] = {0x01, 0x07, 0x00, 0x00}; + #pragma pack(push, 1) struct UBX_NAV_PVT_PAYLOAD { uint32_t iTOW; @@ -47,6 +49,8 @@ struct UBX_NAV_PVT_PAYLOAD { }; #pragma pack(pop) +const static uint8_t SOL_MESSAGE[4] = {0x01, 0x06, 0x00, 0x00}; + #pragma pack(push, 1) struct UBX_NAV_SOL_PAYLOAD { // 0x01 0x06 uint32_t iTOW; diff --git a/gps_ubxm8_i2c/ubxPacket.h b/gps_ubxm8_i2c/ubxPacket.h index 3b72bd5..3d041b7 100644 --- a/gps_ubxm8_i2c/ubxPacket.h +++ b/gps_ubxm8_i2c/ubxPacket.h @@ -2,6 +2,10 @@ #include +#ifndef PACKET_READER_PAYLOAD_SIZE +#define PACKET_READER_PAYLOAD_SIZE 512 +#endif + enum class UBXPacketUpdateResult { UPDATE_OK, CHECKSUM_FAILED, @@ -9,6 +13,10 @@ enum class UBXPacketUpdateResult { PACKET_INDEX_OVERFLOW // indicates internal error with packet reader }; +/** + * reads a ubx payload byte-by-byte into an internal buffer. The size of this is configurable with + * the macro PACKET_READER_PAYLOAD_SIZE +*/ class UBXPacketReader { public: UBXPacketReader(); @@ -22,7 +30,7 @@ class UBXPacketReader { void reset(); private: - uint8_t payload[512]; + uint8_t payload[PACKET_READER_PAYLOAD_SIZE]; uint8_t payloadLength; uint8_t packetIndex; uint8_t messageClass; From 4e2f6f046e0cfcc39f55ea1ae4cfa1d03290f6de Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Thu, 22 Feb 2024 22:48:19 -0800 Subject: [PATCH 30/52] fix syntax errors from not building earlier --- gps_ubxm8_i2c/gps.cc | 6 +++--- gps_ubxm8_i2c/gps.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 529d3be..197f57f 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -15,7 +15,7 @@ GpsUbxM8I2c::GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin, I2C _ubxMessage = ubxMessage; } -GpsUbxM8I2c::Init() { HAL_GPIO_WritePin(_gpioResetPort, _gpioResetPin, GPIO_PIN_SET); } +void GpsUbxM8I2c::Init() { HAL_GPIO_WritePin(_gpioResetPort, _gpioResetPin, GPIO_PIN_SET); } const GpsUbxM8I2c::State GpsUbxM8I2c::GetState() { return _state; } @@ -27,7 +27,7 @@ const GpsUbxM8I2c::State GpsUbxM8I2c::GetState() { return _state; } */ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate() { if (_state == GpsUbxM8I2c::State::REQUEST_NOT_SENT) { - sendUBX(_ubxMessage, 4); + sendUBX(_ubxMessage); _state = GpsUbxM8I2c::State::POLLING_RESPONSE; } @@ -131,7 +131,7 @@ void GpsUbxM8I2c::Reset() { */ bool GpsUbxM8I2c::sendUBX(uint8_t* message) { static uint8_t magicBytes[2] = {0xB5, 0x62}; - uint16_t len = 4+(uint16_t)message[2]<<8 + message[3]; + uint16_t len = 4 + (uint16_t)message[2] << 8 + message[3]; uint8_t CK_A{0}, CK_B{0}; diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 1ad8629..fc47887 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -54,10 +54,10 @@ class GpsUbxM8I2c { DATA_RECEIVE_I2C_FAILED, // there was a failure in the I2C receive to read the available data from the GPS DATA_RECEIVE_CHECKSUM_FAILED // we received UBX data but the checksum didn't match the message. }; - GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin); + GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin, I2C_HandleTypeDef* i2c, uint8_t* ubxMessage); void Init(); const State GetState(); - const PollResult PollUpdate(I2C_HandleTypeDef* i2c); + const PollResult PollUpdate(); const void* GetSolution(); void Reset(); From e91c12179e9aa520201dea276360f08ff781d0c7 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Thu, 22 Feb 2024 23:14:01 -0800 Subject: [PATCH 31/52] add extra parens --- gps_ubxm8_i2c/gps.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 197f57f..c411d4d 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -131,7 +131,7 @@ void GpsUbxM8I2c::Reset() { */ bool GpsUbxM8I2c::sendUBX(uint8_t* message) { static uint8_t magicBytes[2] = {0xB5, 0x62}; - uint16_t len = 4 + (uint16_t)message[2] << 8 + message[3]; + uint16_t len = 4 + ((uint16_t)message[2] << 8) + message[3]; uint8_t CK_A{0}, CK_B{0}; From df910ccfeab8fdc89c310424faf3f785f330e28c Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Thu, 22 Feb 2024 23:14:23 -0800 Subject: [PATCH 32/52] add ecef conversion helper --- gps_ubxm8_i2c/coordHelpers.cc | 24 ++++++++++++++++++++++++ gps_ubxm8_i2c/coordHelpers.h | 1 + 2 files changed, 25 insertions(+) create mode 100644 gps_ubxm8_i2c/coordHelpers.cc create mode 100644 gps_ubxm8_i2c/coordHelpers.h diff --git a/gps_ubxm8_i2c/coordHelpers.cc b/gps_ubxm8_i2c/coordHelpers.cc new file mode 100644 index 0000000..81fafd0 --- /dev/null +++ b/gps_ubxm8_i2c/coordHelpers.cc @@ -0,0 +1,24 @@ +#include "coordHelpers.h" + +#include + +const double a = 6378137.0; // WGS-84 semi-major axis +const double e2 = 6.6943799901377997e-3; // WGS-84 first eccentricity squared +const double a1 = 4.2697672707157535e+4; // a1 = a*e2 +const double a2 = 1.8230912546075455e+9; // a2 = a1*a1 +const double a3 = 1.4291722289812413e+2; // a3 = a1*e2/2 +const double a4 = 4.5577281365188637e+9; // a4 = 2.5*a2 +const double a5 = 4.2840589930055659e+4; // a5 = a1+a3 +const double a6 = 9.9330562000986220e-1; // a6 = 1-e2 + +static double ecef[3]; +// Convert Lat, Lon, Altitude to Earth-Centered-Earth-Fixed (ECEF) +// Input is a three element array containing lat, lon (rads) and alt (m) +// Returned array contains x, y, z in meters +double* geo_to_ecef(double lon, double lat, double alt) { + double n = a / sqrt(1 - e2 * sin(lat) * sin(lat)); + ecef[0] = (n + alt) * cos(lat) * cos(lon); // ECEF x + ecef[1] = (n + alt) * cos(lat) * sin(lon); // ECEF y + ecef[2] = (n * (1 - e2) + alt) * sin(lat); // ECEF z + return (ecef); // Return x, y, z in ECEF +} diff --git a/gps_ubxm8_i2c/coordHelpers.h b/gps_ubxm8_i2c/coordHelpers.h new file mode 100644 index 0000000..172c8e8 --- /dev/null +++ b/gps_ubxm8_i2c/coordHelpers.h @@ -0,0 +1 @@ +double* geo_to_ecef(double* geo); From 03be05a7ccc060376361162671b7d3b2cd9586db Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Thu, 22 Feb 2024 23:14:37 -0800 Subject: [PATCH 33/52] un-const messages --- gps_ubxm8_i2c/ubxMessages.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gps_ubxm8_i2c/ubxMessages.h b/gps_ubxm8_i2c/ubxMessages.h index 75ab33a..799223e 100644 --- a/gps_ubxm8_i2c/ubxMessages.h +++ b/gps_ubxm8_i2c/ubxMessages.h @@ -10,7 +10,7 @@ enum class GPSFixType : uint8_t { TIME_ONLY_FIX }; -const static uint8_t PVT_MESSAGE[4] = {0x01, 0x07, 0x00, 0x00}; +static uint8_t PVT_MESSAGE[4] = {0x01, 0x07, 0x00, 0x00}; #pragma pack(push, 1) struct UBX_NAV_PVT_PAYLOAD { @@ -49,10 +49,10 @@ struct UBX_NAV_PVT_PAYLOAD { }; #pragma pack(pop) -const static uint8_t SOL_MESSAGE[4] = {0x01, 0x06, 0x00, 0x00}; +static uint8_t SOL_MESSAGE[4] = {0x01, 0x06, 0x00, 0x00}; #pragma pack(push, 1) -struct UBX_NAV_SOL_PAYLOAD { // 0x01 0x06 +struct UBX_NAV_SOL_PAYLOAD { // 0x01 0x06 uint32_t iTOW; int32_t fTOW; int16_t week; From 143f797986ba706bbc6a4e9bcee99e8abd1a580c Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Thu, 22 Feb 2024 23:33:47 -0800 Subject: [PATCH 34/52] start working on coordinate conversion --- gps_ubxm8_i2c/coordHelpers.h | 2 +- gps_ubxm8_i2c/gps.cc | 36 ++++++++++++++++++++++++++++++++++++ gps_ubxm8_i2c/gps.h | 4 ++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/gps_ubxm8_i2c/coordHelpers.h b/gps_ubxm8_i2c/coordHelpers.h index 172c8e8..09fe0ea 100644 --- a/gps_ubxm8_i2c/coordHelpers.h +++ b/gps_ubxm8_i2c/coordHelpers.h @@ -1 +1 @@ -double* geo_to_ecef(double* geo); +double* geo_to_ecef(double lon, double lat, double alt); diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index c411d4d..3da4fec 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -1,11 +1,17 @@ #include "gps.h" +#include + +#include "coordHelpers.h" #include "ubxMessages.h" #include "ubxPacket.h" #define I2C_BUFFER_SIZE 1024 #define GPS_I2C_TIMEOUT 100 +/** + * @param ubxMessage one of the messages from `ubxMessages.h` to send. + */ GpsUbxM8I2c::GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin, I2C_HandleTypeDef* i2c, uint8_t* ubxMessage) { _packetReader = UBXPacketReader(); _state = GpsUbxM8I2c::State::REQUEST_NOT_SENT; @@ -118,6 +124,36 @@ void GpsUbxM8I2c::Reset() { _packetReader.reset(); } +UBX_NAV_SOL_PAYLOAD ConvertPayloadToECEF(UBX_NAV_PVT_PAYLOAD pvtPayload) { + UBX_NAV_SOL_PAYLOAD payload; + double lat = (double)pvtPayload.lat / 1e7; + double lon = (double)pvtPayload.lon / 1e7; + double alt = (double)pvtPayload.height / 1000; + double* ecef = geo_to_ecef(lat, lon, alt); + + payload.iTOW = pvtPayload.iTOW; + payload.fTOW = pvtPayload.iTOW; + payload.week = 0; // ??? + payload.gpsFix = pvtPayload.fixType; + payload.flags = pvtPayload.flags; + payload.ecefX = ecef[0]; + payload.ecefY = ecef[1]; + payload.ecefZ = ecef[2]; + payload.pAcc = pvtPayload.hAcc; + + // convert velocity to ECEF about the lat and lon + double velN = (double)pvtPayload.velN / 1000; + double velE = (double)pvtPayload.velE / 1000; + double velD = (double)pvtPayload.velD / 1000; + + double cosLat = cos(lat); + double sinLat = sin(lat); + double cosLon = cos(lon); + double sinLon = sin(lon); + + // TODO: actually convert to ECEF +} + /** * @brief Sends a UBX protocol message over i2c * diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index fc47887..20fad95 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -9,6 +9,9 @@ #include "stm32f4xx_hal.h" #endif +#include +#include + #include "ubxMessages.h" #include "ubxPacket.h" @@ -60,6 +63,7 @@ class GpsUbxM8I2c { const PollResult PollUpdate(); const void* GetSolution(); void Reset(); + UBX_NAV_SOL_PAYLOAD ConvertPayloadToECEF(UBX_NAV_PVT_PAYLOAD pvtPayload); private: UBXPacketReader _packetReader; From 080f3cb02749790d11e0d6c56fa3226798dcfa64 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Thu, 22 Feb 2024 23:33:54 -0800 Subject: [PATCH 35/52] add datesheet links to message structs --- gps_ubxm8_i2c/ubxMessages.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gps_ubxm8_i2c/ubxMessages.h b/gps_ubxm8_i2c/ubxMessages.h index 799223e..48b737d 100644 --- a/gps_ubxm8_i2c/ubxMessages.h +++ b/gps_ubxm8_i2c/ubxMessages.h @@ -12,6 +12,7 @@ enum class GPSFixType : uint8_t { static uint8_t PVT_MESSAGE[4] = {0x01, 0x07, 0x00, 0x00}; +// https://content.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_UBX-13003221.pdf#%5B%7B%22num%22%3A777%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C0%2C654.8%2Cnull%5D #pragma pack(push, 1) struct UBX_NAV_PVT_PAYLOAD { uint32_t iTOW; @@ -51,6 +52,7 @@ struct UBX_NAV_PVT_PAYLOAD { static uint8_t SOL_MESSAGE[4] = {0x01, 0x06, 0x00, 0x00}; +// https://content.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_UBX-13003221.pdf#%5B%7B%22num%22%3A799%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C0%2C525.5%2Cnull%5D #pragma pack(push, 1) struct UBX_NAV_SOL_PAYLOAD { // 0x01 0x06 uint32_t iTOW; From 0df94181296c8f540e11a2076205818fcde11bdb Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sat, 24 Feb 2024 21:44:36 -0800 Subject: [PATCH 36/52] convert coords to ECEF --- gps_ubxm8_i2c/coordHelpers.cc | 56 ++++++++++++++++++++++------------- gps_ubxm8_i2c/coordHelpers.h | 11 ++++++- gps_ubxm8_i2c/gps.cc | 27 ++++++----------- gps_ubxm8_i2c/gps.h | 2 +- gps_ubxm8_i2c/ubxMessages.h | 30 +++++++------------ 5 files changed, 65 insertions(+), 61 deletions(-) diff --git a/gps_ubxm8_i2c/coordHelpers.cc b/gps_ubxm8_i2c/coordHelpers.cc index 81fafd0..749df9b 100644 --- a/gps_ubxm8_i2c/coordHelpers.cc +++ b/gps_ubxm8_i2c/coordHelpers.cc @@ -1,24 +1,38 @@ #include "coordHelpers.h" -#include - -const double a = 6378137.0; // WGS-84 semi-major axis -const double e2 = 6.6943799901377997e-3; // WGS-84 first eccentricity squared -const double a1 = 4.2697672707157535e+4; // a1 = a*e2 -const double a2 = 1.8230912546075455e+9; // a2 = a1*a1 -const double a3 = 1.4291722289812413e+2; // a3 = a1*e2/2 -const double a4 = 4.5577281365188637e+9; // a4 = 2.5*a2 -const double a5 = 4.2840589930055659e+4; // a5 = a1+a3 -const double a6 = 9.9330562000986220e-1; // a6 = 1-e2 - -static double ecef[3]; -// Convert Lat, Lon, Altitude to Earth-Centered-Earth-Fixed (ECEF) -// Input is a three element array containing lat, lon (rads) and alt (m) -// Returned array contains x, y, z in meters -double* geo_to_ecef(double lon, double lat, double alt) { - double n = a / sqrt(1 - e2 * sin(lat) * sin(lat)); - ecef[0] = (n + alt) * cos(lat) * cos(lon); // ECEF x - ecef[1] = (n + alt) * cos(lat) * sin(lon); // ECEF y - ecef[2] = (n * (1 - e2) + alt) * sin(lat); // ECEF z - return (ecef); // Return x, y, z in ECEF +#include + +// Constants for WGS84 ellipsoid +const double WGS84_A = 6378137.0; // semi-major axis in meters +const double WGS84_INV_FLATTENING = 298.257223563; // inverse flattening + +// Convert degrees to radians +double Deg2Rad(double deg) { return deg * M_PI / 180.0; } + +// Convert radians to degrees +double Rad2Deg(double rad) { return rad * 180.0 / M_PI; } + +// Convert GPS coordinates (latitude, longitude, altitude) to ECEF coordinates +void GPS2ECEF(double lat, double lon, double alt, double& x, double& y, double& z) { + double cos_lat = cos(Deg2Rad(lat)); + double sin_lat = sin(Deg2Rad(lat)); + double cos_lon = cos(Deg2Rad(lon)); + double sin_lon = sin(Deg2Rad(lon)); + + double N = WGS84_A / sqrt(1 - pow((1 - 1 / WGS84_INV_FLATTENING) * sin_lat, 2)); + + x = (N + alt) * cos_lat * cos_lon; + y = (N + alt) * cos_lat * sin_lon; + z = (N * (1 - 1 / WGS84_INV_FLATTENING) + alt) * sin_lat; +} + +// Convert NED (North-East-Down) velocity to ECEF velocity +void NED2ECEFVel(double lat, double lon, double alt, double vn, double ve, double vd, double& vx, double& vy, double& vz) { + double x, y, z; + GPS2ECEF(lat, lon, alt, x, y, z); + + // Convert NED velocity to ECEF velocity + vx = -ve * sin(Deg2Rad(lon)) - vn * sin(Deg2Rad(lat)) * cos(Deg2Rad(lon)) + vd * cos(Deg2Rad(lat)) * cos(Deg2Rad(lon)); + vy = ve * cos(Deg2Rad(lon)) - vn * sin(Deg2Rad(lat)) * sin(Deg2Rad(lon)) + vd * cos(Deg2Rad(lat)) * sin(Deg2Rad(lon)); + vz = vn * cos(Deg2Rad(lat)) + vd * sin(Deg2Rad(lat)); } diff --git a/gps_ubxm8_i2c/coordHelpers.h b/gps_ubxm8_i2c/coordHelpers.h index 09fe0ea..c9e42c8 100644 --- a/gps_ubxm8_i2c/coordHelpers.h +++ b/gps_ubxm8_i2c/coordHelpers.h @@ -1 +1,10 @@ -double* geo_to_ecef(double lon, double lat, double alt); +// Convert degrees to radians +double Deg2Rad(double deg); + +// Convert radians to degrees +double Rad2Deg(double rad); +// Convert GPS coordinates (latitude, longitude, altitude) to ECEF coordinates +void GPS2ECEF(double lat, double lon, double alt, double& x, double& y, double& z); + +// Convert NED (North-East-Down) velocity to ECEF velocity +void NED2ECEFVel(double lat, double lon, double alt, double vn, double ve, double vd, double& vx, double& vy, double& vz); diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 3da4fec..4be8ed7 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -124,34 +124,25 @@ void GpsUbxM8I2c::Reset() { _packetReader.reset(); } -UBX_NAV_SOL_PAYLOAD ConvertPayloadToECEF(UBX_NAV_PVT_PAYLOAD pvtPayload) { - UBX_NAV_SOL_PAYLOAD payload; +UCIRP_GPS_PAYLOAD ConvertPayloadToECEF(UBX_NAV_PVT_PAYLOAD pvtPayload) { + UCIRP_GPS_PAYLOAD payload; + payload.gpsFix = pvtPayload.fixType; + payload.horizontalPositionAcc = (double)pvtPayload.hAcc / 1000; + payload.verticalPositionAcc = (double)pvtPayload.vAcc / 1000; + payload.speedAcc = (double)pvtPayload.sAcc / 1000; + double lat = (double)pvtPayload.lat / 1e7; double lon = (double)pvtPayload.lon / 1e7; double alt = (double)pvtPayload.height / 1000; - double* ecef = geo_to_ecef(lat, lon, alt); - payload.iTOW = pvtPayload.iTOW; - payload.fTOW = pvtPayload.iTOW; - payload.week = 0; // ??? - payload.gpsFix = pvtPayload.fixType; - payload.flags = pvtPayload.flags; - payload.ecefX = ecef[0]; - payload.ecefY = ecef[1]; - payload.ecefZ = ecef[2]; - payload.pAcc = pvtPayload.hAcc; + GPS2ECEF(lat, lon, alt, payload.ecefX, payload.ecefY, payload.ecefZ); // convert velocity to ECEF about the lat and lon double velN = (double)pvtPayload.velN / 1000; double velE = (double)pvtPayload.velE / 1000; double velD = (double)pvtPayload.velD / 1000; - double cosLat = cos(lat); - double sinLat = sin(lat); - double cosLon = cos(lon); - double sinLon = sin(lon); - - // TODO: actually convert to ECEF + NED2ECEFVel(lat, lon, alt, velN, velE, velD, payload.ecefVX, payload.ecefVY, payload.ecefVZ); } /** diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 20fad95..baa3cb9 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -63,7 +63,7 @@ class GpsUbxM8I2c { const PollResult PollUpdate(); const void* GetSolution(); void Reset(); - UBX_NAV_SOL_PAYLOAD ConvertPayloadToECEF(UBX_NAV_PVT_PAYLOAD pvtPayload); + UCIRP_GPS_PAYLOAD ConvertPayloadToECEF(UBX_NAV_PVT_PAYLOAD pvtPayload); private: UBXPacketReader _packetReader; diff --git a/gps_ubxm8_i2c/ubxMessages.h b/gps_ubxm8_i2c/ubxMessages.h index 48b737d..a76c1db 100644 --- a/gps_ubxm8_i2c/ubxMessages.h +++ b/gps_ubxm8_i2c/ubxMessages.h @@ -50,27 +50,17 @@ struct UBX_NAV_PVT_PAYLOAD { }; #pragma pack(pop) -static uint8_t SOL_MESSAGE[4] = {0x01, 0x06, 0x00, 0x00}; - -// https://content.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_UBX-13003221.pdf#%5B%7B%22num%22%3A799%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C0%2C525.5%2Cnull%5D #pragma pack(push, 1) -struct UBX_NAV_SOL_PAYLOAD { // 0x01 0x06 - uint32_t iTOW; - int32_t fTOW; - int16_t week; +struct UCIRP_GPS_PAYLOAD { // our custom struct GPSFixType gpsFix; - uint8_t flags; - int32_t ecefX; - int32_t ecefY; - int32_t ecefZ; - uint32_t pAcc; - int32_t ecefVX; - int32_t ecefVY; - int32_t ecefVZ; - uint32_t sAcc; - uint16_t pDOP; - uint8_t reserved1; - uint8_t numSV; - uint8_t reserved2[4]; + double ecefX; + double ecefY; + double ecefZ; + double horizontalPositionAcc; + double verticalPositionAcc; + double ecefVX; + double ecefVY; + double ecefVZ; + double speedAcc; }; #pragma pack(pop) From 459a1cc9da6d5941808d9126d574e5bb9108a52d Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sat, 24 Feb 2024 21:53:04 -0800 Subject: [PATCH 37/52] fix whitespace problem --- gps_ubxm8_i2c/ubxPacket.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gps_ubxm8_i2c/ubxPacket.h b/gps_ubxm8_i2c/ubxPacket.h index 3d041b7..fb60a04 100644 --- a/gps_ubxm8_i2c/ubxPacket.h +++ b/gps_ubxm8_i2c/ubxPacket.h @@ -16,7 +16,7 @@ enum class UBXPacketUpdateResult { /** * reads a ubx payload byte-by-byte into an internal buffer. The size of this is configurable with * the macro PACKET_READER_PAYLOAD_SIZE -*/ + */ class UBXPacketReader { public: UBXPacketReader(); From 35dbd3f0cea2888c93deaa6b34b173f600516504 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Wed, 6 Mar 2024 16:47:02 -0800 Subject: [PATCH 38/52] fix math includes --- gps_ubxm8_i2c/coordHelpers.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gps_ubxm8_i2c/coordHelpers.cc b/gps_ubxm8_i2c/coordHelpers.cc index 749df9b..b28709a 100644 --- a/gps_ubxm8_i2c/coordHelpers.cc +++ b/gps_ubxm8_i2c/coordHelpers.cc @@ -1,6 +1,7 @@ #include "coordHelpers.h" -#include +#include +#define M_PI 3.14159265358979323 // Constants for WGS84 ellipsoid const double WGS84_A = 6378137.0; // semi-major axis in meters From 27f57f0df4d289bf30f55181a81e95f65a796551 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 24 Mar 2024 18:33:03 -0700 Subject: [PATCH 39/52] add include guard on coorhelpers header --- gps_ubxm8_i2c/coordHelpers.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gps_ubxm8_i2c/coordHelpers.h b/gps_ubxm8_i2c/coordHelpers.h index c9e42c8..6a04806 100644 --- a/gps_ubxm8_i2c/coordHelpers.h +++ b/gps_ubxm8_i2c/coordHelpers.h @@ -1,3 +1,4 @@ +#pragma once // Convert degrees to radians double Deg2Rad(double deg); From 9e486a0d2a61f217159dc4808433dcdcd5a57e99 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 24 Mar 2024 18:33:44 -0700 Subject: [PATCH 40/52] pascal case function names --- gps_ubxm8_i2c/coordHelpers.cc | 6 +++--- gps_ubxm8_i2c/coordHelpers.h | 4 ++-- gps_ubxm8_i2c/gps.cc | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gps_ubxm8_i2c/coordHelpers.cc b/gps_ubxm8_i2c/coordHelpers.cc index b28709a..fbf8287 100644 --- a/gps_ubxm8_i2c/coordHelpers.cc +++ b/gps_ubxm8_i2c/coordHelpers.cc @@ -14,7 +14,7 @@ double Deg2Rad(double deg) { return deg * M_PI / 180.0; } double Rad2Deg(double rad) { return rad * 180.0 / M_PI; } // Convert GPS coordinates (latitude, longitude, altitude) to ECEF coordinates -void GPS2ECEF(double lat, double lon, double alt, double& x, double& y, double& z) { +void Gps2Ecef(double lat, double lon, double alt, double& x, double& y, double& z) { double cos_lat = cos(Deg2Rad(lat)); double sin_lat = sin(Deg2Rad(lat)); double cos_lon = cos(Deg2Rad(lon)); @@ -28,9 +28,9 @@ void GPS2ECEF(double lat, double lon, double alt, double& x, double& y, double& } // Convert NED (North-East-Down) velocity to ECEF velocity -void NED2ECEFVel(double lat, double lon, double alt, double vn, double ve, double vd, double& vx, double& vy, double& vz) { +void Ned2EcefVel(double lat, double lon, double alt, double vn, double ve, double vd, double& vx, double& vy, double& vz) { double x, y, z; - GPS2ECEF(lat, lon, alt, x, y, z); + Gps2Ecef(lat, lon, alt, x, y, z); // Convert NED velocity to ECEF velocity vx = -ve * sin(Deg2Rad(lon)) - vn * sin(Deg2Rad(lat)) * cos(Deg2Rad(lon)) + vd * cos(Deg2Rad(lat)) * cos(Deg2Rad(lon)); diff --git a/gps_ubxm8_i2c/coordHelpers.h b/gps_ubxm8_i2c/coordHelpers.h index 6a04806..1aa2b4b 100644 --- a/gps_ubxm8_i2c/coordHelpers.h +++ b/gps_ubxm8_i2c/coordHelpers.h @@ -5,7 +5,7 @@ double Deg2Rad(double deg); // Convert radians to degrees double Rad2Deg(double rad); // Convert GPS coordinates (latitude, longitude, altitude) to ECEF coordinates -void GPS2ECEF(double lat, double lon, double alt, double& x, double& y, double& z); +void Gps2Ecef(double lat, double lon, double alt, double& x, double& y, double& z); // Convert NED (North-East-Down) velocity to ECEF velocity -void NED2ECEFVel(double lat, double lon, double alt, double vn, double ve, double vd, double& vx, double& vy, double& vz); +void Ned2EcefVel(double lat, double lon, double alt, double vn, double ve, double vd, double& vx, double& vy, double& vz); diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 4be8ed7..0de12a2 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -135,14 +135,14 @@ UCIRP_GPS_PAYLOAD ConvertPayloadToECEF(UBX_NAV_PVT_PAYLOAD pvtPayload) { double lon = (double)pvtPayload.lon / 1e7; double alt = (double)pvtPayload.height / 1000; - GPS2ECEF(lat, lon, alt, payload.ecefX, payload.ecefY, payload.ecefZ); + Gps2Ecef(lat, lon, alt, payload.ecefX, payload.ecefY, payload.ecefZ); // convert velocity to ECEF about the lat and lon double velN = (double)pvtPayload.velN / 1000; double velE = (double)pvtPayload.velE / 1000; double velD = (double)pvtPayload.velD / 1000; - NED2ECEFVel(lat, lon, alt, velN, velE, velD, payload.ecefVX, payload.ecefVY, payload.ecefVZ); + Ned2EcefVel(lat, lon, alt, velN, velE, velD, payload.ecefVX, payload.ecefVY, payload.ecefVZ); } /** From 5f5f7f3e21020aa759e48b0869faae1631ae50ba Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 24 Mar 2024 18:34:46 -0700 Subject: [PATCH 41/52] fix macros --- gps_ubxm8_i2c/gps.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index baa3cb9..2d97871 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -4,14 +4,10 @@ // header on your machine that can get you `I2C_HandleTypeDef` #if defined(STM32F1) #include "stm32f1xx_hal.h" -#endif -#if defined(STM32F4XX) +#elif defined(STM32F4xx) #include "stm32f4xx_hal.h" #endif -#include -#include - #include "ubxMessages.h" #include "ubxPacket.h" From 6b27138b5cbf03e99fb24cabf8073fa698193d4a Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 24 Mar 2024 18:36:12 -0700 Subject: [PATCH 42/52] rename and dont ifndef packet reader size --- gps_ubxm8_i2c/ubxPacket.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/gps_ubxm8_i2c/ubxPacket.h b/gps_ubxm8_i2c/ubxPacket.h index fb60a04..930f8bb 100644 --- a/gps_ubxm8_i2c/ubxPacket.h +++ b/gps_ubxm8_i2c/ubxPacket.h @@ -2,9 +2,7 @@ #include -#ifndef PACKET_READER_PAYLOAD_SIZE -#define PACKET_READER_PAYLOAD_SIZE 512 -#endif +#define GPS_PACKET_READER_PAYLOAD_SIZE 512 enum class UBXPacketUpdateResult { UPDATE_OK, @@ -15,7 +13,7 @@ enum class UBXPacketUpdateResult { /** * reads a ubx payload byte-by-byte into an internal buffer. The size of this is configurable with - * the macro PACKET_READER_PAYLOAD_SIZE + * the macro GPS_PACKET_READER_PAYLOAD_SIZE */ class UBXPacketReader { public: @@ -30,7 +28,7 @@ class UBXPacketReader { void reset(); private: - uint8_t payload[PACKET_READER_PAYLOAD_SIZE]; + uint8_t payload[GPS_PACKET_READER_PAYLOAD_SIZE]; uint8_t payloadLength; uint8_t packetIndex; uint8_t messageClass; From e049ea2ffbf76f365d4af05f2f644b3af05af170 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 24 Mar 2024 18:36:59 -0700 Subject: [PATCH 43/52] shorten datasheet link --- gps_ubxm8_i2c/ubxMessages.h | 53 ++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/gps_ubxm8_i2c/ubxMessages.h b/gps_ubxm8_i2c/ubxMessages.h index a76c1db..071c307 100644 --- a/gps_ubxm8_i2c/ubxMessages.h +++ b/gps_ubxm8_i2c/ubxMessages.h @@ -12,7 +12,58 @@ enum class GPSFixType : uint8_t { static uint8_t PVT_MESSAGE[4] = {0x01, 0x07, 0x00, 0x00}; -// https://content.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_UBX-13003221.pdf#%5B%7B%22num%22%3A777%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C0%2C654.8%2Cnull%5D +// https://content.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_UBX-13003221.pdf +#pragma pack(push, 1) +struct UBX_NAV_PVT_PAYLOAD { + uint32_t iTOW; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t min; + uint8_t sec; + uint8_t valid; + uint32_t tAcc; + int32_t nano; + GPSFixType fixType; + uint8_t flags; + uint8_t flags2; + uint8_t numSV; + int32_t lon; + int32_t lat; + int32_t height; + int32_t hMSL; + uint32_t hAcc; + uint32_t vAcc; + int32_t velN; + int32_t velE; + int32_t velD; + int32_t gSpeed; + int32_t headMot; + uint32_t sAcc; + uint32_t headAcc; + uint16_t pDOP; + uint8_t reserved1[6]; + int32_t headVeh; + int16_t magDec; + uint16_t magAcc; +}; +#pragma pack(pop) + +#pragma pack(push, 1) +struct UCIRP_GPS_PAYLOAD { // our custom struct + GPSFixType gpsFix; + double ecefX; + double ecefY; + double ecefZ; + double horizontalPositionAcc; + double verticalPositionAcc; + double ecefVX; + double ecefVY; + double ecefVZ; + double speedAcc; +}; +#pragma pack(pop) #pragma pack(push, 1) struct UBX_NAV_PVT_PAYLOAD { uint32_t iTOW; From 4a8d227a64471dcbc4ea282e83b1dd31cdc74128 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 24 Mar 2024 23:20:51 -0700 Subject: [PATCH 44/52] add example of ecef conversion function --- gps_ubxm8_i2c/gps.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 2d97871..1a36c73 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -23,6 +23,7 @@ * while(1) { * if(myGPS.PollUpdate() == GPS::PollResult::POLL_FINISHED) { * UBX_NAV_PVT_PAYLOAD pvtData = myGPS.GetSolution(); + * UCIRP_GPS_PAYLOAD ecefData = myGPS.ConvertPayloadToECEF(pvtData); * myGPS.Reset(); * } * } From 345ab6ef54ffb7ef0ccf80dfa581bd7755f27f75 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 24 Mar 2024 23:29:53 -0700 Subject: [PATCH 45/52] use only 1 accuracy and fix duplicate structs --- gps_ubxm8_i2c/gps.cc | 4 +-- gps_ubxm8_i2c/ubxMessages.h | 54 +------------------------------------ 2 files changed, 3 insertions(+), 55 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 0de12a2..aa185e5 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -1,6 +1,7 @@ #include "gps.h" #include +#include #include "coordHelpers.h" #include "ubxMessages.h" @@ -127,8 +128,7 @@ void GpsUbxM8I2c::Reset() { UCIRP_GPS_PAYLOAD ConvertPayloadToECEF(UBX_NAV_PVT_PAYLOAD pvtPayload) { UCIRP_GPS_PAYLOAD payload; payload.gpsFix = pvtPayload.fixType; - payload.horizontalPositionAcc = (double)pvtPayload.hAcc / 1000; - payload.verticalPositionAcc = (double)pvtPayload.vAcc / 1000; + payload.positionAcc = std::max((double)pvtPayload.hAcc / 1000, (double)pvtPayload.vAcc / 1000); payload.speedAcc = (double)pvtPayload.sAcc / 1000; double lat = (double)pvtPayload.lat / 1e7; diff --git a/gps_ubxm8_i2c/ubxMessages.h b/gps_ubxm8_i2c/ubxMessages.h index 071c307..0bc4952 100644 --- a/gps_ubxm8_i2c/ubxMessages.h +++ b/gps_ubxm8_i2c/ubxMessages.h @@ -56,59 +56,7 @@ struct UCIRP_GPS_PAYLOAD { // our custom struct double ecefX; double ecefY; double ecefZ; - double horizontalPositionAcc; - double verticalPositionAcc; - double ecefVX; - double ecefVY; - double ecefVZ; - double speedAcc; -}; -#pragma pack(pop) -#pragma pack(push, 1) -struct UBX_NAV_PVT_PAYLOAD { - uint32_t iTOW; - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t min; - uint8_t sec; - uint8_t valid; - uint32_t tAcc; - int32_t nano; - GPSFixType fixType; - uint8_t flags; - uint8_t flags2; - uint8_t numSV; - int32_t lon; - int32_t lat; - int32_t height; - int32_t hMSL; - uint32_t hAcc; - uint32_t vAcc; - int32_t velN; - int32_t velE; - int32_t velD; - int32_t gSpeed; - int32_t headMot; - uint32_t sAcc; - uint32_t headAcc; - uint16_t pDOP; - uint8_t reserved1[6]; - int32_t headVeh; - int16_t magDec; - uint16_t magAcc; -}; -#pragma pack(pop) - -#pragma pack(push, 1) -struct UCIRP_GPS_PAYLOAD { // our custom struct - GPSFixType gpsFix; - double ecefX; - double ecefY; - double ecefZ; - double horizontalPositionAcc; - double verticalPositionAcc; + double positionAcc; double ecefVX; double ecefVY; double ecefVZ; From f44baaf56e89f8c9bf5bb357399e979f87656b79 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Sun, 24 Mar 2024 23:31:33 -0700 Subject: [PATCH 46/52] fix header order --- gps_ubxm8_i2c/gps.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index aa185e5..433c1c8 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -1,7 +1,7 @@ #include "gps.h" -#include #include +#include #include "coordHelpers.h" #include "ubxMessages.h" From a3d3b0de2a2180e9f115a247c0dfe9895d500381 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Thu, 11 Apr 2024 21:24:02 -0700 Subject: [PATCH 47/52] update example --- gps_ubxm8_i2c/gps.h | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index 1a36c73..d2f4dea 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -18,16 +18,38 @@ * This class keeps its own finite state machine for abstracting away polling data availability and retrying requests. * An example usage is as follows: * ``` - * GPS myGPS(GPS_RESET_PORT, GPS_RESET_PIN, &hi2c3, PVT_MESSAGE); - * myGPS.Init(); - * while(1) { - * if(myGPS.PollUpdate() == GPS::PollResult::POLL_FINISHED) { - * UBX_NAV_PVT_PAYLOAD pvtData = myGPS.GetSolution(); - * UCIRP_GPS_PAYLOAD ecefData = myGPS.ConvertPayloadToECEF(pvtData); - * myGPS.Reset(); - * } - * } - * ``` + int main(void) + { + HAL_Init(); + + SystemClock_Config(); + + MX_GPIO_Init(); + + MX_I2C1_Init(); + + GPS gps(GPS_RST_GPIO_Port, GPS_RST_Pin, &hi2c1, PVT_MESSAGE); + gps.Init(); + HAL_Delay(1000); + + int lastITOW = 0; + while(1) { + volatile GPS::PollResult res = gps.PollUpdate(); + auto state = gps.GetState(); + if(state == GPS::State::RESPONSE_READY) { + UBX_NAV_PVT_PAYLOAD sol = *(UBX_NAV_PVT_PAYLOAD*)gps.GetSolution(); + volatile int diff = sol.iTOW - lastITOW; + lastITOW = sol.iTOW; + if((GPSFixType)sol.fixType == GPSFixType::FIX_3D) { + HAL_Delay(1000); + } + gps.Reset(); + } else { + HAL_Delay(100); + } + } + } + ``` * * After a packet is received, you _need_ to call the reset method. * If you don't, `pollUpdate` will just do nothing and return a `POLL_ALREADY_FINISHED` response. From b9ef6eaf82ca46d1f9f5bcf8a52ae817fb609453 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Fri, 12 Apr 2024 12:43:06 -0700 Subject: [PATCH 48/52] check ubx send status and actually return payload --- gps_ubxm8_i2c/gps.cc | 6 +++++- gps_ubxm8_i2c/gps.h | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 433c1c8..1d93de9 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -34,7 +34,9 @@ const GpsUbxM8I2c::State GpsUbxM8I2c::GetState() { return _state; } */ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate() { if (_state == GpsUbxM8I2c::State::REQUEST_NOT_SENT) { - sendUBX(_ubxMessage); + if(!sendUBX(_ubxMessage)) { + return GpsUbxM8I2c::PollResult::REQUEST_SEND_FAILED; + } _state = GpsUbxM8I2c::State::POLLING_RESPONSE; } @@ -143,6 +145,8 @@ UCIRP_GPS_PAYLOAD ConvertPayloadToECEF(UBX_NAV_PVT_PAYLOAD pvtPayload) { double velD = (double)pvtPayload.velD / 1000; Ned2EcefVel(lat, lon, alt, velN, velE, velD, payload.ecefVX, payload.ecefVY, payload.ecefVZ); + + return payload; } /** diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps.h index d2f4dea..7ec3585 100644 --- a/gps_ubxm8_i2c/gps.h +++ b/gps_ubxm8_i2c/gps.h @@ -74,7 +74,8 @@ class GpsUbxM8I2c { NO_UBX_DATA, // data read successfully but no UBX start bytes found DATA_LEN_POLL_FAILED, // there was a failure in the I2C mem read for getting the quantity of data available DATA_RECEIVE_I2C_FAILED, // there was a failure in the I2C receive to read the available data from the GPS - DATA_RECEIVE_CHECKSUM_FAILED // we received UBX data but the checksum didn't match the message. + DATA_RECEIVE_CHECKSUM_FAILED, // we received UBX data but the checksum didn't match the message. + REQUEST_SEND_FAILED // the request to the GPS failed (probably i2c transmit error) }; GpsUbxM8I2c(GPIO_TypeDef* gpioResetPort, uint16_t gpioResetPin, I2C_HandleTypeDef* i2c, uint8_t* ubxMessage); void Init(); From 12e612649765fe90374c269c6116e3892100ff87 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Fri, 12 Apr 2024 16:10:30 -0700 Subject: [PATCH 49/52] swap packet reader conditionals (fixed dumbass bug) --- gps_ubxm8_i2c/gps.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps.cc index 1d93de9..b18f1f6 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps.cc @@ -91,14 +91,15 @@ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate() { } } - if (!_packetReader.isInProgress()) { - return GpsUbxM8I2c::PollResult::NO_UBX_DATA; - } - if (_packetReader.isComplete()) { _state = GpsUbxM8I2c::State::RESPONSE_READY; return GpsUbxM8I2c::PollResult::POLL_JUST_FINISHED; } + + if (!_packetReader.isInProgress()) { + return GpsUbxM8I2c::PollResult::NO_UBX_DATA; + } + return GpsUbxM8I2c::PollResult::RECEIVE_IN_PROGRESS; } } From 398572b588ab77ce3f438901a8cfbd9ec6128550 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Fri, 12 Apr 2024 16:11:52 -0700 Subject: [PATCH 50/52] rename files and add missing namespace to payload conversion --- gps_ubxm8_i2c/{gps.cc => gps_ubxm8_i2c.cc} | 4 ++-- gps_ubxm8_i2c/{gps.h => gps_ubxm8_i2c.h} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename gps_ubxm8_i2c/{gps.cc => gps_ubxm8_i2c.cc} (98%) rename gps_ubxm8_i2c/{gps.h => gps_ubxm8_i2c.h} (100%) diff --git a/gps_ubxm8_i2c/gps.cc b/gps_ubxm8_i2c/gps_ubxm8_i2c.cc similarity index 98% rename from gps_ubxm8_i2c/gps.cc rename to gps_ubxm8_i2c/gps_ubxm8_i2c.cc index b18f1f6..0b55915 100644 --- a/gps_ubxm8_i2c/gps.cc +++ b/gps_ubxm8_i2c/gps_ubxm8_i2c.cc @@ -1,4 +1,4 @@ -#include "gps.h" +#include "gps_ubxm8_i2c.h" #include #include @@ -128,7 +128,7 @@ void GpsUbxM8I2c::Reset() { _packetReader.reset(); } -UCIRP_GPS_PAYLOAD ConvertPayloadToECEF(UBX_NAV_PVT_PAYLOAD pvtPayload) { +UCIRP_GPS_PAYLOAD GpsUbxM8I2c::ConvertPayloadToECEF(UBX_NAV_PVT_PAYLOAD pvtPayload) { UCIRP_GPS_PAYLOAD payload; payload.gpsFix = pvtPayload.fixType; payload.positionAcc = std::max((double)pvtPayload.hAcc / 1000, (double)pvtPayload.vAcc / 1000); diff --git a/gps_ubxm8_i2c/gps.h b/gps_ubxm8_i2c/gps_ubxm8_i2c.h similarity index 100% rename from gps_ubxm8_i2c/gps.h rename to gps_ubxm8_i2c/gps_ubxm8_i2c.h From 25b63477b2f8c33b3a0d3a2d74b46c5f06da0aca Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Fri, 12 Apr 2024 16:17:19 -0700 Subject: [PATCH 51/52] make payload conversion pass-by-reference --- gps_ubxm8_i2c/gps_ubxm8_i2c.cc | 2 +- gps_ubxm8_i2c/gps_ubxm8_i2c.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gps_ubxm8_i2c/gps_ubxm8_i2c.cc b/gps_ubxm8_i2c/gps_ubxm8_i2c.cc index 0b55915..a269d70 100644 --- a/gps_ubxm8_i2c/gps_ubxm8_i2c.cc +++ b/gps_ubxm8_i2c/gps_ubxm8_i2c.cc @@ -128,7 +128,7 @@ void GpsUbxM8I2c::Reset() { _packetReader.reset(); } -UCIRP_GPS_PAYLOAD GpsUbxM8I2c::ConvertPayloadToECEF(UBX_NAV_PVT_PAYLOAD pvtPayload) { +UCIRP_GPS_PAYLOAD GpsUbxM8I2c::ConvertPayloadToECEF(const UBX_NAV_PVT_PAYLOAD& pvtPayload) { UCIRP_GPS_PAYLOAD payload; payload.gpsFix = pvtPayload.fixType; payload.positionAcc = std::max((double)pvtPayload.hAcc / 1000, (double)pvtPayload.vAcc / 1000); diff --git a/gps_ubxm8_i2c/gps_ubxm8_i2c.h b/gps_ubxm8_i2c/gps_ubxm8_i2c.h index 7ec3585..aeeadcf 100644 --- a/gps_ubxm8_i2c/gps_ubxm8_i2c.h +++ b/gps_ubxm8_i2c/gps_ubxm8_i2c.h @@ -83,7 +83,7 @@ class GpsUbxM8I2c { const PollResult PollUpdate(); const void* GetSolution(); void Reset(); - UCIRP_GPS_PAYLOAD ConvertPayloadToECEF(UBX_NAV_PVT_PAYLOAD pvtPayload); + UCIRP_GPS_PAYLOAD ConvertPayloadToECEF(const UBX_NAV_PVT_PAYLOAD& pvtPayload); private: UBXPacketReader _packetReader; From 093a5a5c3086b77b1acfdd9366face2d37cac160 Mon Sep 17 00:00:00 2001 From: Eric Pedley Date: Fri, 12 Apr 2024 16:35:15 -0700 Subject: [PATCH 52/52] make conversion function private and just return simpler struct --- gps_ubxm8_i2c/gps_ubxm8_i2c.cc | 5 ++++- gps_ubxm8_i2c/gps_ubxm8_i2c.h | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/gps_ubxm8_i2c/gps_ubxm8_i2c.cc b/gps_ubxm8_i2c/gps_ubxm8_i2c.cc index a269d70..2bda2a1 100644 --- a/gps_ubxm8_i2c/gps_ubxm8_i2c.cc +++ b/gps_ubxm8_i2c/gps_ubxm8_i2c.cc @@ -117,7 +117,10 @@ const GpsUbxM8I2c::PollResult GpsUbxM8I2c::PollUpdate() { * * @retval pointer to payload. Can be casted to a struct in ubxMessages. */ -const void* GpsUbxM8I2c::GetSolution() { return _packetReader.getPayload(); } +const UCIRP_GPS_PAYLOAD GpsUbxM8I2c::GetSolution() { + UBX_NAV_PVT_PAYLOAD pvtPayload = *(UBX_NAV_PVT_PAYLOAD*)_packetReader.getPayload(); + return ConvertPayloadToECEF(pvtPayload); +} /** * @brief Puts the GPS state back to its initial value so that `pollUpdate` knows diff --git a/gps_ubxm8_i2c/gps_ubxm8_i2c.h b/gps_ubxm8_i2c/gps_ubxm8_i2c.h index aeeadcf..d4d8f79 100644 --- a/gps_ubxm8_i2c/gps_ubxm8_i2c.h +++ b/gps_ubxm8_i2c/gps_ubxm8_i2c.h @@ -81,9 +81,8 @@ class GpsUbxM8I2c { void Init(); const State GetState(); const PollResult PollUpdate(); - const void* GetSolution(); + const UCIRP_GPS_PAYLOAD GetSolution(); void Reset(); - UCIRP_GPS_PAYLOAD ConvertPayloadToECEF(const UBX_NAV_PVT_PAYLOAD& pvtPayload); private: UBXPacketReader _packetReader; @@ -93,4 +92,5 @@ class GpsUbxM8I2c { I2C_HandleTypeDef* _i2c; uint8_t* _ubxMessage; bool sendUBX(uint8_t* message); + UCIRP_GPS_PAYLOAD ConvertPayloadToECEF(const UBX_NAV_PVT_PAYLOAD& pvtPayload); };