diff --git a/.gitignore b/.gitignore
index 4a29d3aad..00c713efe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -117,3 +117,4 @@ ipch/
:50003
:50006
.vscode/.cortex-debug.peripherals.state.json
+db_dump.txt
diff --git a/keil/B-L072Z-LRWAN1/loramac/periodic-uplink-lpp/periodic-uplink-lpp.uvprojx b/keil/B-L072Z-LRWAN1/loramac/periodic-uplink-lpp/periodic-uplink-lpp.uvprojx
index 1b6a38293..477651d8a 100644
--- a/keil/B-L072Z-LRWAN1/loramac/periodic-uplink-lpp/periodic-uplink-lpp.uvprojx
+++ b/keil/B-L072Z-LRWAN1/loramac/periodic-uplink-lpp/periodic-uplink-lpp.uvprojx
@@ -528,6 +528,11 @@
1
..\..\..\..\src\boards\B-L072Z-LRWAN1\adc-board.c
+
+ gps-board.c
+ 1
+ ..\..\..\..\src\boards\B-L072Z-LRWAN1\gps-board.c
+
@@ -813,16 +818,6 @@
1
..\..\..\..\src\peripherals\LoRaWAN_config_switcher.c
-
- SparkFun_Ublox_Arduino_Library.c
- 1
- ..\..\..\..\src\peripherals\SparkFun_Ublox_Arduino_Library.c
-
-
- ublox.c
- 1
- ..\..\..\..\src\peripherals\ublox.c
-
playback.c
1
@@ -833,11 +828,6 @@
1
..\..\..\..\src\peripherals\struct.c
-
- i2c_middleware.c
- 1
- ..\..\..\..\src\peripherals\i2c_middleware.c
-
eeprom_settings_manager.c
1
@@ -928,6 +918,11 @@
1
..\..\..\..\src\system\adc.c
+
+ gps.c
+ 1
+ ..\..\..\..\src\system\gps.c
+
diff --git a/src/apps/LoRaMac/common/callbacks.c b/src/apps/LoRaMac/common/callbacks.c
index 33e9cd90f..3444baaa0 100644
--- a/src/apps/LoRaMac/common/callbacks.c
+++ b/src/apps/LoRaMac/common/callbacks.c
@@ -18,7 +18,6 @@
#include
#include "NvmDataMgmt.h"
#include "string.h"
-#include "ublox.h"
#include "soft-se-hal.h"
#include "nvmm.h"
#include "struct.h"
@@ -40,8 +39,10 @@ void OnNvmDataChange(LmHandlerNvmContextStates_t state, uint16_t size)
DisplayNvmDataChange(state, size);
/**
- * @brief This is the last event in a Class A transmission, as the last
+ * @brief Only turn back on the GPS during the Store function call. This is the last
+ * event in a Class A transmission, so its now safe to turn back on the GPS. The last
* RX window has closed by now.
+ *
*/
if (state == LORAMAC_HANDLER_NVM_STORE)
{
diff --git a/src/apps/LoRaMac/periodic-uplink-lpp/B-L072Z-LRWAN1/main.c b/src/apps/LoRaMac/periodic-uplink-lpp/B-L072Z-LRWAN1/main.c
index 76da6e0cf..89224c67d 100644
--- a/src/apps/LoRaMac/periodic-uplink-lpp/B-L072Z-LRWAN1/main.c
+++ b/src/apps/LoRaMac/periodic-uplink-lpp/B-L072Z-LRWAN1/main.c
@@ -28,7 +28,6 @@
#include "Commissioning.h"
#include "config.h"
-#include "ublox.h"
#include "geofence.h"
#include "iwdg.h"
#include "print_utils.h"
@@ -244,6 +243,7 @@ static void PrepareTxFrame( void )
return;
}
+ tx_count_on_this_credential ++;
sensor_read_and_send( &AppData, LmHandlerParams.Region );
uint32_t interval = read_tx_interval_in_eeprom( TX_INTERVAL_EEPROM_ADDRESS,
TX_INTERVAL_GPS_FIX_OK );
diff --git a/src/boards/B-L072Z-LRWAN1/board-config.h b/src/boards/B-L072Z-LRWAN1/board-config.h
index 20a7f61af..be4a1d5c3 100644
--- a/src/boards/B-L072Z-LRWAN1/board-config.h
+++ b/src/boards/B-L072Z-LRWAN1/board-config.h
@@ -72,7 +72,6 @@ extern "C"
#define LED_3 PB_6
#define LED_4 PB_7
#define GPS_INT PB_13
-#define LOAD_ENABLE PA_11
#define LED_GREEN LED_1
#define LED_RED1 LED_2
@@ -93,8 +92,13 @@ extern "C"
#define I2C_SCL PB_8
#define I2C_SDA PB_9
-#define UART_TX PA_9
-#define UART_RX PA_10
+#define GPS_POWER_ON PA_11
+#define GPS_PPS PB_14
+#define GPS_UART_TX PA_2
+#define GPS_UART_RX PA_3
+
+#define UART1_TX PA_9
+#define UART1_RX PA_10
// Debug pins definition.
#define RADIO_DBG_PIN_TX PB_13
diff --git a/src/boards/B-L072Z-LRWAN1/board.c b/src/boards/B-L072Z-LRWAN1/board.c
index 2e78f9e00..127a33a30 100644
--- a/src/boards/B-L072Z-LRWAN1/board.c
+++ b/src/boards/B-L072Z-LRWAN1/board.c
@@ -41,6 +41,7 @@
#include "delay.h"
#include "iwdg.h"
#include "string.h"
+#include "gps.h"
#include "stm32l0xx_ll_adc.h"
@@ -63,7 +64,6 @@
Gpio_t Led1;
Gpio_t Gps_int;
-Gpio_t Load_enable;
Gpio_t i2c_scl;
Gpio_t i2c_sda;
@@ -72,6 +72,7 @@ Gpio_t i2c_sda;
* MCU objects
*/
Uart_t Uart1;
+Uart_t Uart2;
I2c_t I2c;
Adc_t Adc;
@@ -101,7 +102,6 @@ static void CalibrateSystemWakeupTime( void );
*/
static void SystemClockReConfig( void );
-
/*!
* Timer used at first boot to calibrate the SystemWakeupTime
*/
@@ -121,7 +121,7 @@ static bool UsbIsConnected = false;
* UART1 FIFO buffers size
*/
#define UART1_FIFO_TX_SIZE 1024
-#define UART1_FIFO_RX_SIZE 50 // We should hardly expect any rx data at all. Max 2-3 bytes
+#define UART1_FIFO_RX_SIZE 1024 // We should hardly expect any rx data at all. Max 2-3 bytes
uint8_t Uart1TxBuffer[UART1_FIFO_TX_SIZE];
uint8_t Uart1RxBuffer[UART1_FIFO_RX_SIZE];
@@ -153,6 +153,8 @@ void BoardCriticalSectionEnd( uint32_t *mask )
void BoardInitPeriph( void )
{
+
+ GpsInit( );
BSP_sensor_Init();
}
@@ -171,7 +173,6 @@ void BoardInitMcu( void )
GpioInit( &Led1, LED_1, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
// Load enable for sensors, GPS
- GpioInit( &Load_enable, LOAD_ENABLE, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
SystemClockConfig( );
#if DEEP_SLEEP_ENABLE
@@ -182,9 +183,11 @@ void BoardInitMcu( void )
FifoInit( &Uart1.FifoTx, Uart1TxBuffer, UART1_FIFO_TX_SIZE );
FifoInit( &Uart1.FifoRx, Uart1RxBuffer, UART1_FIFO_RX_SIZE );
+ Uart1.IrqNotify = HostMcuIrqNotify;
+
// Configure your terminal for 8 Bits data (7 data bit + 1 parity bit), no parity and no flow ctrl
- UartInit( &Uart1, UART_1, UART_TX, UART_RX );
- UartConfig( &Uart1, RX_TX, 2000000, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL );
+ UartInit( &Uart1, UART_1, UART1_TX, UART1_RX );
+ UartConfig( &Uart1, RX_TX, 9600, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL );
I2cInit( &I2c, I2C_1, I2C_SCL, I2C_SDA );
@@ -546,3 +549,15 @@ void assert_failed( uint8_t* file, uint32_t line )
}
}
#endif
+
+void HostMcuIrqNotify(UartNotifyId_t id)
+{
+ uint8_t data;
+ if (id == UART_NOTIFY_RX)
+ {
+ if (UartGetChar(&Uart1, &data) == 0)
+ {
+ UartPutChar(&Uart2, data);
+ }
+ }
+}
diff --git a/src/boards/B-L072Z-LRWAN1/gps-board.c b/src/boards/B-L072Z-LRWAN1/gps-board.c
new file mode 100644
index 000000000..8cd450fcb
--- /dev/null
+++ b/src/boards/B-L072Z-LRWAN1/gps-board.c
@@ -0,0 +1,160 @@
+/*!
+ * \file gps-board.c
+ *
+ * \brief Target board GPS driver implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ */
+#include "board-config.h"
+#include "board.h"
+#include "gpio.h"
+#include "gps.h"
+#include "uart.h"
+#include "lpm-board.h"
+#include "rtc-board.h"
+#include "gps-board.h"
+#include "delay.h"
+
+/*!
+ * FIFO buffers size
+ */
+#define FIFO_TX_SIZE 128
+#define FIFO_RX_SIZE 128
+
+static uint8_t TxBuffer[FIFO_TX_SIZE];
+static uint8_t RxBuffer[FIFO_RX_SIZE];
+
+/*!
+ * \brief Buffer holding the raw data received from the gps
+ */
+static uint8_t NmeaString[128];
+
+/*!
+ * \brief Maximum number of data byte that we will accept from the GPS
+ */
+static volatile uint8_t NmeaStringSize = 0;
+
+static Gpio_t GpsPowerEn;
+static Gpio_t GpsPps;
+
+static volatile bool GpsPowerEnInverted = true;
+
+extern Uart_t Uart2;
+extern Uart_t Uart1;
+
+void GpsMcuOnPpsSignal( void* context )
+{
+ bool parseData = true;
+
+ // GpsPpsHandler( &parseData );
+
+ if( parseData == true )
+ {
+ // Disables lowest power modes
+ // LpmSetStopMode( LPM_GPS_ID , LPM_DISABLE );
+
+
+ }
+}
+
+void GpsMcuInvertPpsTrigger( void )
+{
+
+}
+#define STRING_SIZE 28
+uint8_t ubxOnlyString[STRING_SIZE] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0x79};
+
+void GpsMcuInit( void )
+{
+ NmeaStringSize = 0;
+
+ GpioInit( &GpsPowerEn, GPS_POWER_ON, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
+
+ GpioInit( &GpsPps, GPS_PPS, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
+ GpioSetInterrupt( &GpsPps, IRQ_FALLING_EDGE, IRQ_VERY_LOW_PRIORITY, &GpsMcuOnPpsSignal );
+
+ FifoInit( &Uart2.FifoRx, RxBuffer, FIFO_RX_SIZE );
+ FifoInit( &Uart2.FifoTx, TxBuffer, FIFO_TX_SIZE );
+ Uart2.IrqNotify = GpsMcuIrqNotify;
+
+ UartInit( &Uart2, UART_2, GPS_UART_TX, GPS_UART_RX );
+ UartConfig( &Uart2, RX_TX, 9600, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL );
+ GpsMcuStart( );
+
+ DelayMs(1000);
+
+ while (UartPutBuffer(&Uart2, (uint8_t *)ubxOnlyString, (uint16_t)STRING_SIZE) != 0)
+ {
+ };
+}
+
+void GpsMcuStart( void )
+{
+ if( GpsPowerEnInverted == true )
+ {
+ GpioWrite( &GpsPowerEn, 0 ); // power up the GPS
+ }
+ else
+ {
+ GpioWrite( &GpsPowerEn, 1 ); // power up the GPS
+ }
+}
+
+void GpsMcuStop( void )
+{
+ if( GpsPowerEnInverted == true )
+ {
+ GpioWrite( &GpsPowerEn, 1 ); // power down the GPS
+ }
+ else
+ {
+ GpioWrite( &GpsPowerEn, 0 ); // power down the GPS
+ }
+}
+
+void GpsMcuProcess( void )
+{
+
+}
+
+void GpsMcuIrqNotify( UartNotifyId_t id )
+{
+ uint8_t data;
+ if( id == UART_NOTIFY_RX )
+ {
+ if( UartGetChar( &Uart2, &data ) == 0 )
+ {
+ UartPutChar( &Uart1, data );
+ if( ( data == '$' ) || ( NmeaStringSize >= 127 ) )
+ {
+ NmeaStringSize = 0;
+ }
+
+ NmeaString[NmeaStringSize++] = ( int8_t )data;
+
+ if( data == '\n' )
+ {
+ NmeaString[NmeaStringSize++] = '\0';
+ GpsParseGpsData( ( int8_t* )NmeaString, NmeaStringSize );
+ // UartDeInit( &Uart2 );
+ // Enables lowest power modes
+ // LpmSetStopMode( LPM_GPS_ID , LPM_ENABLE );
+ }
+ }
+ }
+}
diff --git a/src/boards/B-L072Z-LRWAN1/uart-board.c b/src/boards/B-L072Z-LRWAN1/uart-board.c
index 981223e02..13ae8c636 100644
--- a/src/boards/B-L072Z-LRWAN1/uart-board.c
+++ b/src/boards/B-L072Z-LRWAN1/uart-board.c
@@ -32,16 +32,20 @@
*/
#define TX_BUFFER_RETRY_COUNT 10
-static UART_HandleTypeDef UartHandle;
-uint8_t RxData = 0;
-uint8_t TxData = 0;
+typedef struct
+{
+ UART_HandleTypeDef UartHandle;
+ uint8_t RxData;
+ uint8_t TxData;
+}UartContext_t;
+
+UartContext_t UartContext[2];
extern Uart_t Uart1;
+extern Uart_t Uart2;
void UartMcuInit( Uart_t *obj, UartId_t uartId, PinNames tx, PinNames rx )
{
- obj->UartId = uartId;
-
if( uartId == UART_USB_CDC )
{
#if defined( USE_USB_CDC )
@@ -50,12 +54,26 @@ void UartMcuInit( Uart_t *obj, UartId_t uartId, PinNames tx, PinNames rx )
}
else
{
- __HAL_RCC_USART1_FORCE_RESET( );
- __HAL_RCC_USART1_RELEASE_RESET( );
- __HAL_RCC_USART1_CLK_ENABLE( );
+ obj->UartId = uartId;
- GpioInit( &obj->Tx, tx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF4_USART1 );
- GpioInit( &obj->Rx, rx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF4_USART1 );
+ if( obj->UartId == UART_1 )
+ {
+ __HAL_RCC_USART1_FORCE_RESET( );
+ __HAL_RCC_USART1_RELEASE_RESET( );
+ __HAL_RCC_USART1_CLK_ENABLE( );
+
+ GpioInit( &obj->Tx, tx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF4_USART1 );
+ GpioInit( &obj->Rx, rx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF4_USART1 );
+ }
+ else if( obj->UartId == UART_2 )
+ {
+ __HAL_RCC_USART2_FORCE_RESET( );
+ __HAL_RCC_USART2_RELEASE_RESET( );
+ __HAL_RCC_USART2_CLK_ENABLE( );
+
+ GpioInit( &obj->Tx, tx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF4_USART2 );
+ GpioInit( &obj->Rx, rx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF4_USART2 );
+ }
}
}
@@ -69,8 +87,15 @@ void UartMcuConfig( Uart_t *obj, UartMode_t mode, uint32_t baudrate, WordLength_
}
else
{
- UartHandle.Instance = USART1;
- UartHandle.Init.BaudRate = baudrate;
+ if( obj->UartId == UART_1 )
+ {
+ UartContext[obj->UartId].UartHandle.Instance = USART1;
+ }
+ else if( obj->UartId == UART_2 )
+ {
+ UartContext[obj->UartId].UartHandle.Instance = USART2;
+ }
+ UartContext[obj->UartId].UartHandle.Init.BaudRate = baudrate;
if( mode == TX_ONLY )
{
@@ -78,7 +103,7 @@ void UartMcuConfig( Uart_t *obj, UartMode_t mode, uint32_t baudrate, WordLength_
{
assert_param( LMN_STATUS_ERROR );
}
- UartHandle.Init.Mode = UART_MODE_TX;
+ UartContext[obj->UartId].UartHandle.Init.Mode = UART_MODE_TX;
}
else if( mode == RX_ONLY )
{
@@ -86,7 +111,7 @@ void UartMcuConfig( Uart_t *obj, UartMode_t mode, uint32_t baudrate, WordLength_
{
assert_param( LMN_STATUS_ERROR );
}
- UartHandle.Init.Mode = UART_MODE_RX;
+ UartContext[obj->UartId].UartHandle.Init.Mode = UART_MODE_RX;
}
else if( mode == RX_TX )
{
@@ -94,7 +119,7 @@ void UartMcuConfig( Uart_t *obj, UartMode_t mode, uint32_t baudrate, WordLength_
{
assert_param( LMN_STATUS_ERROR );
}
- UartHandle.Init.Mode = UART_MODE_TX_RX;
+ UartContext[obj->UartId].UartHandle.Init.Mode = UART_MODE_TX_RX;
}
else
{
@@ -103,69 +128,74 @@ void UartMcuConfig( Uart_t *obj, UartMode_t mode, uint32_t baudrate, WordLength_
if( wordLength == UART_8_BIT )
{
- UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
+ UartContext[obj->UartId].UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
}
else if( wordLength == UART_9_BIT )
{
- UartHandle.Init.WordLength = UART_WORDLENGTH_9B;
+ UartContext[obj->UartId].UartHandle.Init.WordLength = UART_WORDLENGTH_9B;
}
switch( stopBits )
{
case UART_2_STOP_BIT:
- UartHandle.Init.StopBits = UART_STOPBITS_2;
- break;
- case UART_1_5_STOP_BIT:
- UartHandle.Init.StopBits = UART_STOPBITS_1_5;
+ UartContext[obj->UartId].UartHandle.Init.StopBits = UART_STOPBITS_2;
break;
case UART_1_STOP_BIT:
default:
- UartHandle.Init.StopBits = UART_STOPBITS_1;
+ UartContext[obj->UartId].UartHandle.Init.StopBits = UART_STOPBITS_1;
break;
}
if( parity == NO_PARITY )
{
- UartHandle.Init.Parity = UART_PARITY_NONE;
+ UartContext[obj->UartId].UartHandle.Init.Parity = UART_PARITY_NONE;
}
else if( parity == EVEN_PARITY )
{
- UartHandle.Init.Parity = UART_PARITY_EVEN;
+ UartContext[obj->UartId].UartHandle.Init.Parity = UART_PARITY_EVEN;
}
else
{
- UartHandle.Init.Parity = UART_PARITY_ODD;
+ UartContext[obj->UartId].UartHandle.Init.Parity = UART_PARITY_ODD;
}
if( flowCtrl == NO_FLOW_CTRL )
{
- UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ UartContext[obj->UartId].UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
}
else if( flowCtrl == RTS_FLOW_CTRL )
{
- UartHandle.Init.HwFlowCtl = UART_HWCONTROL_RTS;
+ UartContext[obj->UartId].UartHandle.Init.HwFlowCtl = UART_HWCONTROL_RTS;
}
else if( flowCtrl == CTS_FLOW_CTRL )
{
- UartHandle.Init.HwFlowCtl = UART_HWCONTROL_CTS;
+ UartContext[obj->UartId].UartHandle.Init.HwFlowCtl = UART_HWCONTROL_CTS;
}
else if( flowCtrl == RTS_CTS_FLOW_CTRL )
{
- UartHandle.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
+ UartContext[obj->UartId].UartHandle.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
}
- UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
+ UartContext[obj->UartId].UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
- if( HAL_UART_Init( &UartHandle ) != HAL_OK )
+ if( HAL_UART_Init( &UartContext[obj->UartId].UartHandle ) != HAL_OK )
{
assert_param( LMN_STATUS_ERROR );
}
- HAL_NVIC_SetPriority( USART1_IRQn, 1, 0 );
- HAL_NVIC_EnableIRQ( USART1_IRQn );
+ if( obj->UartId == UART_1 )
+ {
+ HAL_NVIC_SetPriority( USART1_IRQn, 1, 0 );
+ HAL_NVIC_EnableIRQ( USART1_IRQn );
+ }
+ else if( obj->UartId == UART_2 )
+ {
+ HAL_NVIC_SetPriority( USART2_IRQn, 1, 0 );
+ HAL_NVIC_EnableIRQ( USART2_IRQn );
+ }
/* Enable the UART Data Register not empty Interrupt */
- HAL_UART_Receive_IT( &UartHandle, &RxData, 1 );
+ HAL_UART_Receive_IT( &UartContext[obj->UartId].UartHandle, &UartContext[obj->UartId].RxData, 1 );
}
}
@@ -179,9 +209,18 @@ void UartMcuDeInit( Uart_t *obj )
}
else
{
- __HAL_RCC_USART1_FORCE_RESET( );
- __HAL_RCC_USART1_RELEASE_RESET( );
- __HAL_RCC_USART1_CLK_DISABLE( );
+ if( obj->UartId == UART_1 )
+ {
+ __HAL_RCC_USART1_FORCE_RESET( );
+ __HAL_RCC_USART1_RELEASE_RESET( );
+ __HAL_RCC_USART1_CLK_DISABLE( );
+ }
+ else if( obj->UartId == UART_2 )
+ {
+ __HAL_RCC_USART2_FORCE_RESET( );
+ __HAL_RCC_USART2_RELEASE_RESET( );
+ __HAL_RCC_USART2_CLK_DISABLE( );
+ }
GpioInit( &obj->Tx, obj->Tx.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
GpioInit( &obj->Rx, obj->Rx.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
@@ -201,14 +240,14 @@ uint8_t UartMcuPutChar( Uart_t *obj, uint8_t data )
else
{
CRITICAL_SECTION_BEGIN( );
- TxData = data;
+ UartContext[obj->UartId].TxData = data;
if( IsFifoFull( &obj->FifoTx ) == false )
{
- FifoPush( &obj->FifoTx, TxData );
+ FifoPush( &obj->FifoTx, UartContext[obj->UartId].TxData );
// Trig UART Tx interrupt to start sending the FIFO contents.
- __HAL_UART_ENABLE_IT( &UartHandle, UART_IT_TC );
+ __HAL_UART_ENABLE_IT( &UartContext[obj->UartId].UartHandle, UART_IT_TC );
CRITICAL_SECTION_END( );
return 0; // OK
@@ -303,41 +342,97 @@ uint8_t UartMcuGetBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size, uint16_t
void HAL_UART_TxCpltCallback( UART_HandleTypeDef *handle )
{
- if( IsFifoEmpty( &Uart1.FifoTx ) == false )
+ Uart_t *uart = &Uart1;
+ UartId_t uartId = UART_1;
+
+ if( handle == &UartContext[UART_1].UartHandle )
+ {
+ uart = &Uart1;
+ uartId = UART_1;
+ }
+ else if( handle == &UartContext[UART_2].UartHandle )
{
- TxData = FifoPop( &Uart1.FifoTx );
+ uart = &Uart2;
+ uartId = UART_2;
+ }
+ else
+ {
+ // Unknown UART peripheral skip processing
+ return;
+ }
+ if( IsFifoEmpty( &uart->FifoTx ) == false )
+ {
+ UartContext[uartId].TxData = FifoPop( &uart->FifoTx );
// Write one byte to the transmit data register
- HAL_UART_Transmit_IT( &UartHandle, &TxData, 1 );
+ HAL_UART_Transmit_IT( &UartContext[uartId].UartHandle, &UartContext[uartId].TxData, 1 );
}
- if( Uart1.IrqNotify != NULL )
+ if( uart->IrqNotify != NULL )
{
- Uart1.IrqNotify( UART_NOTIFY_TX );
+ uart->IrqNotify( UART_NOTIFY_TX );
}
}
void HAL_UART_RxCpltCallback( UART_HandleTypeDef *handle )
{
- if( IsFifoFull( &Uart1.FifoRx ) == false )
+ Uart_t *uart = &Uart1;
+ UartId_t uartId = UART_1;
+
+ if( handle == &UartContext[UART_1].UartHandle )
+ {
+ uart = &Uart1;
+ uartId = UART_1;
+ }
+ else if( handle == &UartContext[UART_2].UartHandle )
+ {
+ uart = &Uart2;
+ uartId = UART_2;
+ }
+ else
+ {
+ // Unknown UART peripheral skip processing
+ return;
+ }
+ if( IsFifoFull( &uart->FifoRx ) == false )
{
// Read one byte from the receive data register
- FifoPush( &Uart1.FifoRx, RxData );
+ FifoPush( &uart->FifoRx, UartContext[uartId].RxData );
}
- if( Uart1.IrqNotify != NULL )
+ if( uart->IrqNotify != NULL )
{
- Uart1.IrqNotify( UART_NOTIFY_RX );
+ uart->IrqNotify( UART_NOTIFY_RX );
}
- HAL_UART_Receive_IT( &UartHandle, &RxData, 1 );
+ HAL_UART_Receive_IT( &UartContext[uartId].UartHandle, &UartContext[uartId].RxData, 1 );
}
void HAL_UART_ErrorCallback( UART_HandleTypeDef *handle )
{
- HAL_UART_Receive_IT( &UartHandle, &RxData, 1 );
+ UartId_t uartId = UART_1;
+
+ if( handle == &UartContext[UART_1].UartHandle )
+ {
+ uartId = UART_1;
+ }
+ else if( handle == &UartContext[UART_2].UartHandle )
+ {
+ uartId = UART_2;
+ }
+ else
+ {
+ // Unknown UART peripheral skip processing
+ return;
+ }
+ HAL_UART_Receive_IT( &UartContext[uartId].UartHandle, &UartContext[uartId].RxData, 1 );
}
void USART1_IRQHandler( void )
{
- HAL_UART_IRQHandler( &UartHandle );
+ HAL_UART_IRQHandler( &UartContext[UART_1].UartHandle );
+}
+
+void USART2_IRQHandler( void )
+{
+ HAL_UART_IRQHandler( &UartContext[UART_2].UartHandle );
}
diff --git a/src/boards/board.h b/src/boards/board.h
index b56341b67..ed0ba4432 100644
--- a/src/boards/board.h
+++ b/src/boards/board.h
@@ -30,6 +30,7 @@ extern "C"
#include
#include "utilities.h"
+#include "uart.h"
/*!
* Possible power sources
*/
@@ -123,6 +124,7 @@ int32_t HW_GetTemperatureLevel_int(void);
void disable_serial_output(void);
+void HostMcuIrqNotify(UartNotifyId_t id);
#ifdef __cplusplus
}
diff --git a/src/peripherals/SparkFun_Ublox_Arduino_Library.c b/src/peripherals/SparkFun_Ublox_Arduino_Library.c
deleted file mode 100644
index 390a53270..000000000
--- a/src/peripherals/SparkFun_Ublox_Arduino_Library.c
+++ /dev/null
@@ -1,2840 +0,0 @@
-/*
- This is a library written for the Ublox ZED-F9P and NEO-M8P-2
- SparkFun sells these at its website: www.sparkfun.com
- Do you like this library? Help support SparkFun. Buy a board!
- https://www.sparkfun.com/products/15136
- https://www.sparkfun.com/products/15005
- https://www.sparkfun.com/products/15733
- https://www.sparkfun.com/products/15193
- https://www.sparkfun.com/products/15210
-
- Written by Nathan Seidle @ SparkFun Electronics, September 6th, 2018
-
- This library handles configuring and handling the responses
- from a Ublox GPS module. Works with most modules from Ublox including
- the Zed-F9P, NEO-M8P-2, NEO-M9N, ZOE-M8Q, SAM-M8Q, and many others.
-
- https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library
-
- Development environment specifics:
- Arduino IDE 1.8.5
-
- SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT).
- The MIT License (MIT)
- Copyright (c) 2016 SparkFun Electronics
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
- associated documentation files (the "Software"), to deal in the Software without restriction,
- including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom the Software is furnished to
- do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all copies or substantial
- portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
- NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-#if 1
-
-
-#include
-#include
-#include "utilities.h"
-#include "i2c.h"
-#include "SparkFun_Ublox_Arduino_Library.h"
-#include
-#include "string.h"
-#include "delay.h"
-
-extern I2c_t I2c;
-
-
-
-
-
-
-
-
-const char *statusString(sfe_ublox_status_e stat)
-{
- switch (stat)
- {
- case SFE_UBLOX_STATUS_SUCCESS:
- return "Success";
- case SFE_UBLOX_STATUS_FAIL:
- return "General Failure";
- case SFE_UBLOX_STATUS_CRC_FAIL:
- return "CRC Fail";
- case SFE_UBLOX_STATUS_TIMEOUT:
- return "Timeout";
- case SFE_UBLOX_STATUS_COMMAND_NACK:
- return "Command not acknowledged (NACK)";
- case SFE_UBLOX_STATUS_OUT_OF_RANGE:
- return "Out of range";
- case SFE_UBLOX_STATUS_INVALID_ARG:
- return "Invalid Arg";
- case SFE_UBLOX_STATUS_INVALID_OPERATION:
- return "Invalid operation";
- case SFE_UBLOX_STATUS_MEM_ERR:
- return "Memory Error";
- case SFE_UBLOX_STATUS_HW_ERR:
- return "Hardware Error";
- case SFE_UBLOX_STATUS_DATA_SENT:
- return "Data Sent";
- case SFE_UBLOX_STATUS_DATA_RECEIVED:
- return "Data Received";
- case SFE_UBLOX_STATUS_I2C_COMM_FAILURE:
- return "I2C Comm Failure";
- case SFE_UBLOX_STATUS_DATA_OVERWRITTEN:
- return "Data Packet Overwritten";
- default:
- return "Unknown Status";
- }
- //return "None";
-}
-
-//The major datums we want to globally store
-static uint16_t gpsYear;
-static uint8_t gpsMonth;
-static uint8_t gpsDay;
-static uint8_t gpsHour;
-static uint8_t gpsMinute;
-static uint8_t gpsSecond;
-static uint16_t gpsMillisecond;
-static int32_t gpsNanosecond;
-static bool gpsDateValid;
-static bool gpsTimeValid;
-
-static int32_t latitude; //Degrees * 10^-7 (more accurate than floats)
-static int32_t longitude; //Degrees * 10^-7 (more accurate than floats)
-static int32_t altitude; //Number of mm above ellipsoid
-static int32_t altitudeMSL; //Number of mm above Mean Sea Level
-static uint8_t SIV; //Number of satellites used in position solution
-static uint8_t fixType; //Tells us when we have a solution aka lock
-static uint8_t gnssFixOK; //Tells us whether fix is OK
-static uint8_t carrierSolution; //Tells us when we have an RTK float/fixed solution
-static int32_t groundSpeed; //mm/s
-static int32_t headingOfMotion; //degrees * 10^-5
-static uint16_t pDOP; //Positional dilution of precision
-static uint8_t versionLow; //Loaded from getProtocolVersion().
-static uint8_t versionHigh;
-
-static uint8_t _gpsI2Caddress = 0x42; //Default 7-bit unshifted address of the ublox 6/7/8/M8/F9 series
-//This can be changed using the ublox configuration software
-
-static bool _printDebug = false; //Flag to print the serial commands we are sending to the Serial port for debug
-static bool _printLimitedDebug = false; //Flag to print limited debug messages. Useful for I2C debugging or high navigation rates
-
-//The packet buffers
-//These are pointed at from within the ubxPacket
-static uint8_t payloadAck[2]; // Holds the requested ACK/NACK
-static uint8_t payloadCfg[MAX_PAYLOAD_SIZE]; // Holds the requested data packet
-static uint8_t payloadBuf[2]; // Temporary buffer used to screen incoming packets or dump unrequested packets
-
-#define BUFFER_SIZE 200
-static uint8_t temp_byte_buffer[BUFFER_SIZE];
-
-//Init the packet structures and init them with pointers to the payloadAck, payloadCfg and payloadBuf arrays
-static ubxPacket packetAck = {0, 0, 0, 0, 0, payloadAck, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
-static ubxPacket packetCfg = {0, 0, 0, 0, 0, payloadCfg, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
-static ubxPacket packetBuf = {0, 0, 0, 0, 0, payloadBuf, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
-
-//Flag if this packet is unrequested (and so should be ignored and not copied into packetCfg or packetAck)
-static bool ignoreThisPayload = false;
-
-//Identify which buffer is in use
-//Data is stored in packetBuf until the requested class and ID can be validated
-//If a match is seen, data is diverted into packetAck or packetCfg
-static sfe_ublox_packet_buffer_e activePacketBuffer = SFE_UBLOX_PACKET_PACKETBUF;
-
-//Limit checking of new data to every X ms
-//If we are expecting an update every X Hz then we should check every half that amount of time
-//Otherwise we may block ourselves from seeing new data
-static uint8_t i2cPollingWait = 100; //Default to 100ms. Adjusted when user calls setNavigationFrequency()
-
-static unsigned long lastCheck = 0;
-static bool autoPVT = false; //Whether autoPVT is enabled or not
-static bool autoPVTImplicitUpdate = true; // Whether autoPVT is triggered by accessing stale data (=true) or by a call to checkUblox (=false)
-static uint16_t ubxFrameCounter; //It counts all UBX frame. [Fixed header(2bytes), CLS(1byte), ID(1byte), length(2bytes), payload(x bytes), checksums(2bytes)]
-
-static uint8_t rollingChecksumA; //Rolls forward as we receive incoming bytes. Checked against the last two A/B checksum bytes
-static uint8_t rollingChecksumB; //Rolls forward as we receive incoming bytes. Checked against the last two A/B checksum bytes
-
-static uint32_t timeOfWeek; // ms
-static int32_t highResLatitude; // Degrees * 10^-7
-static int32_t highResLongitude; // Degrees * 10^-7
-static int32_t elipsoid; // Height above ellipsoid in mm (Typo! Should be eLLipsoid! **Uncorrected for backward-compatibility.**)
-static int32_t meanSeaLevel; // Height above mean sea level in mm
-static int32_t geoidSeparation; // This seems to only be provided in NMEA GGA and GNS messages
-static uint32_t horizontalAccuracy; // mm * 10^-1 (i.e. 0.1mm)
-static uint32_t verticalAccuracy; // mm * 10^-1 (i.e. 0.1mm)
-static int8_t elipsoidHp; // High precision component of the height above ellipsoid in mm * 10^-1 (Deliberate typo! Should be eLLipsoidHp!)
-static int8_t meanSeaLevelHp; // High precision component of Height above mean sea level in mm * 10^-1
-static int8_t highResLatitudeHp; // High precision component of latitude: Degrees * 10^-9
-static int8_t highResLongitudeHp; // High precision component of longitude: Degrees * 10^-9
-
-static uint16_t rtcmFrameCounter = 0; //Tracks the type of incoming byte inside RTCM frame
-
-//Depending on the sentence type the processor will load characters into different arrays
-static enum SentenceTypes { NONE = 0,
- NMEA,
- UBX,
- RTCM
-} currentSentence = NONE;
-
-static enum commTypes { COMM_TYPE_I2C = 0,
- COMM_TYPE_SERIAL,
- COMM_TYPE_SPI
-} commType = COMM_TYPE_I2C; //Controls which port we look to for incoming bytes
-
-//Create bit field for staleness of each datum in PVT we want to monitor
-//moduleQueried.latitude goes true each time we call getPVT()
-//This reduces the number of times we have to call getPVT as this can take up to ~1s per read
-//depending on update rate
-static struct
-{
- uint32_t gpsiTOW : 1;
- uint32_t gpsYear : 1;
- uint32_t gpsMonth : 1;
- uint32_t gpsDay : 1;
- uint32_t gpsHour : 1;
- uint32_t gpsMinute : 1;
- uint32_t gpsSecond : 1;
- uint32_t gpsDateValid : 1;
- uint32_t gpsTimeValid : 1;
- uint32_t gpsNanosecond : 1;
-
- uint32_t all : 1;
- uint32_t longitude : 1;
- uint32_t latitude : 1;
- uint32_t altitude : 1;
- uint32_t altitudeMSL : 1;
- uint32_t SIV : 1;
- uint32_t fixType : 1;
- uint32_t gnssFixOK : 1;
- uint32_t carrierSolution : 1;
- uint32_t groundSpeed : 1;
- uint32_t headingOfMotion : 1;
- uint32_t pDOP : 1;
- uint32_t versionNumber : 1;
-} moduleQueried;
-
-static struct
-{
- uint16_t all : 1;
- uint16_t timeOfWeek : 1;
- uint16_t highResLatitude : 1;
- uint16_t highResLongitude : 1;
- uint16_t elipsoid : 1;
- uint16_t meanSeaLevel : 1;
- uint16_t geoidSeparation : 1; // Redundant but kept for backward-compatibility
- uint16_t horizontalAccuracy : 1;
- uint16_t verticalAccuracy : 1;
- uint16_t elipsoidHp : 1;
- uint16_t meanSeaLevelHp : 1;
- uint16_t highResLatitudeHp : 1;
- uint16_t highResLongitudeHp : 1;
-} highResModuleQueried;
-
-static uint16_t rtcmLen = 0;
-
-void factoryReset()
-{
- // Copy default settings to permanent
- // Note: this does not load the permanent configuration into the current configuration. Calling factoryDefault() will do that.
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_CFG;
- packetCfg.len = 13;
- packetCfg.startingSpot = 0;
- for (uint8_t i = 0; i < 4; i++)
- {
- payloadCfg[0 + i] = 0xff; // clear mask: copy default config to permanent config
- payloadCfg[4 + i] = 0x00; // save mask: don't save current to permanent
- payloadCfg[8 + i] = 0x00; // load mask: don't copy permanent config to current
- }
- payloadCfg[12] = 0xff; // all forms of permanent memory
- sendCommand(&packetCfg, 0); // don't expect ACK
- hardReset(); // cause factory default config to actually be loaded and used cleanly
-}
-
-void hardReset()
-{
- // Issue hard reset
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_RST;
- packetCfg.len = 4;
- packetCfg.startingSpot = 0;
- payloadCfg[0] = 0xff; // cold start
- payloadCfg[1] = 0xff; // cold start
- payloadCfg[2] = 0; // 0=HW reset
- payloadCfg[3] = 0; // reserved
- sendCommand(&packetCfg, 0); // don't expect ACK
-}
-
-
-// original uint8_t resetReceiver[12] = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0xFF, 0xB9, 0x00, 0x00, 0xC6, 0x8B};
-void ihardReset()
-{
- // Issue hard reset
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_RST;
- packetCfg.len = 4;
- packetCfg.startingSpot = 0;
- payloadCfg[0] = 0xff; // cold start
- payloadCfg[1] = 0xb9; // cold start
- payloadCfg[2] = 0; // 0=HW reset
- payloadCfg[3] = 0; // reserved
- sendCommand(&packetCfg, 0); // don't expect ACK
-}
-
-
-//Called regularly to check for available bytes on the user' specified port
-bool checkUblox(uint8_t requestedClass, uint8_t requestedID)
-{
- return checkUbloxInternal(&packetCfg, requestedClass, requestedID);
-}
-
-//Called regularly to check for available bytes on the user' specified port
-bool checkUbloxInternal(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID)
-{
- if (commType == COMM_TYPE_I2C)
- return (checkUbloxI2C(incomingUBX, requestedClass, requestedID));
-
- return false;
-}
-
-//Polls I2C for data, passing any new bytes to process()
-//Returns true if new bytes are available
-bool checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID)
-{
- if (SysTimeToMs(SysTimeGet()) - lastCheck >= i2cPollingWait)
- {
- //Get the number of bytes available from the module
- uint16_t bytesAvailable = 0;
-// _i2cPort->beginTransmission(_gpsI2Caddress);
-// _i2cPort->write(0xFD); //0xFD (MSB) and 0xFE (LSB) are the registers that contain number of bytes available
-// if (_i2cPort->endTransmission(false) != 0) //Send a restart command. Do not release bus.
-// return (false); //Sensor did not ACK
-
-
- // if (HAL_I2C_IsDeviceReady(&hi2c1,(uint16_t) _gpsI2Caddress << 1,5,defaultMaxWait) != HAL_OK)
- // {
- // return (false); //Sensor did not ACK
- // }
-
-
- //uint16_t return_value = 0;
- if (I2cReadMemBuffer(&I2c,(uint16_t) _gpsI2Caddress << 1,(uint16_t)0xFD,temp_byte_buffer,2 ) != LMN_STATUS_OK)
- {
- return (false); //Sensor did not ACK
- }
-
- uint8_t msb = temp_byte_buffer[0];
- uint8_t lsb = temp_byte_buffer[1];
-
-
-
- if (lsb == 0xFF)
- {
- //I believe this is a Ublox bug. Device should never present an 0xFF.
- if ((_printDebug == true) || (_printLimitedDebug == true)) // printf this if doing limited debugging
- {
- printf("checkUbloxI2C: Ublox bug, length lsb is 0xFF\r\n");
- }
-
- lastCheck = SysTimeToMs(SysTimeGet()); //Put off checking to avoid I2C bus traffic
- return (false);
- }
- bytesAvailable = (uint16_t)msb << 8 | lsb;
-
-
- if (bytesAvailable == 0)
- {
- if (_printDebug == true)
- {
- printf("checkUbloxI2C: OK, zero bytes available\r\n");
- }
- lastCheck = SysTimeToMs(SysTimeGet()); //Put off checking to avoid I2C bus traffic
- return (false);
- }
-
- //Check for undocumented bit error. We found this doing logic scans.
- //This error is rare but if we incorrectly interpret the first bit of the two 'data available' bytes as 1
- //then we have far too many bytes to check. May be related to I2C setup time violations: https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/issues/40
- if (bytesAvailable & ((uint16_t)1 << 15))
- {
- //Clear the MSbit
- bytesAvailable &= ~((uint16_t)1 << 15);
-
- if ((_printDebug == true) || (_printLimitedDebug == true)) // printf this if doing limited debugging
- {
- printf("checkUbloxI2C: Bytes available error:");
- printf("%d\r\n",bytesAvailable);
- }
- }
-
- if (bytesAvailable > 100)
- {
- if (_printDebug == true)
- {
- printf("checkUbloxI2C: Large packet of ");
- printf("%d",bytesAvailable);
- printf(" bytes received\r\n");
- }
- }
- else
- {
- if (_printDebug == true)
- {
- printf("checkUbloxI2C: Reading ");
- printf("%d",bytesAvailable);
- printf(" bytes\r\n");
- }
- }
-
- if (I2cReadMemBuffer(&I2c,(uint16_t) _gpsI2Caddress << 1,(uint16_t)0xFF, temp_byte_buffer, BUFFER_SIZE) != LMN_STATUS_OK)
- {
- return (false); //Sensor did not ACK
- }
-
- for(uint32_t i = 0; i < BUFFER_SIZE ; i++)
- {
- process(temp_byte_buffer[i], incomingUBX, requestedClass, requestedID); //Process this valid character
- }
- }
-
- return (true);
-
-} //end checkUbloxI2C()
-
-
-//Processes NMEA and UBX binary sentences one byte at a time
-//Take a given byte and file it into the proper array
-void process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID)
-{
- if ((currentSentence == NONE) || (currentSentence == NMEA))
- {
- if (incoming == 0xB5) //UBX binary frames start with 0xB5, aka μ
- {
- //This is the start of a binary sentence. Reset flags.
- //We still don't know the response class
- ubxFrameCounter = 0;
- currentSentence = UBX;
- //Reset the packetBuf.counter even though we will need to reset it again when ubxFrameCounter == 2
- packetBuf.counter = 0;
- ignoreThisPayload = false; //We should not ignore this payload - yet
- //Store data in packetBuf until we know if we have a requested class and ID match
- activePacketBuffer = SFE_UBLOX_PACKET_PACKETBUF;
- }
- else if (incoming == '$')
- {
- currentSentence = NMEA;
- }
- else if (incoming == 0xD3) //RTCM frames start with 0xD3
- {
- rtcmFrameCounter = 0;
- currentSentence = RTCM;
- }
- else
- {
- //This character is unknown or we missed the previous start of a sentence
- }
- }
-
- //Depending on the sentence, pass the character to the individual processor
- if (currentSentence == UBX)
- {
- //Decide what type of response this is
- if ((ubxFrameCounter == 0) && (incoming != 0xB5)) //ISO 'μ'
- currentSentence = NONE; //Something went wrong. Reset.
- else if ((ubxFrameCounter == 1) && (incoming != 0x62)) //ASCII 'b'
- currentSentence = NONE; //Something went wrong. Reset.
- // Note to future self:
- // There may be some duplication / redundancy in the next few lines as processUBX will also
- // load information into packetBuf, but we'll do it here too for clarity
- else if (ubxFrameCounter == 2) //Class
- {
- // Record the class in packetBuf until we know what to do with it
- packetBuf.cls = incoming; // (Duplication)
- rollingChecksumA = 0; //Reset our rolling checksums here (not when we receive the 0xB5)
- rollingChecksumB = 0;
- packetBuf.counter = 0; //Reset the packetBuf.counter (again)
- packetBuf.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; // Reset the packet validity (redundant?)
- packetBuf.startingSpot = incomingUBX->startingSpot; //Copy the startingSpot
- }
- else if (ubxFrameCounter == 3) //ID
- {
- // Record the ID in packetBuf until we know what to do with it
- packetBuf.id = incoming; // (Duplication)
- //We can now identify the type of response
- //If the packet we are receiving is not an ACK then check for a class and ID match
- if (packetBuf.cls != UBX_CLASS_ACK)
- {
- //This is not an ACK so check for a class and ID match
- if ((packetBuf.cls == requestedClass) && (packetBuf.id == requestedID))
- {
- //This is not an ACK and we have a class and ID match
- //So start diverting data into incomingUBX (usually packetCfg)
- activePacketBuffer = SFE_UBLOX_PACKET_PACKETCFG;
- incomingUBX->cls = packetBuf.cls; //Copy the class and ID into incomingUBX (usually packetCfg)
- incomingUBX->id = packetBuf.id;
- incomingUBX->counter = packetBuf.counter; //Copy over the .counter too
- }
- else
- {
- //This is not an ACK and we do not have a class and ID match
- //so we should keep diverting data into packetBuf and ignore the payload
- ignoreThisPayload = true;
- }
- }
- else
- {
- // This is an ACK so it is to early to do anything with it
- // We need to wait until we have received the length and data bytes
- // So we should keep diverting data into packetBuf
- }
- }
- else if (ubxFrameCounter == 4) //Length LSB
- {
- //We should save the length in packetBuf even if activePacketBuffer == SFE_UBLOX_PACKET_PACKETCFG
- packetBuf.len = incoming; // (Duplication)
- }
- else if (ubxFrameCounter == 5) //Length MSB
- {
- //We should save the length in packetBuf even if activePacketBuffer == SFE_UBLOX_PACKET_PACKETCFG
- packetBuf.len |= incoming << 8; // (Duplication)
- }
- else if (ubxFrameCounter == 6) //This should be the first byte of the payload unless .len is zero
- {
- if (packetBuf.len == 0) // Check if length is zero (hopefully this is impossible!)
- {
- if (_printDebug == true)
- {
- printf("process: ZERO LENGTH packet received: Class: 0x");
- printf("%02X",packetBuf.cls);
- printf(" ID: 0x");
- printf("%02X\r\n",packetBuf.id);
- }
- //If length is zero (!) this will be the first byte of the checksum so record it
- packetBuf.checksumA = incoming;
- }
- else
- {
- //The length is not zero so record this byte in the payload
- packetBuf.payload[0] = incoming;
- }
- }
- else if (ubxFrameCounter == 7) //This should be the second byte of the payload unless .len is zero or one
- {
- if (packetBuf.len == 0) // Check if length is zero (hopefully this is impossible!)
- {
- //If length is zero (!) this will be the second byte of the checksum so record it
- packetBuf.checksumB = incoming;
- }
- else if (packetBuf.len == 1) // Check if length is one
- {
- //The length is one so this is the first byte of the checksum
- packetBuf.checksumA = incoming;
- }
- else // Length is >= 2 so this must be a payload byte
- {
- packetBuf.payload[1] = incoming;
- }
- // Now that we have received two payload bytes, we can check for a matching ACK/NACK
- if ((activePacketBuffer == SFE_UBLOX_PACKET_PACKETBUF) // If we are not already processing a data packet
- && (packetBuf.cls == UBX_CLASS_ACK) // and if this is an ACK/NACK
- && (packetBuf.payload[0] == requestedClass) // and if the class matches
- && (packetBuf.payload[1] == requestedID)) // and if the ID matches
- {
- if (packetBuf.len == 2) // Check if .len is 2
- {
- // Then this is a matching ACK so copy it into packetAck
- activePacketBuffer = SFE_UBLOX_PACKET_PACKETACK;
- packetAck.cls = packetBuf.cls;
- packetAck.id = packetBuf.id;
- packetAck.len = packetBuf.len;
- packetAck.counter = packetBuf.counter;
- packetAck.payload[0] = packetBuf.payload[0];
- packetAck.payload[1] = packetBuf.payload[1];
- }
- else // Length is not 2 (hopefully this is impossible!)
- {
- if (_printDebug == true)
- {
- printf("process: ACK received with .len != 2: Class: 0x");
- printf("%02X ",packetBuf.payload[0]);
- printf(" ID: 0x");
- printf("%02X ",packetBuf.payload[1]);
- printf(" len: ");
- printf("%02X\r\n",packetBuf.len);
- }
- }
- }
- }
-
- //Divert incoming into the correct buffer
- if (activePacketBuffer == SFE_UBLOX_PACKET_PACKETACK)
- processUBX(incoming, &packetAck, requestedClass, requestedID);
- else if (activePacketBuffer == SFE_UBLOX_PACKET_PACKETCFG)
- processUBX(incoming, incomingUBX, requestedClass, requestedID);
- else // if (activePacketBuffer == SFE_UBLOX_PACKET_PACKETBUF)
- processUBX(incoming, &packetBuf, requestedClass, requestedID);
-
- //Finally, increment the frame counter
- ubxFrameCounter++;
- }
- else if (currentSentence == NMEA)
- {
- processNMEA(incoming); //Process each NMEA character
- }
- else if (currentSentence == RTCM)
- {
- processRTCMframe(incoming); //Deal with RTCM bytes
- }
-}
-
-//This is the default or generic NMEA processor. We're only going to pipe the data to serial port so we can see it.
-//User could overwrite this function to pipe characters to nmea.process(c) of tinyGPS or MicroNMEA
-//Or user could pipe each character to a buffer, radio, etc.
-void processNMEA(char incoming)
-{
-// //If user has assigned an output port then pipe the characters there
-// if (_nmeaOutputPort != NULL)
- printf("%c",incoming); //Echo this byte to the serial port
-}
-
-//We need to be able to identify an RTCM packet and then the length
-//so that we know when the RTCM message is completely received and we then start
-//listening for other sentences (like NMEA or UBX)
-//RTCM packet structure is very odd. I never found RTCM STANDARD 10403.2 but
-//http://d1.amobbs.com/bbs_upload782111/files_39/ourdev_635123CK0HJT.pdf is good
-//https://dspace.cvut.cz/bitstream/handle/10467/65205/F3-BP-2016-Shkalikava-Anastasiya-Prenos%20polohove%20informace%20prostrednictvim%20datove%20site.pdf?sequence=-1
-//Lead me to: https://forum.u-blox.com/index.php/4348/how-to-read-rtcm-messages-from-neo-m8p
-//RTCM 3.2 bytes look like this:
-//Byte 0: Always 0xD3
-//Byte 1: 6-bits of zero
-//Byte 2: 10-bits of length of this packet including the first two-ish header bytes, + 6.
-//byte 3 + 4 bits: Msg type 12 bits
-//Example: D3 00 7C 43 F0 ... / 0x7C = 124+6 = 130 bytes in this packet, 0x43F = Msg type 1087
-void processRTCMframe(uint8_t incoming)
-{
- if (rtcmFrameCounter == 1)
- {
- rtcmLen = (incoming & 0x03) << 8; //Get the last two bits of this byte. Bits 8&9 of 10-bit length
- }
- else if (rtcmFrameCounter == 2)
- {
- rtcmLen |= incoming; //Bits 0-7 of packet length
- rtcmLen += 6; //There are 6 additional bytes of what we presume is header, msgType, CRC, and stuff
- }
- /*else if (rtcmFrameCounter == 3)
- {
- rtcmMsgType = incoming << 4; //Message Type, MS 4 bits
- }
- else if (rtcmFrameCounter == 4)
- {
- rtcmMsgType |= (incoming >> 4); //Message Type, bits 0-7
- }*/
-
- rtcmFrameCounter++;
-
- processRTCM(incoming); //Here is where we expose this byte to the user
-
- if (rtcmFrameCounter == rtcmLen)
- {
- //We're done!
- currentSentence = NONE; //Reset and start looking for next sentence type
- }
-}
-
-//This function is called for each byte of an RTCM frame
-//Ths user can overwrite this function and process the RTCM frame as they please
-//Bytes can be piped to Serial or other interface. The consumer could be a radio or the internet (Ntrip broadcaster)
-void processRTCM(uint8_t incoming)
-{
- //Radio.sendReliable((String)incoming); //An example of passing this byte to a radio
-
- //write(incoming); //An example of passing this byte out the serial port
-
- //Debug printing
- // printf(" "));
- // iincoming < 0x10) printf("0"));
- // iincoming < 0x10) printf("0"));
- // printf(incoming, HEX);
- // irtcmFrameCounter % 16 == 0) printf();
-}
-
-//Given a character, file it away into the uxb packet structure
-//Set valid to VALID or NOT_VALID once sentence is completely received and passes or fails CRC
-//The payload portion of the packet can be 100s of bytes but the max array
-//size is MAX_PAYLOAD_SIZE bytes. startingSpot can be set so we only record
-//a subset of bytes within a larger packet.
-void processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID)
-{
- //Add all incoming bytes to the rolling checksum
- //Stop at len+4 as this is the checksum bytes to that should not be added to the rolling checksum
- if (incomingUBX->counter < incomingUBX->len + 4)
- addToChecksum(incoming);
-
- if (incomingUBX->counter == 0)
- {
- incomingUBX->cls = incoming;
- }
- else if (incomingUBX->counter == 1)
- {
- incomingUBX->id = incoming;
- }
- else if (incomingUBX->counter == 2) //Len LSB
- {
- incomingUBX->len = incoming;
- }
- else if (incomingUBX->counter == 3) //Len MSB
- {
- incomingUBX->len |= incoming << 8;
- }
- else if (incomingUBX->counter == incomingUBX->len + 4) //ChecksumA
- {
- incomingUBX->checksumA = incoming;
- }
- else if (incomingUBX->counter == incomingUBX->len + 5) //ChecksumB
- {
- incomingUBX->checksumB = incoming;
-
- currentSentence = NONE; //We're done! Reset the sentence to being looking for a new start char
-
- //Validate this sentence
- if ((incomingUBX->checksumA == rollingChecksumA) && (incomingUBX->checksumB == rollingChecksumB))
- {
- incomingUBX->valid = SFE_UBLOX_PACKET_VALIDITY_VALID; // Flag the packet as valid
-
- // Let's check if the class and ID match the requestedClass and requestedID
- // Remember - this could be a data packet or an ACK packet
- if ((incomingUBX->cls == requestedClass) && (incomingUBX->id == requestedID))
- {
- incomingUBX->classAndIDmatch = SFE_UBLOX_PACKET_VALIDITY_VALID; // If we have a match, set the classAndIDmatch flag to valid
- }
-
- // If this is an ACK then let's check if the class and ID match the requestedClass and requestedID
- else if ((incomingUBX->cls == UBX_CLASS_ACK) && (incomingUBX->id == UBX_ACK_ACK) && (incomingUBX->payload[0] == requestedClass) && (incomingUBX->payload[1] == requestedID))
- {
- incomingUBX->classAndIDmatch = SFE_UBLOX_PACKET_VALIDITY_VALID; // If we have a match, set the classAndIDmatch flag to valid
- }
-
- // If this is a NACK then let's check if the class and ID match the requestedClass and requestedID
- else if ((incomingUBX->cls == UBX_CLASS_ACK) && (incomingUBX->id == UBX_ACK_NACK) && (incomingUBX->payload[0] == requestedClass) && (incomingUBX->payload[1] == requestedID))
- {
- incomingUBX->classAndIDmatch = SFE_UBLOX_PACKET_NOTACKNOWLEDGED; // If we have a match, set the classAndIDmatch flag to NOTACKNOWLEDGED
- if (_printDebug == true)
- {
- printf("processUBX: NACK received: Requested Class: 0x");
- printf("%02X ",incomingUBX->payload[0]);
- printf(" Requested ID: 0x");
- printf("%02X \r\n",incomingUBX->payload[1]);
- }
- }
-
- if (_printDebug == true)
- {
- printf("Incoming: Size: ");
- printf("%d",incomingUBX->len);
- printf(" Received: ");
- printPacket(incomingUBX);
-
- if (incomingUBX->valid == SFE_UBLOX_PACKET_VALIDITY_VALID)
- {
- printf("packetCfg now valid\r\n");
- }
- if (packetAck.valid == SFE_UBLOX_PACKET_VALIDITY_VALID)
- {
- printf("packetAck now valid\r\n");
- }
- if (incomingUBX->classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_VALID)
- {
- printf("packetCfg classAndIDmatch\r\n");
- }
- if (packetAck.classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_VALID)
- {
- printf("packetAck classAndIDmatch\r\n");
- }
- }
-
- //We've got a valid packet, now do something with it but only if ignoreThisPayload is false
- if (ignoreThisPayload == false)
- {
- processUBXpacket(incomingUBX);
- }
- }
- else // Checksum failure
- {
- incomingUBX->valid = SFE_UBLOX_PACKET_VALIDITY_NOT_VALID;
-
- // Let's check if the class and ID match the requestedClass and requestedID.
- // This is potentially risky as we are saying that we saw the requested Class and ID
- // but that the packet checksum failed. Potentially it could be the class or ID bytes
- // that caused the checksum error!
- if ((incomingUBX->cls == requestedClass) && (incomingUBX->id == requestedID))
- {
- incomingUBX->classAndIDmatch = SFE_UBLOX_PACKET_VALIDITY_NOT_VALID; // If we have a match, set the classAndIDmatch flag to not valid
- }
- // If this is an ACK then let's check if the class and ID match the requestedClass and requestedID
- else if ((incomingUBX->cls == UBX_CLASS_ACK) && (incomingUBX->payload[0] == requestedClass) && (incomingUBX->payload[1] == requestedID))
- {
- incomingUBX->classAndIDmatch = SFE_UBLOX_PACKET_VALIDITY_NOT_VALID; // If we have a match, set the classAndIDmatch flag to not valid
- }
-
- if ((_printDebug == true) || (_printLimitedDebug == true)) // printf this if doing limited debugging
- {
-
-
- printf("Checksum failed:");
- printf(" checksumA: ");
- printf("%d",incomingUBX->checksumA);
- printf(" checksumB: ");
- printf("%d",incomingUBX->checksumB);
-
- printf(" rollingChecksumA: ");
- printf("%d",rollingChecksumA);
- printf(" rollingChecksumB: ");
- printf("%d",rollingChecksumB);
- printf("\r\n");
-
- printf("Failed : ");
- printf("Size: ");
- printf("%d",incomingUBX->len);
- printf(" Received: ");
- printPacket(incomingUBX);
- }
- }
- }
- else //Load this byte into the payload array
- {
- //If a UBX_NAV_PVT packet comes in asynchronously, we need to fudge the startingSpot
- uint16_t startingSpot = incomingUBX->startingSpot;
- if (incomingUBX->cls == UBX_CLASS_NAV && incomingUBX->id == UBX_NAV_PVT)
- startingSpot = 0;
- //Begin recording if counter goes past startingSpot
- if ((incomingUBX->counter - 4) >= startingSpot)
- {
- //Check to see if we have room for this byte
- if (((incomingUBX->counter - 4) - startingSpot) < MAX_PAYLOAD_SIZE) //If counter = 208, starting spot = 200, we're good to record.
- {
- // Check if this is payload data which should be ignored
- if (ignoreThisPayload == false)
- {
- incomingUBX->payload[incomingUBX->counter - 4 - startingSpot] = incoming; //Store this byte into payload array
- }
- }
- }
- }
-
- //Increment the counter
- incomingUBX->counter++;
-
- if (incomingUBX->counter == MAX_PAYLOAD_SIZE)
- {
- //Something has gone very wrong
- currentSentence = NONE; //Reset the sentence to being looking for a new start char
- if (_printDebug == true)
- {
- printf("processUBX: counter hit MAX_PAYLOAD_SIZE");
- }
- }
-}
-
-//Once a packet has been received and validated, identify this packet's class/id and update internal flags
-//Note: if the user requests a PVT or a HPPOSLLH message using a custom packet, the data extraction will
-// not work as expected beacuse extractLong etc are hardwired to packetCfg payloadCfg. Ideally
-// extractLong etc should be updated so they receive a pointer to the packet buffer.
-void processUBXpacket(ubxPacket *msg)
-{
- switch (msg->cls)
- {
- case UBX_CLASS_NAV:
- if (msg->id == UBX_NAV_PVT && msg->len == 92)
- {
- //Parse various byte fields into global vars
- int startingSpot = 0; //fixed value used in processUBX
-
- timeOfWeek = extractLong(0);
- gpsMillisecond = extractLong(0) % 1000; //Get last three digits of iTOW
- gpsYear = extractInt(4);
- gpsMonth = extractByte(6);
- gpsDay = extractByte(7);
- gpsHour = extractByte(8);
- gpsMinute = extractByte(9);
- gpsSecond = extractByte(10);
- gpsDateValid = extractByte(11) & 0x01;
- gpsTimeValid = (extractByte(11) & 0x02) >> 1;
- gpsNanosecond = extractLong(16); //Includes milliseconds
-
- fixType = extractByte(20 - startingSpot);
- gnssFixOK = (extractByte(21 - startingSpot) >> 0) & 0x01; // get the first bit(least significant bit)
- carrierSolution = extractByte(21 - startingSpot) >> 6; //Get 6th&7th bits of this byte
- SIV = extractByte(23 - startingSpot);
- longitude = extractLong(24 - startingSpot);
- latitude = extractLong(28 - startingSpot);
- altitude = extractLong(32 - startingSpot);
- altitudeMSL = extractLong(36 - startingSpot);
- groundSpeed = extractLong(60 - startingSpot);
- headingOfMotion = extractLong(64 - startingSpot);
- pDOP = extractInt(76 - startingSpot);
-
- //Mark all datums as fresh (not read before)
- moduleQueried.gpsiTOW = true;
- moduleQueried.gpsYear = true;
- moduleQueried.gpsMonth = true;
- moduleQueried.gpsDay = true;
- moduleQueried.gpsHour = true;
- moduleQueried.gpsMinute = true;
- moduleQueried.gpsSecond = true;
- moduleQueried.gpsDateValid = true;
- moduleQueried.gpsTimeValid = true;
- moduleQueried.gpsNanosecond = true;
-
- moduleQueried.all = true;
- moduleQueried.longitude = true;
- moduleQueried.latitude = true;
- moduleQueried.altitude = true;
- moduleQueried.altitudeMSL = true;
- moduleQueried.SIV = true;
- moduleQueried.fixType = true;
- moduleQueried.gnssFixOK = true;
- moduleQueried.carrierSolution = true;
- moduleQueried.groundSpeed = true;
- moduleQueried.headingOfMotion = true;
- moduleQueried.pDOP = true;
- }
- else if (msg->id == UBX_NAV_HPPOSLLH && msg->len == 36)
- {
- timeOfWeek = extractLong(4);
- highResLongitude = extractLong(8);
- highResLatitude = extractLong(12);
- elipsoid = extractLong(16);
- meanSeaLevel = extractLong(20);
- highResLongitudeHp = extractSignedChar(24);
- highResLatitudeHp = extractSignedChar(25);
- elipsoidHp = extractSignedChar(26);
- meanSeaLevelHp = extractSignedChar(27);
- horizontalAccuracy = extractLong(28);
- verticalAccuracy = extractLong(32);
-
- highResModuleQueried.all = true;
- highResModuleQueried.highResLatitude = true;
- highResModuleQueried.highResLatitudeHp = true;
- highResModuleQueried.highResLongitude = true;
- highResModuleQueried.highResLongitudeHp = true;
- highResModuleQueried.elipsoid = true;
- highResModuleQueried.elipsoidHp = true;
- highResModuleQueried.meanSeaLevel = true;
- highResModuleQueried.meanSeaLevelHp = true;
- highResModuleQueried.geoidSeparation = true;
- highResModuleQueried.horizontalAccuracy = true;
- highResModuleQueried.verticalAccuracy = true;
- moduleQueried.gpsiTOW = true; // this can arrive via HPPOS too.
-
- if (_printDebug == true)
- {
- printf("Sec: ");
- printf("%3.5f\n",((float)extractLong(4)) / 1000.0f);
- printf(" ");
- printf("LON: ");
- printf("%3.5f\n",((float)(int32_t)extractLong(8)) / 10000000.0f);
- printf(" ");
- printf("LAT: ");
- printf("%3.5f\n",((float)(int32_t)extractLong(12)) / 10000000.0f);
- printf(" ");
- printf("ELI M: ");
- printf("%3.5f\n",((float)(int32_t)extractLong(16)) / 1000.0f);
- printf(" ");
- printf("MSL M: ");
- printf("%3.5f\n",((float)(int32_t)extractLong(20)) / 1000.0f);
- printf(" ");
- printf("LON HP: ");
- printf("%d\r\n",extractSignedChar(24));
- printf(" ");
- printf("LAT HP: ");
- printf("%d\r\n",extractSignedChar(25));
- printf(" ");
- printf("ELI HP: ");
- printf("%d\r\n",extractSignedChar(26));
- printf(" ");
- printf("MSL HP: ");
- printf("%d\r\n",extractSignedChar(27));
- printf(" ");
- printf("HA 2D M: ");
- printf("%3.5f\n",((float)(int32_t)extractLong(28)) / 10000.0f);
- printf(" ");
- printf("VERT M: ");
- printf("%3.5f\n",((float)(int32_t)extractLong(32)) / 10000.0f);
- }
- }
- break;
- }
-}
-
-//Given a packet and payload, send everything including CRC bytes via I2C port
-sfe_ublox_status_e sendCommand(ubxPacket *outgoingUBX, uint16_t maxWait)
-{
- sfe_ublox_status_e retVal = SFE_UBLOX_STATUS_SUCCESS;
-
- calcChecksum(outgoingUBX); //Sets checksum A and B bytes of the packet
-
- if (_printDebug == true)
- {
- printf("\nSending: ");
- printPacket(outgoingUBX);
- }
-
- if (commType == COMM_TYPE_I2C)
- {
- retVal = sendI2cCommand(outgoingUBX, maxWait);
- if (retVal != SFE_UBLOX_STATUS_SUCCESS)
- {
- if (_printDebug == true)
- {
- printf("Send I2C Command failed");
- }
- return retVal;
- }
- }
-
- if (maxWait > 0)
- {
- //Depending on what we just sent, either we need to look for an ACK or not
- if (outgoingUBX->cls == UBX_CLASS_CFG)
- {
- if (_printDebug == true)
- {
- printf("sendCommand: Waiting for ACK response\r\n");
- }
- retVal = waitForACKResponse(outgoingUBX, outgoingUBX->cls, outgoingUBX->id, maxWait); //Wait for Ack response
- }
- else
- {
- if (_printDebug == true)
- {
- printf("sendCommand: Waiting for No ACK response\r\n");
- }
- retVal = waitForNoACKResponse(outgoingUBX, outgoingUBX->cls, outgoingUBX->id, maxWait); //Wait for Ack response
- }
- }
- return retVal;
-}
-
-
-
-//Returns false if sensor fails to respond to I2C traffic
-sfe_ublox_status_e sendI2cCommand(ubxPacket *outgoingUBX, uint16_t maxWait)
-{
-
- uint8_t cnt = 0;
- /* Total packet consists of 8 bytes minimum and then payload */
- uint8_t GPS_buffer[outgoingUBX->len + 8];
- GPS_buffer[cnt++] = UBX_SYNCH_1; //μ - oh ublox, you're funny. I will call you micro-blox from now on.
- GPS_buffer[cnt++] = UBX_SYNCH_2; //b
- GPS_buffer[cnt++] = outgoingUBX->cls;
- GPS_buffer[cnt++] = outgoingUBX->id;
- GPS_buffer[cnt++] = outgoingUBX->len & 0xFF; //LSB
- GPS_buffer[cnt++] = outgoingUBX->len >> 8; //MSB
-
- for (uint16_t x = 0; x < outgoingUBX->len; x++)
- {
- GPS_buffer[cnt++] = outgoingUBX->payload[x];
- }
-
- GPS_buffer[cnt++] = outgoingUBX->checksumA;
- GPS_buffer[cnt++] = outgoingUBX->checksumB;
-
-
- return ((I2cWriteMemBuffer(&I2c, _gpsI2Caddress << 1,(uint16_t)0xFF, GPS_buffer, cnt) == LMN_STATUS_OK)
- ? SFE_UBLOX_STATUS_SUCCESS : SFE_UBLOX_STATUS_I2C_COMM_FAILURE);
-}
-
-
-//Returns true if I2C device ack's
-bool isConnected(uint16_t maxWait)
-{
-
- // Query navigation rate to see whether we get a meaningful response
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_RATE;
- packetCfg.len = 0;
- packetCfg.startingSpot = 0;
-
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_RECEIVED); // We are polling the RATE so we expect data and an ACK
-}
-
-//Given a message, calc and store the two byte "8-Bit Fletcher" checksum over the entirety of the message
-//This is called before we send a command message
-void calcChecksum(ubxPacket *msg)
-{
- msg->checksumA = 0;
- msg->checksumB = 0;
-
- msg->checksumA += msg->cls;
- msg->checksumB += msg->checksumA;
-
- msg->checksumA += msg->id;
- msg->checksumB += msg->checksumA;
-
- msg->checksumA += (msg->len & 0xFF);
- msg->checksumB += msg->checksumA;
-
- msg->checksumA += (msg->len >> 8);
- msg->checksumB += msg->checksumA;
-
- for (uint16_t i = 0; i < msg->len; i++)
- {
- msg->checksumA += msg->payload[i];
- msg->checksumB += msg->checksumA;
- }
-}
-
-//Given a message and a byte, add to rolling "8-Bit Fletcher" checksum
-//This is used when receiving messages from module
-void addToChecksum(uint8_t incoming)
-{
- rollingChecksumA += incoming;
- rollingChecksumB += rollingChecksumA;
-}
-
-//Pretty prints the current ubxPacket
-void printPacket(ubxPacket *packet)
-{
- if (_printDebug == true)
- {
- printf("CLS:");
- if (packet->cls == UBX_CLASS_NAV) //1
- printf("NAV");
- else if (packet->cls == UBX_CLASS_ACK) //5
- printf("ACK");
- else if (packet->cls == UBX_CLASS_CFG) //6
- printf("CFG");
- else if (packet->cls == UBX_CLASS_MON) //0x0A
- printf("MON");
- else
- {
- printf("0x");
- printf("%d",packet->cls);
- }
-
- printf(" ID:");
- if (packet->cls == UBX_CLASS_NAV && packet->id == UBX_NAV_PVT)
- printf("PVT");
- else if (packet->cls == UBX_CLASS_CFG && packet->id == UBX_CFG_RATE)
- printf("RATE");
- else if (packet->cls == UBX_CLASS_CFG && packet->id == UBX_CFG_CFG)
- printf("SAVE");
- else
- {
- printf("0x");
- printf("%02X",packet->id);
- }
-
- printf(" Len: 0x");
- printf("%02X",packet->len);
-
- // Only printf the payload is ignoreThisPayload is false otherwise
- // we could be printing gibberish from beyond the end of packetBuf
- if (ignoreThisPayload == false)
- {
- printf(" Payload:");
-
- for (int x = 0; x < packet->len; x++)
- {
- printf("0x");
- printf("%02X ",packet->payload[x]);
- }
- }
- else
- {
- printf(" Payload: IGNORED");
- }
- printf("\r\n");
- }
-}
-
-//=-=-=-=-=-=-=-= Specific commands =-=-=-=-=-=-=-==-=-=-=-=-=-=-=
-//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-//When messages from the class CFG are sent to the receiver, the receiver will send an "acknowledge"(UBX - ACK - ACK) or a
-//"not acknowledge"(UBX-ACK-NAK) message back to the sender, depending on whether or not the message was processed correctly.
-//Some messages from other classes also use the same acknowledgement mechanism.
-
-//When we poll or get a setting, we will receive _both_ a config packet and an ACK
-//If the poll or get request is not valid, we will receive _only_ a NACK
-
-//If we are trying to get or poll a setting, then packetCfg.len will be 0 or 1 when the packetCfg is _sent_.
-//If we poll the setting for a particular port using UBX-CFG-PRT then .len will be 1 initially
-//For all other gets or polls, .len will be 0 initially
-//(It would be possible for .len to be 2 _if_ we were using UBX-CFG-MSG to poll the settings for a particular message - but we don't use that (currently))
-
-//If the get or poll _fails_, i.e. is NACK'd, then packetCfg.len could still be 0 or 1 after the NACK is received
-//But if the get or poll is ACK'd, then packetCfg.len will have been updated by the incoming data and will always be at least 2
-
-//If we are going to set the value for a setting, then packetCfg.len will be at least 3 when the packetCfg is _sent_.
-//(UBX-CFG-MSG appears to have the shortest set length of 3 bytes)
-
-//We need to think carefully about how interleaved PVT packets affect things.
-//It is entirely possible that our packetCfg and packetAck were received successfully
-//but while we are still in the "if (checkUblox() == true)" loop a PVT packet is processed
-//or _starts_ to arrive (remember that Serial data can arrive very slowly).
-
-//Returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got an ACK and a valid packetCfg (module is responding with register content)
-//Returns SFE_UBLOX_STATUS_DATA_SENT if we got an ACK and no packetCfg (no valid packetCfg needed, module absorbs new register data)
-//Returns SFE_UBLOX_STATUS_FAIL if something very bad happens (e.g. a double checksum failure)
-//Returns SFE_UBLOX_STATUS_COMMAND_NACK if the packet was not-acknowledged (NACK)
-//Returns SFE_UBLOX_STATUS_CRC_FAIL if we had a checksum failure
-//Returns SFE_UBLOX_STATUS_TIMEOUT if we timed out
-//Returns SFE_UBLOX_STATUS_DATA_OVERWRITTEN if we got an ACK and a valid packetCfg but that the packetCfg has been
-// or is currently being overwritten (remember that Serial data can arrive very slowly)
-sfe_ublox_status_e waitForACKResponse(ubxPacket *outgoingUBX, uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime)
-{
- outgoingUBX->valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; //This will go VALID (or NOT_VALID) when we receive a response to the packet we sent
- packetAck.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED;
- packetBuf.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED;
- outgoingUBX->classAndIDmatch = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; // This will go VALID (or NOT_VALID) when we receive a packet that matches the requested class and ID
- packetAck.classAndIDmatch = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED;
- packetBuf.classAndIDmatch = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED;
-
- unsigned long startTime = SysTimeToMs(SysTimeGet());
- while (SysTimeToMs(SysTimeGet()) - startTime < maxTime)
- {
- DelayMs(i2cPollingWait);
-
- if (checkUbloxInternal(outgoingUBX, requestedClass, requestedID) == true) //See if new data is available. Process bytes as they come in.
- {
- // If both the outgoingUBX->classAndIDmatch and packetAck.classAndIDmatch are VALID
- // and outgoingUBX->valid is _still_ VALID and the class and ID _still_ match
- // then we can be confident that the data in outgoingUBX is valid
- if ((outgoingUBX->classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_VALID) && (packetAck.classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_VALID) && (outgoingUBX->valid == SFE_UBLOX_PACKET_VALIDITY_VALID) && (outgoingUBX->cls == requestedClass) && (outgoingUBX->id == requestedID))
- {
- if (_printDebug == true)
- {
- printf("waitForACKResponse: valid data and valid ACK received after ");
- printf("%ld",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec\r\n");
- }
- return (SFE_UBLOX_STATUS_DATA_RECEIVED); //We received valid data and a correct ACK!
- }
-
- // We can be confident that the data packet (if we are going to get one) will always arrive
- // before the matching ACK. So if we sent a config packet which only produces an ACK
- // then outgoingUBX->classAndIDmatch will be NOT_DEFINED and the packetAck.classAndIDmatch will VALID.
- // We should not check outgoingUBX->valid, outgoingUBX->cls or outgoingUBX->id
- // as these may have been changed by a PVT packet.
- else if ((outgoingUBX->classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED) && (packetAck.classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_VALID))
- {
- if (_printDebug == true)
- {
- printf("waitForACKResponse: no data and valid ACK after ");
- printf("%ld",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec\r\n");
- }
- return (SFE_UBLOX_STATUS_DATA_SENT); //We got an ACK but no data...
- }
-
- // If both the outgoingUBX->classAndIDmatch and packetAck.classAndIDmatch are VALID
- // but the outgoingUBX->cls or ID no longer match then we can be confident that we had
- // valid data but it has been or is currently being overwritten by another packet (e.g. PVT).
- // If (e.g.) a PVT packet is _being_ received: outgoingUBX->valid will be NOT_DEFINED
- // If (e.g.) a PVT packet _has been_ received: outgoingUBX->valid will be VALID (or just possibly NOT_VALID)
- // So we cannot use outgoingUBX->valid as part of this check.
- // Note: the addition of packetBuf should make this check redundant!
- else if ((outgoingUBX->classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_VALID) && (packetAck.classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_VALID) && !((outgoingUBX->cls != requestedClass) || (outgoingUBX->id != requestedID)))
- {
- if (_printDebug == true)
- {
- printf("waitForACKResponse: data being OVERWRITTEN after ");
- printf("%ld\r\n",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec");
- }
- return (SFE_UBLOX_STATUS_DATA_OVERWRITTEN); // Data was valid but has been or is being overwritten
- }
-
- // If packetAck.classAndIDmatch is VALID but both outgoingUBX->valid and outgoingUBX->classAndIDmatch
- // are NOT_VALID then we can be confident we have had a checksum failure on the data packet
- else if ((packetAck.classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_VALID) && (outgoingUBX->classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_NOT_VALID) && (outgoingUBX->valid == SFE_UBLOX_PACKET_VALIDITY_NOT_VALID))
- {
- if (_printDebug == true)
- {
- printf("waitForACKResponse: CRC failed after ");
- printf("%ld\r\n",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec");
- }
- return (SFE_UBLOX_STATUS_CRC_FAIL); //Checksum fail
- }
-
- // If our packet was not-acknowledged (NACK) we do not receive a data packet - we only get the NACK.
- // So you would expect outgoingUBX->valid and outgoingUBX->classAndIDmatch to still be NOT_DEFINED
- // But if a full PVT packet arrives afterwards outgoingUBX->valid could be VALID (or just possibly NOT_VALID)
- // but outgoingUBX->cls and outgoingUBX->id would not match...
- // So I think this is telling us we need a special state for packetAck.classAndIDmatch to tell us
- // the packet was definitely NACK'd otherwise we are possibly just guessing...
- // Note: the addition of packetBuf changes the logic of this, but we'll leave the code as is for now.
- else if (packetAck.classAndIDmatch == SFE_UBLOX_PACKET_NOTACKNOWLEDGED)
- {
- if (_printDebug == true)
- {
- printf("waitForACKResponse: data was NOTACKNOWLEDGED (NACK) after ");
- printf("%ld\r\n",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec");
- }
- return (SFE_UBLOX_STATUS_COMMAND_NACK); //We received a NACK!
- }
-
- // If the outgoingUBX->classAndIDmatch is VALID but the packetAck.classAndIDmatch is NOT_VALID
- // then the ack probably had a checksum error. We will take a gamble and return DATA_RECEIVED.
- // If we were playing safe, we should return FAIL instead
- else if ((outgoingUBX->classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_VALID) && (packetAck.classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_NOT_VALID) && (outgoingUBX->valid == SFE_UBLOX_PACKET_VALIDITY_VALID) && (outgoingUBX->cls == requestedClass) && (outgoingUBX->id == requestedID))
- {
- if (_printDebug == true)
- {
- printf("waitForACKResponse: VALID data and INVALID ACK received after ");
- printf("%ld\r\n",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec");
- }
- return (SFE_UBLOX_STATUS_DATA_RECEIVED); //We received valid data and an invalid ACK!
- }
-
- // If the outgoingUBX->classAndIDmatch is NOT_VALID and the packetAck.classAndIDmatch is NOT_VALID
- // then we return a FAIL. This must be a double checksum failure?
- else if ((outgoingUBX->classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_NOT_VALID) && (packetAck.classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_NOT_VALID))
- {
- if (_printDebug == true)
- {
- printf("waitForACKResponse: INVALID data and INVALID ACK received after ");
- printf("%ld",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec\r\n");
- }
- return (SFE_UBLOX_STATUS_FAIL); //We received invalid data and an invalid ACK!
- }
-
- // If the outgoingUBX->classAndIDmatch is VALID and the packetAck.classAndIDmatch is NOT_DEFINED
- // then the ACK has not yet been received and we should keep waiting for it
- else if ((outgoingUBX->classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_VALID) && (packetAck.classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED))
- {
- if (_printDebug == true)
- {
- printf("waitForACKResponse: valid data after ");
- printf("%ld",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec. Waiting for ACK.\r\n");
- }
- }
-
- } //checkUbloxInternal == true
-
- }
-
- // We have timed out...
- // If the outgoingUBX->classAndIDmatch is VALID then we can take a gamble and return DATA_RECEIVED
- // even though we did not get an ACK
- if ((outgoingUBX->classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_VALID) && (packetAck.classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED) && (outgoingUBX->valid == SFE_UBLOX_PACKET_VALIDITY_VALID) && (outgoingUBX->cls == requestedClass) && (outgoingUBX->id == requestedID))
- {
- if (_printDebug == true)
- {
- printf("waitForACKResponse: TIMEOUT with valid data after ");
- printf("%ld",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec. \r\n");
- }
- return (SFE_UBLOX_STATUS_DATA_RECEIVED); //We received valid data... But no ACK!
- }
-
- if (_printDebug == true)
- {
- printf("waitForACKResponse: TIMEOUT after ");
- printf("%ld",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec. \r\n");
- }
-
- return (SFE_UBLOX_STATUS_TIMEOUT);
-}
-
-//For non-CFG queries no ACK is sent so we use this function
-//Returns SFE_UBLOX_STATUS_DATA_RECEIVED if we got a config packet full of response data that has CLS/ID match to our query packet
-//Returns SFE_UBLOX_STATUS_CRC_FAIL if we got a corrupt config packet that has CLS/ID match to our query packet
-//Returns SFE_UBLOX_STATUS_TIMEOUT if we timed out
-//Returns SFE_UBLOX_STATUS_DATA_OVERWRITTEN if we got an a valid packetCfg but that the packetCfg has been
-// or is currently being overwritten (remember that Serial data can arrive very slowly)
-sfe_ublox_status_e waitForNoACKResponse(ubxPacket *outgoingUBX, uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime)
-{
- outgoingUBX->valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; //This will go VALID (or NOT_VALID) when we receive a response to the packet we sent
- packetAck.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED;
- packetBuf.valid = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED;
- outgoingUBX->classAndIDmatch = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED; // This will go VALID (or NOT_VALID) when we receive a packet that matches the requested class and ID
- packetAck.classAndIDmatch = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED;
- packetBuf.classAndIDmatch = SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED;
-
- unsigned long startTime = SysTimeToMs(SysTimeGet());
- while (SysTimeToMs(SysTimeGet()) - startTime < maxTime)
- {
- DelayMs(i2cPollingWait);
-
- if (checkUbloxInternal(outgoingUBX, requestedClass, requestedID) == true) //See if new data is available. Process bytes as they come in.
- {
-
- // If outgoingUBX->classAndIDmatch is VALID
- // and outgoingUBX->valid is _still_ VALID and the class and ID _still_ match
- // then we can be confident that the data in outgoingUBX is valid
- if ((outgoingUBX->classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_VALID) && (outgoingUBX->valid == SFE_UBLOX_PACKET_VALIDITY_VALID) && (outgoingUBX->cls == requestedClass) && (outgoingUBX->id == requestedID))
- {
- if (_printDebug == true)
- {
- printf("waitForNoACKResponse: valid data with CLS/ID match after ");
- printf("%ld",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec\r\n");
- }
- return (SFE_UBLOX_STATUS_DATA_RECEIVED); //We received valid data!
- }
-
- // If the outgoingUBX->classAndIDmatch is VALID
- // but the outgoingUBX->cls or ID no longer match then we can be confident that we had
- // valid data but it has been or is currently being overwritten by another packet (e.g. PVT).
- // If (e.g.) a PVT packet is _being_ received: outgoingUBX->valid will be NOT_DEFINED
- // If (e.g.) a PVT packet _has been_ received: outgoingUBX->valid will be VALID (or just possibly NOT_VALID)
- // So we cannot use outgoingUBX->valid as part of this check.
- // Note: the addition of packetBuf should make this check redundant!
- else if ((outgoingUBX->classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_VALID) && !((outgoingUBX->cls != requestedClass) || (outgoingUBX->id != requestedID)))
- {
- if (_printDebug == true)
- {
- printf("waitForNoACKResponse: data being OVERWRITTEN after ");
- printf("%ld\r\n",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec");
- }
- return (SFE_UBLOX_STATUS_DATA_OVERWRITTEN); // Data was valid but has been or is being overwritten
- }
-
- // If outgoingUBX->classAndIDmatch is NOT_DEFINED
- // and outgoingUBX->valid is VALID then this must be (e.g.) a PVT packet
- else if ((outgoingUBX->classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED) && (outgoingUBX->valid == SFE_UBLOX_PACKET_VALIDITY_VALID))
- {
- if (_printDebug == true)
- {
- printf("waitForNoACKResponse: valid but UNWANTED data after ");
- printf("%ld\r\n",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec. Class: ");
- printf("%02X\r\n",outgoingUBX->cls);
- printf(" ID: ");
- printf("%02X\r\n",outgoingUBX->id);
- }
- }
-
- // If the outgoingUBX->classAndIDmatch is NOT_VALID then we return CRC failure
- else if (outgoingUBX->classAndIDmatch == SFE_UBLOX_PACKET_VALIDITY_NOT_VALID)
- {
- if (_printDebug == true)
- {
- printf("waitForNoACKResponse: CLS/ID match but failed CRC after ");
- printf("%ld\r\n",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec");
- }
- return (SFE_UBLOX_STATUS_CRC_FAIL); //We received invalid data
- }
- }
-
- }
-
- if (_printDebug == true)
- {
- printf("waitForNoACKResponse: TIMEOUT after ");
- printf("%ld",SysTimeToMs(SysTimeGet()) - startTime);
- printf(" msec. No packet received.\r\n");
- }
-
- return (SFE_UBLOX_STATUS_TIMEOUT);
-}
-
-//Save current configuration to flash and BBR (battery backed RAM)
-//This still works but it is the old way of configuring ublox modules. See getVal and setVal for the new methods
-bool saveConfiguration(uint16_t maxWait)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_CFG;
- packetCfg.len = 12;
- packetCfg.startingSpot = 0;
-
- //Clear packet payload
- for (uint8_t x = 0; x < packetCfg.len; x++)
- packetCfg.payload[x] = 0;
-
- packetCfg.payload[4] = 0xFF; //Set any bit in the saveMask field to save current config to Flash and BBR
- packetCfg.payload[5] = 0xFF;
-
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Save the selected configuration sub-sections to flash and BBR (battery backed RAM)
-//This still works but it is the old way of configuring ublox modules. See getVal and setVal for the new methods
-bool saveConfigSelective(uint32_t configMask, uint16_t maxWait)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_CFG;
- packetCfg.len = 12;
- packetCfg.startingSpot = 0;
-
- //Clear packet payload
- for (uint8_t x = 0; x < packetCfg.len; x++)
- packetCfg.payload[x] = 0;
-
- packetCfg.payload[4] = configMask & 0xFF; //Set the appropriate bits in the saveMask field to save current config to Flash and BBR
- packetCfg.payload[5] = (configMask >> 8) & 0xFF;
- packetCfg.payload[6] = (configMask >> 16) & 0xFF;
- packetCfg.payload[7] = (configMask >> 24) & 0xFF;
-
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Reset module to factory defaults
-//This still works but it is the old way of configuring ublox modules. See getVal and setVal for the new methods
-bool factoryDefault(uint16_t maxWait)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_CFG;
- packetCfg.len = 12;
- packetCfg.startingSpot = 0;
-
- //Clear packet payload
- for (uint8_t x = 0; x < packetCfg.len; x++)
- packetCfg.payload[x] = 0;
-
- packetCfg.payload[0] = 0xFF; //Set any bit in the clearMask field to clear saved config
- packetCfg.payload[1] = 0xFF;
- packetCfg.payload[8] = 0xFF; //Set any bit in the loadMask field to discard current config and rebuild from lower non-volatile memory layers
- packetCfg.payload[9] = 0xFF;
-
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-
-//Given a key, set a 16-bit value
-//This function takes a full 32-bit key
-//Default layer is BBR
-//Configuration of modern Ublox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P
-uint8_t setVal(uint32_t key, uint16_t value, uint8_t layer, uint16_t maxWait)
-{
- return setVal16(key, value, layer, maxWait);
-}
-
-//Given a key, set a 16-bit value
-//This function takes a full 32-bit key
-//Default layer is BBR
-//Configuration of modern Ublox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P
-uint8_t setVal16(uint32_t key, uint16_t value, uint8_t layer, uint16_t maxWait)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_VALSET;
- packetCfg.len = 4 + 4 + 2; //4 byte header, 4 byte key ID, 2 bytes of value
- packetCfg.startingSpot = 0;
-
- //Clear packet payload
- for (uint16_t x = 0; x < packetCfg.len; x++)
- packetCfg.payload[x] = 0;
-
- payloadCfg[0] = 0; //Message Version - set to 0
- payloadCfg[1] = layer; //By default we ask for the BBR layer
-
- //Load key into outgoing payload
- payloadCfg[4] = key >> 8 * 0; //Key LSB
- payloadCfg[5] = key >> 8 * 1;
- payloadCfg[6] = key >> 8 * 2;
- payloadCfg[7] = key >> 8 * 3;
-
- //Load user's value
- payloadCfg[8] = value >> 8 * 0; //Value LSB
- payloadCfg[9] = value >> 8 * 1;
-
- //Send VALSET command with this key and value
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Given a key, set an 8-bit value
-//This function takes a full 32-bit key
-//Default layer is BBR
-//Configuration of modern Ublox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P
-uint8_t setVal8(uint32_t key, uint8_t value, uint8_t layer, uint16_t maxWait)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_VALSET;
- packetCfg.len = 4 + 4 + 1; //4 byte header, 4 byte key ID, 1 byte value
- packetCfg.startingSpot = 0;
-
- //Clear packet payload
- for (uint16_t x = 0; x < packetCfg.len; x++)
- packetCfg.payload[x] = 0;
-
- payloadCfg[0] = 0; //Message Version - set to 0
- payloadCfg[1] = layer; //By default we ask for the BBR layer
-
- //Load key into outgoing payload
- payloadCfg[4] = key >> 8 * 0; //Key LSB
- payloadCfg[5] = key >> 8 * 1;
- payloadCfg[6] = key >> 8 * 2;
- payloadCfg[7] = key >> 8 * 3;
-
- //Load user's value
- payloadCfg[8] = value; //Value
-
- //Send VALSET command with this key and value
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Given a key, set a 32-bit value
-//This function takes a full 32-bit key
-//Default layer is BBR
-//Configuration of modern Ublox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P
-uint8_t setVal32(uint32_t key, uint32_t value, uint8_t layer, uint16_t maxWait)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_VALSET;
- packetCfg.len = 4 + 4 + 4; //4 byte header, 4 byte key ID, 4 bytes of value
- packetCfg.startingSpot = 0;
-
- //Clear packet payload
- for (uint16_t x = 0; x < packetCfg.len; x++)
- packetCfg.payload[x] = 0;
-
- payloadCfg[0] = 0; //Message Version - set to 0
- payloadCfg[1] = layer; //By default we ask for the BBR layer
-
- //Load key into outgoing payload
- payloadCfg[4] = key >> 8 * 0; //Key LSB
- payloadCfg[5] = key >> 8 * 1;
- payloadCfg[6] = key >> 8 * 2;
- payloadCfg[7] = key >> 8 * 3;
-
- //Load user's value
- payloadCfg[8] = value >> 8 * 0; //Value LSB
- payloadCfg[9] = value >> 8 * 1;
- payloadCfg[10] = value >> 8 * 2;
- payloadCfg[11] = value >> 8 * 3;
-
- //Send VALSET command with this key and value
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Start defining a new UBX-CFG-VALSET ubxPacket
-//This function takes a full 32-bit key and 32-bit value
-//Default layer is BBR
-//Configuration of modern Ublox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P
-uint8_t newCfgValset32(uint32_t key, uint32_t value, uint8_t layer)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_VALSET;
- packetCfg.len = 4 + 4 + 4; //4 byte header, 4 byte key ID, 4 bytes of value
- packetCfg.startingSpot = 0;
-
- //Clear packet payload
- for (uint16_t x = 0; x < MAX_PAYLOAD_SIZE; x++)
- packetCfg.payload[x] = 0;
-
- payloadCfg[0] = 0; //Message Version - set to 0
- payloadCfg[1] = layer; //By default we ask for the BBR layer
-
- //Load key into outgoing payload
- payloadCfg[4] = key >> 8 * 0; //Key LSB
- payloadCfg[5] = key >> 8 * 1;
- payloadCfg[6] = key >> 8 * 2;
- payloadCfg[7] = key >> 8 * 3;
-
- //Load user's value
- payloadCfg[8] = value >> 8 * 0; //Value LSB
- payloadCfg[9] = value >> 8 * 1;
- payloadCfg[10] = value >> 8 * 2;
- payloadCfg[11] = value >> 8 * 3;
-
- //All done
- return (true);
-}
-
-//Start defining a new UBX-CFG-VALSET ubxPacket
-//This function takes a full 32-bit key and 16-bit value
-//Default layer is BBR
-//Configuration of modern Ublox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P
-uint8_t newCfgValset16(uint32_t key, uint16_t value, uint8_t layer)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_VALSET;
- packetCfg.len = 4 + 4 + 2; //4 byte header, 4 byte key ID, 2 bytes of value
- packetCfg.startingSpot = 0;
-
- //Clear packet payload
- for (uint16_t x = 0; x < MAX_PAYLOAD_SIZE; x++)
- packetCfg.payload[x] = 0;
-
- payloadCfg[0] = 0; //Message Version - set to 0
- payloadCfg[1] = layer; //By default we ask for the BBR layer
-
- //Load key into outgoing payload
- payloadCfg[4] = key >> 8 * 0; //Key LSB
- payloadCfg[5] = key >> 8 * 1;
- payloadCfg[6] = key >> 8 * 2;
- payloadCfg[7] = key >> 8 * 3;
-
- //Load user's value
- payloadCfg[8] = value >> 8 * 0; //Value LSB
- payloadCfg[9] = value >> 8 * 1;
-
- //All done
- return (true);
-}
-
-//Start defining a new UBX-CFG-VALSET ubxPacket
-//This function takes a full 32-bit key and 8-bit value
-//Default layer is BBR
-//Configuration of modern Ublox modules is now done via getVal/setVal/delVal, ie protocol v27 and above found on ZED-F9P
-uint8_t newCfgValset8(uint32_t key, uint8_t value, uint8_t layer)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_VALSET;
- packetCfg.len = 4 + 4 + 1; //4 byte header, 4 byte key ID, 1 byte value
- packetCfg.startingSpot = 0;
-
- //Clear packet payload
- for (uint16_t x = 0; x < MAX_PAYLOAD_SIZE; x++)
- packetCfg.payload[x] = 0;
-
- payloadCfg[0] = 0; //Message Version - set to 0
- payloadCfg[1] = layer; //By default we ask for the BBR layer
-
- //Load key into outgoing payload
- payloadCfg[4] = key >> 8 * 0; //Key LSB
- payloadCfg[5] = key >> 8 * 1;
- payloadCfg[6] = key >> 8 * 2;
- payloadCfg[7] = key >> 8 * 3;
-
- //Load user's value
- payloadCfg[8] = value; //Value
-
- //All done
- return (true);
-}
-
-//Add another keyID and value to an existing UBX-CFG-VALSET ubxPacket
-//This function takes a full 32-bit key and 32-bit value
-uint8_t addCfgValset32(uint32_t key, uint32_t value)
-{
- //Load key into outgoing payload
- payloadCfg[packetCfg.len + 0] = key >> 8 * 0; //Key LSB
- payloadCfg[packetCfg.len + 1] = key >> 8 * 1;
- payloadCfg[packetCfg.len + 2] = key >> 8 * 2;
- payloadCfg[packetCfg.len + 3] = key >> 8 * 3;
-
- //Load user's value
- payloadCfg[packetCfg.len + 4] = value >> 8 * 0; //Value LSB
- payloadCfg[packetCfg.len + 5] = value >> 8 * 1;
- payloadCfg[packetCfg.len + 6] = value >> 8 * 2;
- payloadCfg[packetCfg.len + 7] = value >> 8 * 3;
-
- //Update packet length: 4 byte key ID, 4 bytes of value
- packetCfg.len = packetCfg.len + 4 + 4;
-
- //All done
- return (true);
-}
-
-//Add another keyID and value to an existing UBX-CFG-VALSET ubxPacket
-//This function takes a full 32-bit key and 16-bit value
-uint8_t addCfgValset16(uint32_t key, uint16_t value)
-{
- //Load key into outgoing payload
- payloadCfg[packetCfg.len + 0] = key >> 8 * 0; //Key LSB
- payloadCfg[packetCfg.len + 1] = key >> 8 * 1;
- payloadCfg[packetCfg.len + 2] = key >> 8 * 2;
- payloadCfg[packetCfg.len + 3] = key >> 8 * 3;
-
- //Load user's value
- payloadCfg[packetCfg.len + 4] = value >> 8 * 0; //Value LSB
- payloadCfg[packetCfg.len + 5] = value >> 8 * 1;
-
- //Update packet length: 4 byte key ID, 2 bytes of value
- packetCfg.len = packetCfg.len + 4 + 2;
-
- //All done
- return (true);
-}
-
-//Add another keyID and value to an existing UBX-CFG-VALSET ubxPacket
-//This function takes a full 32-bit key and 8-bit value
-uint8_t addCfgValset8(uint32_t key, uint8_t value)
-{
- //Load key into outgoing payload
- payloadCfg[packetCfg.len + 0] = key >> 8 * 0; //Key LSB
- payloadCfg[packetCfg.len + 1] = key >> 8 * 1;
- payloadCfg[packetCfg.len + 2] = key >> 8 * 2;
- payloadCfg[packetCfg.len + 3] = key >> 8 * 3;
-
- //Load user's value
- payloadCfg[packetCfg.len + 4] = value; //Value
-
- //Update packet length: 4 byte key ID, 1 byte value
- packetCfg.len = packetCfg.len + 4 + 1;
-
- //All done
- return (true);
-}
-
-//Add a final keyID and value to an existing UBX-CFG-VALSET ubxPacket and send it
-//This function takes a full 32-bit key and 32-bit value
-uint8_t sendCfgValset32(uint32_t key, uint32_t value, uint16_t maxWait)
-{
- //Load keyID and value into outgoing payload
- addCfgValset32(key, value);
-
- //Send VALSET command with this key and value
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Add a final keyID and value to an existing UBX-CFG-VALSET ubxPacket and send it
-//This function takes a full 32-bit key and 16-bit value
-uint8_t sendCfgValset16(uint32_t key, uint16_t value, uint16_t maxWait)
-{
- //Load keyID and value into outgoing payload
- addCfgValset16(key, value);
-
- //Send VALSET command with this key and value
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Add a final keyID and value to an existing UBX-CFG-VALSET ubxPacket and send it
-//This function takes a full 32-bit key and 8-bit value
-uint8_t sendCfgValset8(uint32_t key, uint8_t value, uint16_t maxWait)
-{
- //Load keyID and value into outgoing payload
- addCfgValset8(key, value);
-
- //Send VALSET command with this key and value
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Get the current TimeMode3 settings - these contain survey in statuses
-bool getSurveyMode(uint16_t maxWait)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_TMODE3;
- packetCfg.len = 0;
- packetCfg.startingSpot = 0;
-
- return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_RECEIVED); // We are expecting data and an ACK
-}
-
-//Control Survey-In for NEO-M8P
-bool setSurveyMode(uint8_t mode, uint16_t observationTime, float requiredAccuracy, uint16_t maxWait)
-{
- if (getSurveyMode(maxWait) == false) //Ask module for the current TimeMode3 settings. Loads into payloadCfg.
- return (false);
-
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_TMODE3;
- packetCfg.len = 40;
- packetCfg.startingSpot = 0;
-
- //Clear packet payload
- for (uint8_t x = 0; x < packetCfg.len; x++)
- packetCfg.payload[x] = 0;
-
- //payloadCfg should be loaded with poll response. Now modify only the bits we care about
- payloadCfg[2] = mode; //Set mode. Survey-In and Disabled are most common. Use ECEF (not LAT/LON/ALT).
-
- //svinMinDur is U4 (uint32_t) but we'll only use a uint16_t (waiting more than 65535 seconds seems excessive!)
- payloadCfg[24] = observationTime & 0xFF; //svinMinDur in seconds
- payloadCfg[25] = observationTime >> 8; //svinMinDur in seconds
- payloadCfg[26] = 0; //Truncate to 16 bits
- payloadCfg[27] = 0; //Truncate to 16 bits
-
- //svinAccLimit is U4 (uint32_t) in 0.1mm.
- uint32_t svinAccLimit = (uint32_t)(requiredAccuracy * 10000.0); //Convert m to 0.1mm
- payloadCfg[28] = svinAccLimit & 0xFF; //svinAccLimit in 0.1mm increments
- payloadCfg[29] = svinAccLimit >> 8;
- payloadCfg[30] = svinAccLimit >> 16;
- payloadCfg[31] = svinAccLimit >> 24;
-
- return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Begin Survey-In for NEO-M8P
-bool enableSurveyMode(uint16_t observationTime, float requiredAccuracy, uint16_t maxWait)
-{
- return (setSurveyMode(SVIN_MODE_ENABLE, observationTime, requiredAccuracy, maxWait));
-}
-
-//Stop Survey-In for NEO-M8P
-bool disableSurveyMode(uint16_t maxWait)
-{
- return (setSurveyMode(SVIN_MODE_DISABLE, 0, 0, maxWait));
-}
-
-
-//Loads the payloadCfg array with the current protocol bits located the UBX-CFG-PRT register for a given port
-bool getPortSettings(uint8_t portID, uint16_t maxWait)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_PRT;
- packetCfg.len = 1;
- packetCfg.startingSpot = 0;
-
- payloadCfg[0] = portID;
-
- return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_RECEIVED); // We are expecting data and an ACK
-}
-
-//Configure a given port to output UBX, NMEA, RTCM3 or a combination thereof
-//Port 0=I2c, 1=UART1, 2=UART2, 3=USB, 4=SPI
-//Bit:0 = UBX, :1=NMEA, :5=RTCM3
-bool setPortOutput(uint8_t portID, uint8_t outStreamSettings, uint16_t maxWait)
-{
- //Get the current config values for this port ID
- if (getPortSettings(portID, maxWait) == false)
- return (false); //Something went wrong. Bail.
-
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_PRT;
- packetCfg.len = 20;
- packetCfg.startingSpot = 0;
-
- //payloadCfg is now loaded with current bytes. Change only the ones we need to
- payloadCfg[14] = outStreamSettings; //OutProtocolMask LSB - Set outStream bits
-
- return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Configure a given port to input UBX, NMEA, RTCM3 or a combination thereof
-//Port 0=I2c, 1=UART1, 2=UART2, 3=USB, 4=SPI
-//Bit:0 = UBX, :1=NMEA, :5=RTCM3
-bool setPortInput(uint8_t portID, uint8_t inStreamSettings, uint16_t maxWait)
-{
- //Get the current config values for this port ID
- //This will load the payloadCfg array with current port settings
- if (getPortSettings(portID, maxWait) == false)
- return (false); //Something went wrong. Bail.
-
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_PRT;
- packetCfg.len = 20;
- packetCfg.startingSpot = 0;
-
- //payloadCfg is now loaded with current bytes. Change only the ones we need to
- payloadCfg[12] = inStreamSettings; //InProtocolMask LSB - Set inStream bits
-
- return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Configure a port to output UBX, NMEA, RTCM3 or a combination thereof
-bool setI2COutput(uint8_t comSettings, uint16_t maxWait)
-{
- return (setPortOutput(COM_PORT_I2C, comSettings, maxWait));
-}
-bool setUART1Output(uint8_t comSettings, uint16_t maxWait)
-{
- return (setPortOutput(COM_PORT_UART1, comSettings, maxWait));
-}
-bool setUART2Output(uint8_t comSettings, uint16_t maxWait)
-{
- return (setPortOutput(COM_PORT_UART2, comSettings, maxWait));
-}
-bool setUSBOutput(uint8_t comSettings, uint16_t maxWait)
-{
- return (setPortOutput(COM_PORT_USB, comSettings, maxWait));
-}
-bool setSPIOutput(uint8_t comSettings, uint16_t maxWait)
-{
- return (setPortOutput(COM_PORT_SPI, comSettings, maxWait));
-}
-
-//Set the rate at which the module will give us an updated navigation solution
-//Expects a number that is the updates per second. For example 1 = 1Hz, 2 = 2Hz, etc.
-//Max is 40Hz(?!)
-bool setNavigationFrequency(uint8_t navFreq, uint16_t maxWait)
-{
- //iupdateRate > 40) updateRate = 40; //Not needed: module will correct out of bounds values
-
- //Adjust the I2C polling timeout based on update rate
- i2cPollingWait = 1000 / (navFreq * 4); //This is the number of ms to wait between checks for new I2C data
-
- //Query the module for the latest lat/long
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_RATE;
- packetCfg.len = 0;
- packetCfg.startingSpot = 0;
-
- //This will load the payloadCfg array with current settings of the given register
- if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK
- return (false); //If command send fails then bail
-
- uint16_t measurementRate = 1000 / navFreq;
-
- //payloadCfg is now loaded with current bytes. Change only the ones we need to
- payloadCfg[0] = measurementRate & 0xFF; //measRate LSB
- payloadCfg[1] = measurementRate >> 8; //measRate MSB
-
- return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Get the rate at which the module is outputting nav solutions
-uint8_t getNavigationFrequency(uint16_t maxWait)
-{
- //Query the module for the latest lat/long
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_RATE;
- packetCfg.len = 0;
- packetCfg.startingSpot = 0;
-
- //This will load the payloadCfg array with current settings of the given register
- if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK
- return (false); //If command send fails then bail
-
- uint16_t measurementRate = 0;
-
- //payloadCfg is now loaded with current bytes. Get what we need
- measurementRate = extractInt(0); //Pull from payloadCfg at measRate LSB
-
- measurementRate = 1000 / measurementRate; //This may return an int when it's a float, but I'd rather not return 4 bytes
- return (measurementRate);
-}
-
-//In case no config access to the GPS is possible and PVT is send cyclically already
-//set config to suitable parameters
-bool assumeAutoPVT(bool enabled, bool implicitUpdate)
-{
- bool changes = autoPVT != enabled || autoPVTImplicitUpdate != implicitUpdate;
- if (changes)
- {
- autoPVT = enabled;
- autoPVTImplicitUpdate = implicitUpdate;
- }
- return changes;
-}
-
-
-//Configure a given message type for a given port (UART1, I2C, SPI, etc)
-bool configureMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint8_t sendRate, uint16_t maxWait)
-{
- //Poll for the current settings for a given message
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_MSG;
- packetCfg.len = 2;
- packetCfg.startingSpot = 0;
-
- payloadCfg[0] = msgClass;
- payloadCfg[1] = msgID;
-
- //This will load the payloadCfg array with current settings of the given register
- if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK
- return (false); //If command send fails then bail
-
- //Now send it back with new mods
- packetCfg.len = 8;
-
- //payloadCfg is now loaded with current bytes. Change only the ones we need to
- payloadCfg[2 + portID] = sendRate; //Send rate is relative to the event a message is registered on. For example, if the rate of a navigation message is set to 2, the message is sent every 2nd navigation solution.
-
- return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Enable a given message type, default of 1 per update rate (usually 1 per second)
-bool enableMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint8_t rate, uint16_t maxWait)
-{
- return (configureMessage(msgClass, msgID, portID, rate, maxWait));
-}
-//Disable a given message type on a given port
-bool disableMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint16_t maxWait)
-{
- return (configureMessage(msgClass, msgID, portID, 0, maxWait));
-}
-
-bool enableNMEAMessage(uint8_t msgID, uint8_t portID, uint8_t rate, uint16_t maxWait)
-{
- return (configureMessage(UBX_CLASS_NMEA, msgID, portID, rate, maxWait));
-}
-bool disableNMEAMessage(uint8_t msgID, uint8_t portID, uint16_t maxWait)
-{
- return (enableNMEAMessage(msgID, portID, 0, maxWait));
-}
-
-//Given a message number turns on a message ID for output over a given portID (UART, I2C, SPI, USB, etc)
-//To disable a message, set secondsBetween messages to 0
-//Note: This function will return false if the message is already enabled
-//For base station RTK output we need to enable various sentences
-
-//NEO-M8P has four:
-//1005 = 0xF5 0x05 - Stationary RTK reference ARP
-//1077 = 0xF5 0x4D - GPS MSM7
-//1087 = 0xF5 0x57 - GLONASS MSM7
-//1230 = 0xF5 0xE6 - GLONASS code-phase biases, set to once every 10 seconds
-
-//ZED-F9P has six:
-//1005, 1074, 1084, 1094, 1124, 1230
-
-//Much of this configuration is not documented and instead discerned from u-center binary console
-bool enableRTCMmessage(uint8_t messageNumber, uint8_t portID, uint8_t sendRate, uint16_t maxWait)
-{
- return (configureMessage(UBX_RTCM_MSB, messageNumber, portID, sendRate, maxWait));
-}
-
-//Disable a given message on a given port by setting secondsBetweenMessages to zero
-bool disableRTCMmessage(uint8_t messageNumber, uint8_t portID, uint16_t maxWait)
-{
- return (enableRTCMmessage(messageNumber, portID, 0, maxWait));
-}
-
-
-
-//Clear the antenna control settings using UBX-CFG-ANT
-//This function is hopefully redundant but may be needed to release
-//any PIO pins pre-allocated for antenna functions
-bool clearAntPIO(uint16_t maxWait)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_ANT;
- packetCfg.len = 4;
- packetCfg.startingSpot = 0;
-
- payloadCfg[0] = 0x10; // Antenna flag mask: set the recovery bit
- payloadCfg[1] = 0;
- payloadCfg[2] = 0xFF; // Antenna pin configuration: set pinSwitch and pinSCD to 31
- payloadCfg[3] = 0xFF; // Antenna pin configuration: set pinOCD to 31, set reconfig bit
-
- return ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-
-//Power Save Mode
-//Enables/Disables Low Power Mode using UBX-CFG-RXM
-bool powerSaveMode(bool power_save, uint16_t maxWait)
-{
- // Now let's change the power setting using UBX-CFG-RXM
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_RXM;
- packetCfg.len = 2;
- packetCfg.startingSpot = 0;
-
- payloadCfg[0] = 0x00;
-
- if (power_save)
- {
- payloadCfg[1] = 1; // Power Save Mode
- }
- else
- {
- payloadCfg[1] = 0; // Continuous Mode
- }
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_SUCCESS); // We are only expecting an ACK
-}
-
-// Get Power Save Mode
-// Returns the current Low Power Mode using UBX-CFG-RXM
-// Returns 255 if the sendCommand fails
-uint8_t getPowerSaveMode(uint16_t maxWait)
-{
- // Let's begin by checking the Protocol Version as UBX_CFG_RXM is not supported on the ZED (protocol >= 27)
- uint8_t protVer = getProtocolVersionHigh(maxWait);
- /*
- if (_printDebug == true)
- {
- printf("Protocol version is ");
- printf(protVer);
- }
- */
- if (protVer >= 27)
- {
- if (_printDebug == true)
- {
- printf("powerSaveMode (UBX-CFG-RXM) is not supported by this protocol version");
- }
- return (255);
- }
-
- // Now let's read the power setting using UBX-CFG-RXM
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_RXM;
- packetCfg.len = 0;
- packetCfg.startingSpot = 0;
-
- //Ask module for the current power management settings. Loads into payloadCfg.
- if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK
- return (255);
-
- return (payloadCfg[1]); // Return the low power mode
-}
-
-// Set the power saving config Setting using UBX-CFG-PM2
-bool set_powersave_config(uint16_t maxWait)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_PM2;
- packetCfg.len = 44;
- packetCfg.startingSpot = 0;
-
- /**
- * @brief Message commands the Ublox to:
- * 1. Force into backup mode when EXTINT0 pin is pulled low
- * 2. Force into active search mode when EXTINT0 is pulled high
- * 3. Don't automatically schedule GPS wakup and searches for fix. Manually control it from
- * the MCU using the EXTINT0 pin.
- *
- */
- uint8_t pm2_config_message[] = {
- 0x01, // Version
- 0x06, // reserved1
- 0xAF, // maxStartupStateDur(seconds)
- 0x00, // reserved2
- 0x6E, 0x90, 0x40, 0x01, // flags
- 0x00, 0x00, 0x00, 0x00, // update period ms
- 0x00, 0x00, 0x00, 0x00, // search period ms
- 0x00, 0x00, 0x00, 0x00, // grid offset
- 0x05, 0x00, // Ontime (s)
- 0x00, 0x00, // minAcqtime(s)
- 0x2C, 0x01, 0x00, 0x00, 0x4F, 0xC1, 0x03, 0x00, 0x87, 0x02, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x64, 0x40, 0x01, 0x00, // reserved
- };
-
- memcpy(payloadCfg, pm2_config_message, packetCfg.len);
-
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-/* Use only the American GPS constellation. Setting using UBX-CFG-GNSS */
-bool setGPS_constellation_only(uint16_t maxWait)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_GNSS;
- packetCfg.len = 0x3C;
- packetCfg.startingSpot = 0;
-
- static uint8_t setGPSonly[] = {
- 0x00, 0x00, 0x20, 0x07, /* use 32 channels, 7 configs following */
- 0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, /* GPS enable */
- 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x01, /* SBAS disable */
- 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, /* Galileo disable */
- 0x03, 0x08, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, /* Beidou disable */
- 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, /* IMES disable */
- 0x05, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, /* QZSS enable */
- 0x06, 0x08, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x01, /* GLONASS disable */
- };
-
- memcpy(payloadCfg, setGPSonly, packetCfg.len);
-
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Change the dynamic platform model using UBX-CFG-NAV5
-//Possible values are:
-//PORTABLE,STATIONARY,PEDESTRIAN,AUTOMOTIVE,SEA,
-//AIRBORNE1g,AIRBORNE2g,AIRBORNE4g,WRIST,BIKE
-//WRIST is not supported in protocol versions less than 18
-//BIKE is supported in protocol versions 19.2
-bool setDynamicModel(dynModel newDynamicModel, uint16_t maxWait)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_NAV5;
- packetCfg.len = 0;
- packetCfg.startingSpot = 0;
-
- //Ask module for the current navigation model settings. Loads into payloadCfg.
- if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK
- return (false);
-
- payloadCfg[0] = 0x01; // mask: set only the dyn bit (0)
- payloadCfg[1] = 0x00; // mask
- payloadCfg[2] = newDynamicModel; // dynModel
-
- packetCfg.len = 36;
- packetCfg.startingSpot = 0;
-
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
-}
-
-//Get the dynamic platform model using UBX-CFG-NAV5
-//Returns 255 if the sendCommand fails
-uint8_t getDynamicModel(uint16_t maxWait)
-{
- packetCfg.cls = UBX_CLASS_CFG;
- packetCfg.id = UBX_CFG_NAV5;
- packetCfg.len = 0;
- packetCfg.startingSpot = 0;
-
- //Ask module for the current navigation model settings. Loads into payloadCfg.
- if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK
- return (255);
-
- return (payloadCfg[2]); // Return the dynamic model
-}
-
-/**
- * @brief Set the Soft Backup object
- *
- * @param do_it
- * @param maxWait
- * @return true
- * @return false
- */
-void setSoftBackup(bool do_it)
-{
- packetCfg.cls = UBX_CLASS_RXM;
- packetCfg.id = UBX_RXM_PMREQ;
- packetCfg.len = 8;
- packetCfg.startingSpot = 0;
-
- /* U4 Duration(ms) of backup. Set 0 for inifinity */
- payloadCfg[0] = 0x00;
- payloadCfg[1] = 0x00;
- payloadCfg[2] = 0x00;
- payloadCfg[3] = 0x00;
-
- /* X4 Backup flag on bit 2 */
- if (do_it == true)
- {
- payloadCfg[4] = 0x02;
- }
- else
- {
- payloadCfg[4] = 0x00;
- }
- payloadCfg[5] = 0x00;
- payloadCfg[6] = 0x00;
- payloadCfg[7] = 0x00;
-
- /* Wakup Sources */
- payloadCfg[12] = 0x20; /* 0b00100000 Wake up the receiver if there is an edge on the EXTINT0 pin */
-
- sendCommand(&packetCfg, 0); // don't expect ACK
-}
-
-//Given a spot in the payload array, extract four bytes and build a long
-uint32_t extractLong(uint8_t spotToStart)
-{
- uint32_t val = 0;
- val |= (uint32_t)payloadCfg[spotToStart + 0] << 8 * 0;
- val |= (uint32_t)payloadCfg[spotToStart + 1] << 8 * 1;
- val |= (uint32_t)payloadCfg[spotToStart + 2] << 8 * 2;
- val |= (uint32_t)payloadCfg[spotToStart + 3] << 8 * 3;
- return (val);
-}
-
-//Given a spot in the payload array, extract two bytes and build an int
-uint16_t extractInt(uint8_t spotToStart)
-{
- uint16_t val = 0;
- val |= (uint16_t)payloadCfg[spotToStart + 0] << 8 * 0;
- val |= (uint16_t)payloadCfg[spotToStart + 1] << 8 * 1;
- return (val);
-}
-
-//Given a spot, extract a byte from the payload
-uint8_t extractByte(uint8_t spotToStart)
-{
- return (payloadCfg[spotToStart]);
-}
-
-//Given a spot, extract a signed 8-bit value from the payload
-int8_t extractSignedChar(uint8_t spotToStart)
-{
- return ((int8_t)payloadCfg[spotToStart]);
-}
-
-//Get the current year
-uint16_t getYear(uint16_t maxWait)
-{
- if (moduleQueried.gpsYear == false)
- getPVT(maxWait);
- moduleQueried.gpsYear = false; //Since we are about to give this to user, mark this data as stale
- return (gpsYear);
-}
-
-//Get the current month
-uint8_t getMonth(uint16_t maxWait)
-{
- if (moduleQueried.gpsMonth == false)
- getPVT(maxWait);
- moduleQueried.gpsMonth = false; //Since we are about to give this to user, mark this data as stale
- return (gpsMonth);
-}
-
-//Get the current day
-uint8_t getDay(uint16_t maxWait)
-{
- if (moduleQueried.gpsDay == false)
- getPVT(maxWait);
- moduleQueried.gpsDay = false; //Since we are about to give this to user, mark this data as stale
- return (gpsDay);
-}
-
-//Get the current hour
-uint8_t getHour(uint16_t maxWait)
-{
- if (moduleQueried.gpsHour == false)
- getPVT(maxWait);
- moduleQueried.gpsHour = false; //Since we are about to give this to user, mark this data as stale
- return (gpsHour);
-}
-
-//Get the current minute
-uint8_t getMinute(uint16_t maxWait)
-{
- if (moduleQueried.gpsMinute == false)
- getPVT(maxWait);
- moduleQueried.gpsMinute = false; //Since we are about to give this to user, mark this data as stale
- return (gpsMinute);
-}
-
-//Get the current second
-uint8_t getSecond(uint16_t maxWait)
-{
- if (moduleQueried.gpsSecond == false)
- getPVT(maxWait);
- moduleQueried.gpsSecond = false; //Since we are about to give this to user, mark this data as stale
- return (gpsSecond);
-}
-
-//Get the current millisecond
-uint16_t getMillisecond(uint16_t maxWait)
-{
- if (moduleQueried.gpsiTOW == false)
- getPVT(maxWait);
- moduleQueried.gpsiTOW = false; //Since we are about to give this to user, mark this data as stale
- return (gpsMillisecond);
-}
-
-//Get the current nanoseconds - includes milliseconds
-int32_t getNanosecond(uint16_t maxWait)
-{
- if (moduleQueried.gpsNanosecond == false)
- getPVT(maxWait);
- moduleQueried.gpsNanosecond = false; //Since we are about to give this to user, mark this data as stale
- return (gpsNanosecond);
-}
-
-//Get the latest Position/Velocity/Time solution and fill all global variables
-bool getPVT(uint16_t maxWait)
-{
- if (autoPVT && autoPVTImplicitUpdate)
- {
- //The GPS is automatically reporting, we just check whether we got unread data
- if (_printDebug == true)
- {
- printf("getPVT: Autoreporting");
- }
- checkUbloxInternal(&packetCfg, UBX_CLASS_NAV, UBX_NAV_PVT);
- return moduleQueried.all;
- }
- else if (autoPVT && !autoPVTImplicitUpdate)
- {
- //Someone else has to call checkUblox for us...
- if (_printDebug == true)
- {
- printf("getPVT: Exit immediately");
- }
- return (false);
- }
- else
- {
- if (_printDebug == true)
- {
- printf("getPVT: Polling");
- }
-
- //The GPS is not automatically reporting navigation position so we have to poll explicitly
- packetCfg.cls = UBX_CLASS_NAV;
- packetCfg.id = UBX_NAV_PVT;
- packetCfg.len = 0;
- //packetCfg.startingSpot = 20; //Begin listening at spot 20 so we can record up to 20+MAX_PAYLOAD_SIZE = 84 bytes Note:now hard-coded in processUBX
-
- //The data is parsed as part of processing the response
- sfe_ublox_status_e retVal = sendCommand(&packetCfg, maxWait);
-
- if (retVal == SFE_UBLOX_STATUS_DATA_RECEIVED)
- return (true);
-
- if (_printDebug == true)
- {
- printf("getPVT retVal: ");
- printf("%s",statusString(retVal));
- }
- return (false);
- }
-}
-
-uint32_t getTimeOfWeek(uint16_t maxWait /* = 250*/)
-{
- if (moduleQueried.gpsiTOW == false)
- getPVT(maxWait);
- moduleQueried.gpsiTOW = false; //Since we are about to give this to user, mark this data as stale
- return (timeOfWeek);
-}
-
-int32_t getHighResLatitude(uint16_t maxWait /* = 250*/)
-{
- if (highResModuleQueried.highResLatitude == false)
- getHPPOSLLH(maxWait);
- highResModuleQueried.highResLatitude = false; //Since we are about to give this to user, mark this data as stale
- return (highResLatitude);
-}
-
-int8_t getHighResLatitudeHp(uint16_t maxWait /* = 250*/)
-{
- if (highResModuleQueried.highResLatitudeHp == false)
- getHPPOSLLH(maxWait);
- highResModuleQueried.highResLatitudeHp = false; //Since we are about to give this to user, mark this data as stale
- return (highResLatitudeHp);
-}
-
-int32_t getHighResLongitude(uint16_t maxWait /* = 250*/)
-{
- if (highResModuleQueried.highResLongitude == false)
- getHPPOSLLH(maxWait);
- highResModuleQueried.highResLongitude = false; //Since we are about to give this to user, mark this data as stale
- return (highResLongitude);
-}
-
-int8_t getHighResLongitudeHp(uint16_t maxWait /* = 250*/)
-{
- if (highResModuleQueried.highResLongitudeHp == false)
- getHPPOSLLH(maxWait);
- highResModuleQueried.highResLongitudeHp = false; //Since we are about to give this to user, mark this data as stale
- return (highResLongitudeHp);
-}
-
-int32_t getElipsoid(uint16_t maxWait /* = 250*/)
-{
- if (highResModuleQueried.elipsoid == false)
- getHPPOSLLH(maxWait);
- highResModuleQueried.elipsoid = false; //Since we are about to give this to user, mark this data as stale
- return (elipsoid);
-}
-
-int8_t getElipsoidHp(uint16_t maxWait /* = 250*/)
-{
- if (highResModuleQueried.elipsoidHp == false)
- getHPPOSLLH(maxWait);
- highResModuleQueried.elipsoidHp = false; //Since we are about to give this to user, mark this data as stale
- return (elipsoidHp);
-}
-
-int32_t getMeanSeaLevel(uint16_t maxWait /* = 250*/)
-{
- if (highResModuleQueried.meanSeaLevel == false)
- getHPPOSLLH(maxWait);
- highResModuleQueried.meanSeaLevel = false; //Since we are about to give this to user, mark this data as stale
- return (meanSeaLevel);
-}
-
-int8_t getMeanSeaLevelHp(uint16_t maxWait /* = 250*/)
-{
- if (highResModuleQueried.meanSeaLevelHp == false)
- getHPPOSLLH(maxWait);
- highResModuleQueried.meanSeaLevelHp = false; //Since we are about to give this to user, mark this data as stale
- return (meanSeaLevelHp);
-}
-
-// getGeoidSeparation is currently redundant. The geoid separation seems to only be provided in NMEA GGA and GNS messages.
-int32_t getGeoidSeparation(uint16_t maxWait /* = 250*/)
-{
- if (highResModuleQueried.geoidSeparation == false)
- getHPPOSLLH(maxWait);
- highResModuleQueried.geoidSeparation = false; //Since we are about to give this to user, mark this data as stale
- return (geoidSeparation);
-}
-
-uint32_t getHorizontalAccuracy(uint16_t maxWait /* = 250*/)
-{
- if (highResModuleQueried.horizontalAccuracy == false)
- getHPPOSLLH(maxWait);
- highResModuleQueried.horizontalAccuracy = false; //Since we are about to give this to user, mark this data as stale
- return (horizontalAccuracy);
-}
-
-uint32_t getVerticalAccuracy(uint16_t maxWait /* = 250*/)
-{
- if (highResModuleQueried.verticalAccuracy == false)
- getHPPOSLLH(maxWait);
- highResModuleQueried.verticalAccuracy = false; //Since we are about to give this to user, mark this data as stale
- return (verticalAccuracy);
-}
-
-bool getHPPOSLLH(uint16_t maxWait)
-{
- //The GPS is not automatically reporting navigation position so we have to poll explicitly
- packetCfg.cls = UBX_CLASS_NAV;
- packetCfg.id = UBX_NAV_HPPOSLLH;
- packetCfg.len = 0;
-
- return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_RECEIVED); // We are only expecting data (no ACK)
-}
-
-//Get the current 3D high precision positional accuracy - a fun thing to watch
-//Returns a long representing the 3D accuracy in millimeters
-uint32_t getPositionAccuracy(uint16_t maxWait)
-{
- packetCfg.cls = UBX_CLASS_NAV;
- packetCfg.id = UBX_NAV_HPPOSECEF;
- packetCfg.len = 0;
- packetCfg.startingSpot = 0;
-
- if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are only expecting data (no ACK)
- return (0); //If command send fails then bail
-
- uint32_t tempAccuracy = extractLong(24); //We got a response, now extract a long beginning at a given position
-
- if ((tempAccuracy % 10) >= 5)
- tempAccuracy += 5; //Round fraction of mm up to next mm if .5 or above
- tempAccuracy /= 10; //Convert 0.1mm units to mm
-
- return (tempAccuracy);
-}
-
-//Get the current date validity
-bool getDateValid(uint16_t maxWait)
-{
- if (moduleQueried.gpsDateValid == false)
- getPVT(maxWait);
- moduleQueried.gpsDateValid = false; //Since we are about to give this to user, mark this data as stale
- return (gpsDateValid);
-}
-
-//Get the current time validity
-bool getTimeValid(uint16_t maxWait)
-{
- if (moduleQueried.gpsTimeValid == false)
- getPVT(maxWait);
- moduleQueried.gpsTimeValid = false; //Since we are about to give this to user, mark this data as stale
- return (gpsTimeValid);
-}
-
-
-//Get the current latitude in degrees
-//Returns a long representing the number of degrees *10^-7
-int32_t getLatitude(uint16_t maxWait)
-{
- if (moduleQueried.latitude == false)
- getPVT(maxWait);
- moduleQueried.latitude = false; //Since we are about to give this to user, mark this data as stale
- moduleQueried.all = false;
-
- return (latitude);
-}
-
-//Get the current longitude in degrees
-//Returns a long representing the number of degrees *10^-7
-int32_t getLongitude(uint16_t maxWait)
-{
- if (moduleQueried.longitude == false)
- getPVT(maxWait);
- moduleQueried.longitude = false; //Since we are about to give this to user, mark this data as stale
- moduleQueried.all = false;
-
- return (longitude);
-}
-
-//Get the current altitude in mm according to ellipsoid model
-int32_t getAltitude(uint16_t maxWait)
-{
- if (moduleQueried.altitude == false)
- getPVT(maxWait);
- moduleQueried.altitude = false; //Since we are about to give this to user, mark this data as stale
- moduleQueried.all = false;
-
- return (altitude);
-}
-
-//Get the current altitude in mm according to mean sea level
-//Ellipsoid model: https://www.esri.com/news/arcuser/0703/geoid1of3.html
-//Difference between Ellipsoid Model and Mean Sea Level: https://eos-gnss.com/elevation-for-beginners/
-int32_t getAltitudeMSL(uint16_t maxWait)
-{
- if (moduleQueried.altitudeMSL == false)
- getPVT(maxWait);
- moduleQueried.altitudeMSL = false; //Since we are about to give this to user, mark this data as stale
- moduleQueried.all = false;
-
- return (altitudeMSL);
-}
-
-//Get the number of satellites used in fix
-uint8_t getSIV(uint16_t maxWait)
-{
- if (moduleQueried.SIV == false)
- getPVT(maxWait);
- moduleQueried.SIV = false; //Since we are about to give this to user, mark this data as stale
- moduleQueried.all = false;
-
- return (SIV);
-}
-
-//Get the current fix type
-//0=no fix, 1=dead reckoning, 2=2D, 3=3D, 4=GNSS, 5=Time fix
-uint8_t getFixType(uint16_t maxWait)
-{
- if (moduleQueried.fixType == false)
- {
- getPVT(maxWait);
- }
- moduleQueried.fixType = false; //Since we are about to give this to user, mark this data as stale
- moduleQueried.all = false;
-
- return (fixType);
-}
-
-
-//Get the current gnssFixOK status
-//0= not valid fix, 1 = not valid fix
-uint8_t getgnssFixOK(uint16_t maxWait)
-{
- if (moduleQueried.gnssFixOK == false)
- {
- getPVT(maxWait);
- }
- moduleQueried.gnssFixOK = false; //Since we are about to give this to user, mark this data as stale
- moduleQueried.all = false;
-
- return (gnssFixOK);
-}
-
-//Get the carrier phase range solution status
-//Useful when querying module to see if it has high-precision RTK fix
-//0=No solution, 1=Float solution, 2=Fixed solution
-uint8_t getCarrierSolutionType(uint16_t maxWait)
-{
- if (moduleQueried.carrierSolution == false)
- getPVT(maxWait);
- moduleQueried.carrierSolution = false; //Since we are about to give this to user, mark this data as stale
- moduleQueried.all = false;
-
- return (carrierSolution);
-}
-
-//Get the ground speed in mm/s
-int32_t getGroundSpeed(uint16_t maxWait)
-{
- if (moduleQueried.groundSpeed == false)
- getPVT(maxWait);
- moduleQueried.groundSpeed = false; //Since we are about to give this to user, mark this data as stale
- moduleQueried.all = false;
-
- return (groundSpeed);
-}
-
-//Get the heading of motion (as opposed to heading of car) in degrees * 10^-5
-int32_t getHeading(uint16_t maxWait)
-{
- if (moduleQueried.headingOfMotion == false)
- getPVT(maxWait);
- moduleQueried.headingOfMotion = false; //Since we are about to give this to user, mark this data as stale
- moduleQueried.all = false;
-
- return (headingOfMotion);
-}
-
-//Get the positional dillution of precision * 10^-2
-uint16_t getPDOP(uint16_t maxWait)
-{
- if (moduleQueried.pDOP == false)
- getPVT(maxWait);
- moduleQueried.pDOP = false; //Since we are about to give this to user, mark this data as stale
- moduleQueried.all = false;
-
- return (pDOP);
-}
-
-//Get the current protocol version of the Ublox module we're communicating with
-//This is helpful when deciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH)
-uint8_t getProtocolVersionHigh(uint16_t maxWait)
-{
- if (moduleQueried.versionNumber == false)
- getProtocolVersion(maxWait);
- return (versionHigh);
-}
-
-//Get the current protocol version of the Ublox module we're communicating with
-//This is helpful when deciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH)
-uint8_t getProtocolVersionLow(uint16_t maxWait)
-{
- if (moduleQueried.versionNumber == false)
- getProtocolVersion(maxWait);
- return (versionLow);
-}
-
-//Get the current protocol version of the Ublox module we're communicating with
-//This is helpful when deciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH)
-bool getProtocolVersion(uint16_t maxWait)
-{
- //Send packet with only CLS and ID, length of zero. This will cause the module to respond with the contents of that CLS/ID.
- packetCfg.cls = UBX_CLASS_MON;
- packetCfg.id = UBX_MON_VER;
-
- packetCfg.len = 0;
- packetCfg.startingSpot = 40; //Start at first "extended software information" string
-
- if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are only expecting data (no ACK)
- return (false); //If command send fails then bail
-
- //Payload should now contain ~220 characters (depends on module type)
-
- // if (_printDebug == true)
- // {
- // printf("MON VER Payload:");
- // for (int location = 0; location < packetCfg.len; location++)
- // {
- // if (location % 30 == 0)
- // printf();
- // write(payloadCfg[location]);
- // }
- // printf();
- // }
-
- //We will step through the payload looking at each extension field of 30 bytes
- for (uint8_t extensionNumber = 0; extensionNumber < 10; extensionNumber++)
- {
- //Now we need to find "PROTVER=18.00" in the incoming byte stream
- if (payloadCfg[(30 * extensionNumber) + 0] == 'P' && payloadCfg[(30 * extensionNumber) + 6] == 'R')
- {
- versionHigh = (payloadCfg[(30 * extensionNumber) + 8] - '0') * 10 + (payloadCfg[(30 * extensionNumber) + 9] - '0'); //Convert '18' to 18
- versionLow = (payloadCfg[(30 * extensionNumber) + 11] - '0') * 10 + (payloadCfg[(30 * extensionNumber) + 12] - '0'); //Convert '00' to 00
- moduleQueried.versionNumber = true; //Mark this data as new
-
- if (_printDebug == true)
- {
- printf("Protocol version: ");
- printf("%d",versionHigh);
- printf(".");
- printf("%d\r\n",versionLow);
- }
- return (true); //Success!
- }
- }
-
- return (false); //We failed
-}
-
-//Mark all the PVT data as read/stale. This is handy to get data alignment after CRC failure
-void flushPVT()
-{
- //Mark all datums as stale (read before)
- moduleQueried.gpsiTOW = false;
- moduleQueried.gpsYear = false;
- moduleQueried.gpsMonth = false;
- moduleQueried.gpsDay = false;
- moduleQueried.gpsHour = false;
- moduleQueried.gpsMinute = false;
- moduleQueried.gpsSecond = false;
- moduleQueried.gpsDateValid = false;
- moduleQueried.gpsTimeValid = false;
- moduleQueried.gpsNanosecond = false;
-
- moduleQueried.all = false;
- moduleQueried.longitude = false;
- moduleQueried.latitude = false;
- moduleQueried.altitude = false;
- moduleQueried.altitudeMSL = false;
- moduleQueried.SIV = false;
- moduleQueried.fixType = false;
- moduleQueried.gnssFixOK = false;
- moduleQueried.carrierSolution = false;
- moduleQueried.groundSpeed = false;
- moduleQueried.headingOfMotion = false;
- moduleQueried.pDOP = false;
-}
-
-
-#endif //#if 0
diff --git a/src/peripherals/SparkFun_Ublox_Arduino_Library.h b/src/peripherals/SparkFun_Ublox_Arduino_Library.h
deleted file mode 100644
index f354ea907..000000000
--- a/src/peripherals/SparkFun_Ublox_Arduino_Library.h
+++ /dev/null
@@ -1,671 +0,0 @@
-/*
- This is a library written for the Ublox ZED-F9P and NEO-M8P-2
- SparkFun sells these at its website: www.sparkfun.com
- Do you like this library? Help support SparkFun. Buy a board!
- https://www.sparkfun.com/products/15136
- https://www.sparkfun.com/products/15005
- https://www.sparkfun.com/products/15733
- https://www.sparkfun.com/products/15193
- https://www.sparkfun.com/products/15210
-
- Written by Nathan Seidle @ SparkFun Electronics, September 6th, 2018
-
- This library handles configuring and handling the responses
- from a Ublox GPS module. Works with most modules from Ublox including
- the Zed-F9P, NEO-M8P-2, NEO-M9N, ZOE-M8Q, SAM-M8Q, and many others.
-
- https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library
-
- Development environment specifics:
- Arduino IDE 1.8.5
-
- SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT).
- The MIT License (MIT)
- Copyright (c) 2016 SparkFun Electronics
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
- associated documentation files (the "Software"), to deal in the Software without restriction,
- including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom the Software is furnished to
- do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all copies or substantial
- portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
- NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-
-#ifndef SPARKFUN_UBLOX_ARDUINO_LIBRARY_H
-#define SPARKFUN_UBLOX_ARDUINO_LIBRARY_H
-
-#include
-#include
-#include
-
-//#include
-
-//Platform specific configurations
-
-//Define the size of the I2C buffer based on the platform the user has
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
-
-//I2C_BUFFER_LENGTH is defined in Wire.H
-#define I2C_BUFFER_LENGTH BUFFER_LENGTH
-
-#elif defined(__SAMD21G18A__)
-
-//SAMD21 uses RingBuffer.h
-#define I2C_BUFFER_LENGTH SERIAL_BUFFER_SIZE
-
-//#elif __MK20DX256__
-//Teensy
-
-#endif
-
-#ifndef I2C_BUFFER_LENGTH
-
-//The catch-all default is 32
-#define I2C_BUFFER_LENGTH 32
-//#define I2C_BUFFER_LENGTH 16 //For testing on Artemis
-
-#endif
-
-// Define Serial for SparkFun SAMD based boards.
-// Boards like the RedBoard Turbo use SerialUSB (not Serial).
-// But other boards like the SAMD51 Thing Plus use Serial (not SerialUSB).
-// The next nine lines let the code compile cleanly on as many SAMD boards as possible.
-#if defined(ARDUINO_ARCH_SAMD) // Is this a SAMD board?
- #if defined(USB_VID) // Is the USB Vendor ID defined?
- #if (USB_VID == 0x1B4F) // Is this a SparkFun board?
- #if !defined(ARDUINO_SAMD51_THING_PLUS) // If it is not a SAMD51 Thing Plus
- #define Serial SerialUSB // Define Serial as SerialUSB
- #endif
- #endif
- #endif
-#endif
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-//Define a digital pin to aid checksum failure capture and analysis
-//Leave set to -1 if not needed
-static const int checksumFailurePin = -1;
-
-// Global Status Returns
-typedef enum
-{
- SFE_UBLOX_STATUS_SUCCESS,
- SFE_UBLOX_STATUS_FAIL,
- SFE_UBLOX_STATUS_CRC_FAIL,
- SFE_UBLOX_STATUS_TIMEOUT,
- SFE_UBLOX_STATUS_COMMAND_NACK, // Indicates that the command was unrecognised, invalid or that the module is too busy to respond
- SFE_UBLOX_STATUS_OUT_OF_RANGE,
- SFE_UBLOX_STATUS_INVALID_ARG,
- SFE_UBLOX_STATUS_INVALID_OPERATION,
- SFE_UBLOX_STATUS_MEM_ERR,
- SFE_UBLOX_STATUS_HW_ERR,
- SFE_UBLOX_STATUS_DATA_SENT, // This indicates that a 'set' was successful
- SFE_UBLOX_STATUS_DATA_RECEIVED, // This indicates that a 'get' (poll) was successful
- SFE_UBLOX_STATUS_I2C_COMM_FAILURE,
- SFE_UBLOX_STATUS_DATA_OVERWRITTEN // This is an error - the data was valid but has been or _is being_ overwritten by another packet
-} sfe_ublox_status_e;
-
-// ubxPacket validity
-typedef enum
-{
- SFE_UBLOX_PACKET_VALIDITY_NOT_VALID,
- SFE_UBLOX_PACKET_VALIDITY_VALID,
- SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED,
- SFE_UBLOX_PACKET_NOTACKNOWLEDGED // This indicates that we received a NACK
-} sfe_ublox_packet_validity_e;
-
-// Identify which packet buffer is in use:
-// packetCfg (or a custom packet), packetAck or packetBuf
-typedef enum
-{
- SFE_UBLOX_PACKET_PACKETCFG,
- SFE_UBLOX_PACKET_PACKETACK,
- SFE_UBLOX_PACKET_PACKETBUF
-} sfe_ublox_packet_buffer_e;
-
-//Registers
-static const uint8_t UBX_SYNCH_1 = 0xB5;
-static const uint8_t UBX_SYNCH_2 = 0x62;
-
-//The following are UBX Class IDs. Descriptions taken from ZED-F9P Interface Description Document page 32, NEO-M8P Interface Description page 145
-#define UBX_CLASS_NAV 0x01 //Navigation Results Messages: Position, Speed, Time, Acceleration, Heading, DOP, SVs used
-static const uint8_t UBX_CLASS_RXM = 0x02; //Receiver Manager Messages: Satellite Status, RTC Status
-static const uint8_t UBX_CLASS_INF = 0x04; //Information Messages: Printf-Style Messages, with IDs such as Error, Warning, Notice
-static const uint8_t UBX_CLASS_ACK = 0x05; //Ack/Nak Messages: Acknowledge or Reject messages to UBX-CFG input messages
-static const uint8_t UBX_CLASS_CFG = 0x06; //Configuration Input Messages: Configure the receiver.
-static const uint8_t UBX_CLASS_UPD = 0x09; //Firmware Update Messages: Memory/Flash erase/write, Reboot, Flash identification, etc.
-static const uint8_t UBX_CLASS_MON = 0x0A; //Monitoring Messages: Communication Status, CPU Load, Stack Usage, Task Status
-static const uint8_t UBX_CLASS_AID = 0x0B; //(NEO-M8P ONLY!!!) AssistNow Aiding Messages: Ephemeris, Almanac, other A-GPS data input
-static const uint8_t UBX_CLASS_TIM = 0x0D; //Timing Messages: Time Pulse Output, Time Mark Results
-static const uint8_t UBX_CLASS_ESF = 0x10; //(NEO-M8P ONLY!!!) External Sensor Fusion Messages: External Sensor Measurements and Status Information
-static const uint8_t UBX_CLASS_MGA = 0x13; //Multiple GNSS Assistance Messages: Assistance data for various GNSS
-static const uint8_t UBX_CLASS_LOG = 0x21; //Logging Messages: Log creation, deletion, info and retrieval
-static const uint8_t UBX_CLASS_SEC = 0x27; //Security Feature Messages
-static const uint8_t UBX_CLASS_HNR = 0x28; //(NEO-M8P ONLY!!!) High Rate Navigation Results Messages: High rate time, position speed, heading
-static const uint8_t UBX_CLASS_NMEA = 0xF0; //NMEA Strings: standard NMEA strings
-
-//The following are used for configuration. Descriptions are from the ZED-F9P Interface Description pg 33-34 and NEO-M9N Interface Description pg 47-48
-static const uint8_t UBX_CFG_ANT = 0x13; //Antenna Control Settings. Used to configure the antenna control settings
-static const uint8_t UBX_CFG_BATCH = 0x93; //Get/set data batching configuration.
-static const uint8_t UBX_CFG_CFG = 0x09; //Clear, Save, and Load Configurations. Used to save current configuration
-static const uint8_t UBX_CFG_DAT = 0x06; //Set User-defined Datum or The currently defined Datum
-static const uint8_t UBX_CFG_DGNSS = 0x70; //DGNSS configuration
-static const uint8_t UBX_CFG_GEOFENCE = 0x69; //Geofencing configuration. Used to configure a geofence
-static const uint8_t UBX_CFG_GNSS = 0x3E; //GNSS system configuration
-static const uint8_t UBX_CFG_INF = 0x02; //Depending on packet length, either: poll configuration for one protocol, or information message configuration
-static const uint8_t UBX_CFG_ITFM = 0x39; //Jamming/Interference Monitor configuration
-static const uint8_t UBX_CFG_LOGFILTER = 0x47; //Data Logger Configuration
-static const uint8_t UBX_CFG_MSG = 0x01; //Poll a message configuration, or Set Message Rate(s), or Set Message Rate
-static const uint8_t UBX_CFG_NAV5 = 0x24; //Navigation Engine Settings. Used to configure the navigation engine including the dynamic model.
-static const uint8_t UBX_CFG_NAVX5 = 0x23; //Navigation Engine Expert Settings
-static const uint8_t UBX_CFG_NMEA = 0x17; //Extended NMEA protocol configuration V1
-static const uint8_t UBX_CFG_ODO = 0x1E; //Odometer, Low-speed COG Engine Settings
-static const uint8_t UBX_CFG_PM2 = 0x3B; //Extended power management configuration
-static const uint8_t UBX_CFG_PMS = 0x86; //Power mode setup
-static const uint8_t UBX_CFG_PRT = 0x00; //Used to configure port specifics. Polls the configuration for one I/O Port, or Port configuration for UART ports, or Port configuration for USB port, or Port configuration for SPI port, or Port configuration for DDC port
-static const uint8_t UBX_CFG_PWR = 0x57; //Put receiver in a defined power state
-static const uint8_t UBX_CFG_RATE = 0x08; //Navigation/Measurement Rate Settings. Used to set port baud rates.
-static const uint8_t UBX_CFG_RINV = 0x34; //Contents of Remote Inventory
-static const uint8_t UBX_CFG_RST = 0x04; //Reset Receiver / Clear Backup Data Structures. Used to reset device.
-static const uint8_t UBX_CFG_RXM = 0x11; //RXM configuration
-static const uint8_t UBX_CFG_SBAS = 0x16; //SBAS configuration
-static const uint8_t UBX_CFG_TMODE3 = 0x71; //Time Mode Settings 3. Used to enable Survey In Mode
-static const uint8_t UBX_CFG_TP5 = 0x31; //Time Pulse Parameters
-static const uint8_t UBX_CFG_USB = 0x1B; //USB Configuration
-static const uint8_t UBX_CFG_VALDEL = 0x8C; //Used for config of higher version Ublox modules (ie protocol v27 and above). Deletes values corresponding to provided keys/ provided keys with a transaction
-static const uint8_t UBX_CFG_VALGET = 0x8B; //Used for config of higher version Ublox modules (ie protocol v27 and above). Configuration Items
-static const uint8_t UBX_CFG_VALSET = 0x8A; //Used for config of higher version Ublox modules (ie protocol v27 and above). Sets values corresponding to provided key-value pairs/ provided key-value pairs within a transaction.
-
-//The following are used to enable NMEA messages. Descriptions come from the NMEA messages overview in the ZED-F9P Interface Description
-static const uint8_t UBX_NMEA_MSB = 0xF0; //All NMEA enable commands have 0xF0 as MSB
-static const uint8_t UBX_NMEA_DTM = 0x0A; //GxDTM (datum reference)
-static const uint8_t UBX_NMEA_GAQ = 0x45; //GxGAQ (poll a standard message (if the current talker ID is GA))
-static const uint8_t UBX_NMEA_GBQ = 0x44; //GxGBQ (poll a standard message (if the current Talker ID is GB))
-static const uint8_t UBX_NMEA_GBS = 0x09; //GxGBS (GNSS satellite fault detection)
-static const uint8_t UBX_NMEA_GGA = 0x00; //GxGGA (Global positioning system fix data)
-static const uint8_t UBX_NMEA_GLL = 0x01; //GxGLL (latitude and long, whith time of position fix and status)
-static const uint8_t UBX_NMEA_GLQ = 0x43; //GxGLQ (poll a standard message (if the current Talker ID is GL))
-static const uint8_t UBX_NMEA_GNQ = 0x42; //GxGNQ (poll a standard message (if the current Talker ID is GN))
-static const uint8_t UBX_NMEA_GNS = 0x0D; //GxGNS (GNSS fix data)
-static const uint8_t UBX_NMEA_GPQ = 0x040; //GxGPQ (poll a standard message (if the current Talker ID is GP))
-static const uint8_t UBX_NMEA_GRS = 0x06; //GxGRS (GNSS range residuals)
-static const uint8_t UBX_NMEA_GSA = 0x02; //GxGSA (GNSS DOP and Active satellites)
-static const uint8_t UBX_NMEA_GST = 0x07; //GxGST (GNSS Pseudo Range Error Statistics)
-static const uint8_t UBX_NMEA_GSV = 0x03; //GxGSV (GNSS satellites in view)
-static const uint8_t UBX_NMEA_RMC = 0x04; //GxRMC (Recommended minimum data)
-static const uint8_t UBX_NMEA_TXT = 0x41; //GxTXT (text transmission)
-static const uint8_t UBX_NMEA_VLW = 0x0F; //GxVLW (dual ground/water distance)
-static const uint8_t UBX_NMEA_VTG = 0x05; //GxVTG (course over ground and Ground speed)
-static const uint8_t UBX_NMEA_ZDA = 0x08; //GxZDA (Time and Date)
-
-//The following are used to configure the NMEA protocol main talker ID and GSV talker ID
-static const uint8_t UBX_NMEA_MAINTALKERID_NOTOVERRIDDEN = 0x00; //main talker ID is system dependent
-static const uint8_t UBX_NMEA_MAINTALKERID_GP = 0x01; //main talker ID is GPS
-static const uint8_t UBX_NMEA_MAINTALKERID_GL = 0x02; //main talker ID is GLONASS
-static const uint8_t UBX_NMEA_MAINTALKERID_GN = 0x03; //main talker ID is combined receiver
-static const uint8_t UBX_NMEA_MAINTALKERID_GA = 0x04; //main talker ID is Galileo
-static const uint8_t UBX_NMEA_MAINTALKERID_GB = 0x05; //main talker ID is BeiDou
-static const uint8_t UBX_NMEA_GSVTALKERID_GNSS = 0x00; //GNSS specific Talker ID (as defined by NMEA)
-static const uint8_t UBX_NMEA_GSVTALKERID_MAIN = 0x01; //use the main Talker ID
-
-//The following are used to configure INF UBX messages (information messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 34)
-static const uint8_t UBX_INF_CLASS = 0x04; //All INF messages have 0x04 as the class
-static const uint8_t UBX_INF_DEBUG = 0x04; //ASCII output with debug contents
-static const uint8_t UBX_INF_ERROR = 0x00; //ASCII output with error contents
-static const uint8_t UBX_INF_NOTICE = 0x02; //ASCII output with informational contents
-static const uint8_t UBX_INF_TEST = 0x03; //ASCII output with test contents
-static const uint8_t UBX_INF_WARNING = 0x01; //ASCII output with warning contents
-
-//The following are used to configure LOG UBX messages (loggings messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 34)
-static const uint8_t UBX_LOG_CREATE = 0x07; //Create Log File
-static const uint8_t UBX_LOG_ERASE = 0x03; //Erase Logged Data
-static const uint8_t UBX_LOG_FINDTIME = 0x0E; //Find index of a log entry based on a given time, or response to FINDTIME requested
-static const uint8_t UBX_LOG_INFO = 0x08; //Poll for log information, or Log information
-static const uint8_t UBX_LOG_RETRIEVEPOSEXTRA = 0x0F; //Odometer log entry
-static const uint8_t UBX_LOG_RETRIEVEPOS = 0x0B; //Position fix log entry
-static const uint8_t UBX_LOG_RETRIEVESTRING = 0x0D; //Byte string log entry
-static const uint8_t UBX_LOG_RETRIEVE = 0x09; //Request log data
-static const uint8_t UBX_LOG_STRING = 0x04; //Store arbitrary string on on-board flash
-
-//The following are used to configure MGA UBX messages (Multiple GNSS Assistance Messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 34)
-static const uint8_t UBX_MGA_ACK_DATA0 = 0x60; //Multiple GNSS Acknowledge message
-static const uint8_t UBX_MGA_BDS_EPH = 0x03; //BDS Ephemeris Assistance
-static const uint8_t UBX_MGA_BDS_ALM = 0x03; //BDS Almanac Assistance
-static const uint8_t UBX_MGA_BDS_HEALTH = 0x03; //BDS Health Assistance
-static const uint8_t UBX_MGA_BDS_UTC = 0x03; //BDS UTC Assistance
-static const uint8_t UBX_MGA_BDS_IONO = 0x03; //BDS Ionospheric Assistance
-static const uint8_t UBX_MGA_DBD = 0x80; //Either: Poll the Navigation Database, or Navigation Database Dump Entry
-static const uint8_t UBX_MGA_GAL_EPH = 0x02; //Galileo Ephemeris Assistance
-static const uint8_t UBX_MGA_GAL_ALM = 0x02; //Galileo Almanac Assitance
-static const uint8_t UBX_MGA_GAL_TIMOFFSET = 0x02; //Galileo GPS time offset assistance
-static const uint8_t UBX_MGA_GAL_UTC = 0x02; //Galileo UTC Assistance
-static const uint8_t UBX_MGA_GLO_EPH = 0x06; //GLONASS Ephemeris Assistance
-static const uint8_t UBX_MGA_GLO_ALM = 0x06; //GLONASS Almanac Assistance
-static const uint8_t UBX_MGA_GLO_TIMEOFFSET = 0x06; //GLONASS Auxiliary Time Offset Assistance
-static const uint8_t UBX_MGA_GPS_EPH = 0x00; //GPS Ephemeris Assistance
-static const uint8_t UBX_MGA_GPS_ALM = 0x00; //GPS Almanac Assistance
-static const uint8_t UBX_MGA_GPS_HEALTH = 0x00; //GPS Health Assistance
-static const uint8_t UBX_MGA_GPS_UTC = 0x00; //GPS UTC Assistance
-static const uint8_t UBX_MGA_GPS_IONO = 0x00; //GPS Ionosphere Assistance
-static const uint8_t UBX_MGA_INI_POS_XYZ = 0x40; //Initial Position Assistance
-static const uint8_t UBX_MGA_INI_POS_LLH = 0x40; //Initial Position Assitance
-static const uint8_t UBX_MGA_INI_TIME_UTC = 0x40; //Initial Time Assistance
-static const uint8_t UBX_MGA_INI_TIME_GNSS = 0x40; //Initial Time Assistance
-static const uint8_t UBX_MGA_INI_CLKD = 0x40; //Initial Clock Drift Assitance
-static const uint8_t UBX_MGA_INI_FREQ = 0x40; //Initial Frequency Assistance
-static const uint8_t UBX_MGA_INI_EOP = 0x40; //Earth Orientation Parameters Assistance
-static const uint8_t UBX_MGA_QZSS_EPH = 0x05; //QZSS Ephemeris Assistance
-static const uint8_t UBX_MGA_QZSS_ALM = 0x05; //QZSS Almanac Assistance
-static const uint8_t UBX_MGA_QZAA_HEALTH = 0x05; //QZSS Health Assistance
-
-//The following are used to configure the MON UBX messages (monitoring messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 35)
-static const uint8_t UBX_MON_COMMS = 0x36; //Comm port information
-static const uint8_t UBX_MON_GNSS = 0x28; //Information message major GNSS selection
-static const uint8_t UBX_MON_HW2 = 0x0B; //Extended Hardware Status
-static const uint8_t UBX_MON_HW3 = 0x37; //HW I/O pin information
-static const uint8_t UBX_MON_HW = 0x09; //Hardware Status
-static const uint8_t UBX_MON_IO = 0x02; //I/O Subsystem Status
-static const uint8_t UBX_MON_MSGPP = 0x06; //Message Parse and Process Status
-static const uint8_t UBX_MON_PATCH = 0x27; //Output information about installed patches
-static const uint8_t UBX_MON_RF = 0x38; //RF information
-static const uint8_t UBX_MON_RXBUF = 0x07; //Receiver Buffer Status
-static const uint8_t UBX_MON_RXR = 0x21; //Receiver Status Information
-static const uint8_t UBX_MON_TXBUF = 0x08; //Transmitter Buffer Status. Used for query tx buffer size/state.
-static const uint8_t UBX_MON_VER = 0x04; //Receiver/Software Version. Used for obtaining Protocol Version.
-
-//The following are used to configure the NAV UBX messages (navigation results messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 35-36)
-static const uint8_t UBX_NAV_ATT = 0x05; //Vehicle "Attitude" Solution
-static const uint8_t UBX_NAV_CLOCK = 0x22; //Clock Solution
-static const uint8_t UBX_NAV_DOP = 0x04; //Dilution of precision
-static const uint8_t UBX_NAV_EOE = 0x61; //End of Epoch
-static const uint8_t UBX_NAV_GEOFENCE = 0x39; //Geofencing status. Used to poll the geofence status
-static const uint8_t UBX_NAV_HPPOSECEF = 0x13; //High Precision Position Solution in ECEF. Used to find our positional accuracy (high precision).
-static const uint8_t UBX_NAV_HPPOSLLH = 0x14; //High Precision Geodetic Position Solution. Used for obtaining lat/long/alt in high precision
-static const uint8_t UBX_NAV_ODO = 0x09; //Odometer Solution
-static const uint8_t UBX_NAV_ORB = 0x34; //GNSS Orbit Database Info
-static const uint8_t UBX_NAV_POSECEF = 0x01; //Position Solution in ECEF
-static const uint8_t UBX_NAV_POSLLH = 0x02; //Geodetic Position Solution
-static const uint8_t UBX_NAV_PVT = 0x07; //All the things! Position, velocity, time, PDOP, height, h/v accuracies, number of satellites. Navigation Position Velocity Time Solution.
-static const uint8_t UBX_NAV_RELPOSNED = 0x3C; //Relative Positioning Information in NED frame
-static const uint8_t UBX_NAV_RESETODO = 0x10; //Reset odometer
-static const uint8_t UBX_NAV_SAT = 0x35; //Satellite Information
-static const uint8_t UBX_NAV_SIG = 0x43; //Signal Information
-static const uint8_t UBX_NAV_STATUS = 0x03; //Receiver Navigation Status
-static const uint8_t UBX_NAV_SVIN = 0x3B; //Survey-in data. Used for checking Survey In status
-static const uint8_t UBX_NAV_TIMEBDS = 0x24; //BDS Time Solution
-static const uint8_t UBX_NAV_TIMEGAL = 0x25; //Galileo Time Solution
-static const uint8_t UBX_NAV_TIMEGLO = 0x23; //GLO Time Solution
-static const uint8_t UBX_NAV_TIMEGPS = 0x20; //GPS Time Solution
-static const uint8_t UBX_NAV_TIMELS = 0x26; //Leap second event information
-static const uint8_t UBX_NAV_TIMEUTC = 0x21; //UTC Time Solution
-static const uint8_t UBX_NAV_VELECEF = 0x11; //Velocity Solution in ECEF
-static const uint8_t UBX_NAV_VELNED = 0x12; //Velocity Solution in NED
-
-//The following are used to configure the RXM UBX messages (receiver manager messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36)
-static const uint8_t UBX_RXM_MEASX = 0x14; //Satellite Measurements for RRLP
-static const uint8_t UBX_RXM_PMREQ = 0x41; //Requests a Power Management task (two differenent packet sizes)
-static const uint8_t UBX_RXM_RAWX = 0x15; //Multi-GNSS Raw Measurement Data
-static const uint8_t UBX_RXM_RLM = 0x59; //Galileo SAR Short-RLM report (two different packet sizes)
-static const uint8_t UBX_RXM_RTCM = 0x32; //RTCM input status
-static const uint8_t UBX_RXM_SFRBX = 0x13; //Boradcast Navigation Data Subframe
-
-//The following are used to configure the SEC UBX messages (security feature messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36)
-static const uint8_t UBX_SEC_UNIQID = 0x03; //Unique chip ID
-
-//The following are used to configure the TIM UBX messages (timing messages). Descriptions from UBX messages overview (ZED_F9P Interface Description Document page 36)
-static const uint8_t UBX_TIM_TM2 = 0x03; //Time mark data
-static const uint8_t UBX_TIM_TP = 0x01; //Time Pulse Timedata
-static const uint8_t UBX_TIM_VRFY = 0x06; //Sourced Time Verification
-
-//The following are used to configure the UPD UBX messages (firmware update messages). Descriptions from UBX messages overview (ZED-F9P Interface Description Document page 36)
-static const uint8_t UBX_UPD_SOS = 0x14; //Poll Backup Fil Restore Status, Create Backup File in Flash, Clear Backup File in Flash, Backup File Creation Acknowledge, System Restored from Backup
-
-//The following are used to enable RTCM messages
-static const uint8_t UBX_RTCM_MSB = 0xF5; //All RTCM enable commands have 0xF5 as MSB
-static const uint8_t UBX_RTCM_1005 = 0x05; //Stationary RTK reference ARP
-static const uint8_t UBX_RTCM_1074 = 0x4A; //GPS MSM4
-static const uint8_t UBX_RTCM_1077 = 0x4D; //GPS MSM7
-static const uint8_t UBX_RTCM_1084 = 0x54; //GLONASS MSM4
-static const uint8_t UBX_RTCM_1087 = 0x57; //GLONASS MSM7
-static const uint8_t UBX_RTCM_1094 = 0x5E; //Galileo MSM4
-static const uint8_t UBX_RTCM_1097 = 0x61; //Galileo MSM7
-static const uint8_t UBX_RTCM_1124 = 0x7C; //BeiDou MSM4
-static const uint8_t UBX_RTCM_1127 = 0x7F; //BeiDou MSM7
-static const uint8_t UBX_RTCM_1230 = 0xE6; //GLONASS code-phase biases, set to once every 10 seconds
-static const uint8_t UBX_RTCM_4072_0 = 0xFE; //Reference station PVT (ublox proprietary RTCM message)
-static const uint8_t UBX_RTCM_4072_1 = 0xFD; //Additional reference station information (ublox proprietary RTCM message)
-
-static const uint8_t UBX_ACK_NACK = 0x00;
-static const uint8_t UBX_ACK_ACK = 0x01;
-static const uint8_t UBX_ACK_NONE = 0x02; //Not a real value
-
-// The following constants are used to get External Sensor Measurements and Status
-// Information.
-static const uint8_t UBX_ESF_MEAS = 0x02;
-static const uint8_t UBX_ESF_RAW = 0x03;
-static const uint8_t UBX_ESF_STATUS = 0x10;
-static const uint8_t UBX_ESF_INS = 0x15; //36 bytes
-
-static const uint8_t SVIN_MODE_DISABLE = 0x00;
-static const uint8_t SVIN_MODE_ENABLE = 0x01;
-
-//The following consts are used to configure the various ports and streams for those ports. See -CFG-PRT.
-static const uint8_t COM_PORT_I2C = 0;
-static const uint8_t COM_PORT_UART1 = 1;
-static const uint8_t COM_PORT_UART2 = 2;
-static const uint8_t COM_PORT_USB = 3;
-static const uint8_t COM_PORT_SPI = 4;
-
-static const uint8_t COM_TYPE_UBX = (1 << 0);
-static const uint8_t COM_TYPE_NMEA = (1 << 1);
-static const uint8_t COM_TYPE_RTCM3 = (1 << 5);
-
-//The following consts are used to generate KEY values for the advanced protocol functions of VELGET/SET/DEL
-static const uint8_t VAL_SIZE_1 = 0x01; //One bit
-static const uint8_t VAL_SIZE_8 = 0x02; //One byte
-static const uint8_t VAL_SIZE_16 = 0x03; //Two bytes
-static const uint8_t VAL_SIZE_32 = 0x04; //Four bytes
-static const uint8_t VAL_SIZE_64 = 0x05; //Eight bytes
-
-//These are the Bitfield layers definitions for the UBX-CFG-VALSET message (not to be confused with Bitfield deviceMask in UBX-CFG-CFG)
-static const uint8_t VAL_LAYER_RAM = (1 << 0);
-static const uint8_t VAL_LAYER_BBR = (1 << 1);
-static const uint8_t VAL_LAYER_FLASH = (1 << 2);
-
-//Below are various Groups, IDs, and sizes for various settings
-//These can be used to call getVal/setVal/delVal
-static const uint8_t VAL_GROUP_I2COUTPROT = 0x72;
-static const uint8_t VAL_GROUP_I2COUTPROT_SIZE = VAL_SIZE_1; //All fields in I2C group are currently 1 bit
-
-static const uint8_t VAL_ID_I2COUTPROT_UBX = 0x01;
-static const uint8_t VAL_ID_I2COUTPROT_NMEA = 0x02;
-static const uint8_t VAL_ID_I2COUTPROT_RTCM3 = 0x03;
-
-static const uint8_t VAL_GROUP_I2C = 0x51;
-static const uint8_t VAL_GROUP_I2C_SIZE = VAL_SIZE_8; //All fields in I2C group are currently 1 byte
-
-static const uint8_t VAL_ID_I2C_ADDRESS = 0x01;
-
-// Configuration Sub-Section mask definitions for saveConfigSelective (UBX-CFG-CFG)
-static const uint32_t VAL_CFG_SUBSEC_IOPORT = 0x00000001; // ioPort - communications port settings (causes IO system reset!)
-static const uint32_t VAL_CFG_SUBSEC_MSGCONF = 0x00000002; // msgConf - message configuration
-static const uint32_t VAL_CFG_SUBSEC_INFMSG = 0x00000004; // infMsg - INF message configuration
-static const uint32_t VAL_CFG_SUBSEC_NAVCONF = 0x00000008; // navConf - navigation configuration
-static const uint32_t VAL_CFG_SUBSEC_RXMCONF = 0x00000010; // rxmConf - receiver manager configuration
-static const uint32_t VAL_CFG_SUBSEC_SENCONF = 0x00000100; // senConf - sensor interface configuration (requires protocol 19+)
-static const uint32_t VAL_CFG_SUBSEC_RINVCONF = 0x00000200; // rinvConf - remove inventory configuration
-static const uint32_t VAL_CFG_SUBSEC_ANTCONF = 0x00000400; // antConf - antenna configuration
-static const uint32_t VAL_CFG_SUBSEC_LOGCONF = 0x00000800; // logConf - logging configuration
-static const uint32_t VAL_CFG_SUBSEC_FTSCONF = 0x00001000; // ftsConf - FTS configuration (FTS products only)
-
-
-// Possible values for the dynamic platform model, which provide more accuract position output for the situation. Description extracted from ZED-F9P Integration Manual;
-
-typedef enum
-{
- DYN_MODEL_PORTABLE = 0, //Applications with low acceleration, e.g. portable devices. Suitable for most situations.
- // 1 is not defined
- DYN_MODEL_STATIONARY = 2, //Used in timing applications (antenna must be stationary) or other stationary applications. Velocity restricted to 0 m/s. Zero dynamics assumed.
- DYN_MODEL_PEDESTRIAN, //Applications with low acceleration and speed, e.g. how a pedestrian would move. Low acceleration assumed.
- DYN_MODEL_AUTOMOTIVE, //Used for applications with equivalent dynamics to those of a passenger car. Low vertical acceleration assumed
- DYN_MODEL_SEA, //Recommended for applications at sea, with zero vertical velocity. Zero vertical velocity assumed. Sea level assumed.
- DYN_MODEL_AIRBORNE1g, //Airborne <1g acceleration. Used for applications with a higher dynamic range and greater vertical acceleration than a passenger car. No 2D position fixes supported.
- DYN_MODEL_AIRBORNE2g, //Airborne <2g acceleration. Recommended for typical airborne environments. No 2D position fixes supported.
- DYN_MODEL_AIRBORNE4g, //Airborne <4g acceleration. Only recommended for extremely dynamic environments. No 2D position fixes supported.
- DYN_MODEL_WRIST, // Not supported in protocol versions less than 18. Only recommended for wrist worn applications. Receiver will filter out arm motion.
- DYN_MODEL_BIKE, // Supported in protocol versions 19.2
-} dynModel;
-#ifndef MAX_PAYLOAD_SIZE
-
-//#define MAX_PAYLOAD_SIZE 256 //We need ~220 bytes for getProtocolVersion on most ublox modules
-#define MAX_PAYLOAD_SIZE 300 //Worst case: UBX_CFG_VALSET packet with 64 keyIDs each with 64 bit values
-
-#endif
-
-//-=-=-=-=- UBX binary specific variables
-typedef struct
-{
- uint8_t cls;
- uint8_t id;
- uint16_t len; //Length of the payload. Does not include cls, id, or checksum bytes
- uint16_t counter; //Keeps track of number of overall bytes received. Some responses are larger than 255 bytes.
- uint16_t startingSpot; //The counter value needed to go past before we begin recording into payload array
- uint8_t *payload;
- uint8_t checksumA; //Given to us from module. Checked against the rolling calculated A/B checksums.
- uint8_t checksumB;
- sfe_ublox_packet_validity_e valid; //Goes from NOT_DEFINED to VALID or NOT_VALID when checksum is checked
- sfe_ublox_packet_validity_e classAndIDmatch; // Goes from NOT_DEFINED to VALID or NOT_VALID when the Class and ID match the requestedClass and requestedID
-} ubxPacket;
-
-// Struct to hold the results returned by getGeofenceState (returned by UBX-NAV-GEOFENCE)
-typedef struct
-{
- uint8_t status; // Geofencing status: 0 - Geofencing not available or not reliable; 1 - Geofencing active
- uint8_t numFences; // Number of geofences
- uint8_t combState; // Combined (logical OR) state of all geofences: 0 - Unknown; 1 - Inside; 2 - Outside
- uint8_t states[4]; // Geofence states: 0 - Unknown; 1 - Inside; 2 - Outside
-} geofenceState;
-
-// Struct to hold the current geofence parameters
-typedef struct
-{
- uint8_t numFences; // Number of active geofences
- int32_t lats[4]; // Latitudes of geofences (in degrees * 10^-7)
- int32_t longs[4]; // Longitudes of geofences (in degrees * 10^-7)
- uint32_t rads[4]; // Radii of geofences (in m * 10^-2)
-} geofenceParams;
-
-
-
-
-// A default of 250ms for maxWait seems fine for I2C but is not enough for SerialUSB.
-// If you know you are only going to be using I2C / Qwiic communication, you can
-// safely reduce defaultMaxWait to 250.
-#ifndef defaultMaxWait // Let's allow the user to define their own value if they want to
-#define defaultMaxWait 1000
-#endif
-
- //By default use the default I2C address, and use Wire port
- //bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42); //Returns true if module is detected
- //serialPort needs to be perviously initialized to correct baud rate
-
- //Returns true if device answers on _gpsI2Caddress address or via Serial
- //maxWait is only used for Serial
- bool isConnected(uint16_t maxWait);
-
- //Changed in V1.8.1: provides backward compatibility for the examples that call checkUblox directly
- //Will default to using packetCfg to look for explicit autoPVT packets so they get processed correctly by processUBX
- bool checkUblox(uint8_t requestedClass, uint8_t requestedID); //Checks module with user selected commType
-
- bool checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Method for I2C polling of data, passing any new bytes to process()
- bool checkUbloxSerial(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Method for serial polling of data, passing any new bytes to process()
-
- void process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Processes NMEA and UBX binary sentences one byte at a time
- void processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Given a character, file it away into the uxb packet structure
- void processRTCMframe(uint8_t incoming); //Monitor the incoming bytes for start and length bytes
- void processRTCM(uint8_t incoming) __attribute__((weak)); //Given rtcm byte, do something with it. User can overwrite if desired to pipe bytes to radio, internet, etc.
-
- void processUBXpacket(ubxPacket *msg); //Once a packet has been received and validated, identify this packet's class/id and update internal flags
- void processNMEA(char incoming) __attribute__((weak)); //Given a NMEA character, do something with it. User can overwrite if desired to use something like tinyGPS or MicroNMEA libraries
-
- void calcChecksum(ubxPacket *msg); //Sets the checksumA and checksumB of a given messages
- sfe_ublox_status_e sendCommand(ubxPacket *outgoingUBX, uint16_t maxWait ); //Given a packet and payload, send everything including CRC bytes, return true if we got a response
- sfe_ublox_status_e sendI2cCommand(ubxPacket *outgoingUBX, uint16_t maxWait );
- void sendSerialCommand(ubxPacket *outgoingUBX);
-
- void printPacket(ubxPacket *packet); //Useful for debugging
-
- void factoryReset(void); //Send factory reset sequence (i.e. load "default" configuration and perform hardReset)
- void hardReset(void); //Perform a reset leading to a cold start (zero info start-up)
- void ihardReset(void); //Perform a reset leading to a cold start (zero info start-up) imperial
-
- bool setI2CAddress(uint8_t deviceAddress, uint16_t maxTime); //Changes the I2C address of the Ublox module
- void setSerialRate(uint32_t baudrate, uint8_t uartPort, uint16_t maxTime ); //Changes the serial baud rate of the Ublox module, uartPort should be COM_PORT_UART1/2
-
- bool setNavigationFrequency(uint8_t navFreq, uint16_t maxWait); //Set the number of nav solutions sent per second
- uint8_t getNavigationFrequency(uint16_t maxWait ); //Get the number of nav solutions sent per second currently being output by module
- bool saveConfiguration(uint16_t maxWait); //Save current configuration to flash and BBR (battery backed RAM)
- bool factoryDefault(uint16_t maxWait); //Reset module to factory defaults
- bool saveConfigSelective(uint32_t configMask, uint16_t maxWait); //Save the selected configuration sub-sections to flash and BBR (battery backed RAM)
- void setSoftBackup(bool do_it);
-
- sfe_ublox_status_e waitForACKResponse(ubxPacket *outgoingUBX, uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime ); //Poll the module until a config packet and an ACK is received
- sfe_ublox_status_e waitForNoACKResponse(ubxPacket *outgoingUBX, uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime ); //Poll the module until a config packet is received
-
-// getPVT will only return data once in each navigation cycle. By default, that is once per second.
-// Therefore we should set getPVTmaxWait to slightly longer than that.
-// If you change the navigation frequency to (e.g.) 4Hz using setNavigationFrequency(4)
-// then you should use a shorter maxWait for getPVT. 300msec would be about right: getPVT(300)
-// The same is true for getHPPOSLLH.
-#define getPVTmaxWait 1100 // Default maxWait for getPVT and all functions which call it
-#define getHPPOSLLHmaxWait 1100 // Default maxWait for getHPPOSLLH and all functions which call it
-
- bool assumeAutoPVT(bool enabled, bool implicitUpdate); //In case no config access to the GPS is possible and PVT is send cyclically already
- bool setAutoPVT(bool enabled, uint16_t maxWait ); //Enable/disable automatic PVT reports at the navigation frequency
- bool getPVT(uint16_t maxWait ); //Query module for latest group of datums and load global vars: lat, long, alt, speed, SIV, accuracies, etc. If autoPVT is disabled, performs an explicit poll and waits, if enabled does not block. Retruns true if new PVT is available.
- bool getHPPOSLLH(uint16_t maxWait ); //Query module for latest group of datums and load global vars: lat, long, alt, speed, SIV, accuracies, etc. If autoPVT is disabled, performs an explicit poll and waits, if enabled does not block. Retruns true if new PVT is available.
- void flushPVT(void); //Mark all the PVT data as read/stale. This is handy to get data alignment after CRC failure
-
- int32_t getLatitude(uint16_t maxWait ); //Returns the current latitude in degrees * 10^-7. Auto selects between HighPrecision and Regular depending on ability of module.
- int32_t getLongitude(uint16_t maxWait ); //Returns the current longitude in degrees * 10-7. Auto selects between HighPrecision and Regular depending on ability of module.
- int32_t getAltitude(uint16_t maxWait ); //Returns the current altitude in mm above ellipsoid
- int32_t getAltitudeMSL(uint16_t maxWait ); //Returns the current altitude in mm above mean sea level
- uint8_t getSIV(uint16_t maxWait ); //Returns number of sats used in fix
- uint8_t getFixType(uint16_t maxWait ); //Returns the type of fix: 0=no, 3=3D, 4=GNSS+Deadreckoning
- uint8_t getgnssFixOK(uint16_t maxWait ); //Returns the fix validity: 0=not valid, 1 = fix valid
- uint8_t getCarrierSolutionType(uint16_t maxWait ); //Returns RTK solution: 0=no, 1=float solution, 2=fixed solution
- int32_t getGroundSpeed(uint16_t maxWait ); //Returns speed in mm/s
- int32_t getHeading(uint16_t maxWait ); //Returns heading in degrees * 10^-7
- uint16_t getPDOP(uint16_t maxWait ); //Returns positional dillution of precision * 10^-2
- uint16_t getYear(uint16_t maxWait );
- uint8_t getMonth(uint16_t maxWait );
- uint8_t getDay(uint16_t maxWait );
- uint8_t getHour(uint16_t maxWait );
- uint8_t getMinute(uint16_t maxWait );
- uint8_t getSecond(uint16_t maxWait );
- uint16_t getMillisecond(uint16_t maxWait );
- int32_t getNanosecond(uint16_t maxWait );
- uint32_t getTimeOfWeek(uint16_t maxWait );
- bool getDateValid(uint16_t maxWait);
- bool getTimeValid(uint16_t maxWait);
-
- int32_t getHighResLatitude(uint16_t maxWait );
- int8_t getHighResLatitudeHp(uint16_t maxWait );
- int32_t getHighResLongitude(uint16_t maxWait );
- int8_t getHighResLongitudeHp(uint16_t maxWait );
- int32_t getElipsoid(uint16_t maxWait );
- int8_t getElipsoidHp(uint16_t maxWait );
- int32_t getMeanSeaLevel(uint16_t maxWait );
- int8_t getMeanSeaLevelHp(uint16_t maxWait );
- int32_t getGeoidSeparation(uint16_t maxWait );
- uint32_t getHorizontalAccuracy(uint16_t maxWait );
- uint32_t getVerticalAccuracy(uint16_t maxWait );
-
- //Port configurations
- bool setPortOutput(uint8_t portID, uint8_t comSettings, uint16_t maxWait ); //Configure a given port to output UBX, NMEA, RTCM3 or a combination thereof
- bool setPortInput(uint8_t portID, uint8_t comSettings, uint16_t maxWait ); //Configure a given port to input UBX, NMEA, RTCM3 or a combination thereof
- bool getPortSettings(uint8_t portID, uint16_t maxWait ); //Returns the current protocol bits in the UBX-CFG-PRT command for a given port
-
- bool setI2COutput(uint8_t comSettings, uint16_t maxWait ); //Configure I2C port to output UBX, NMEA, RTCM3 or a combination thereof
- bool setUART1Output(uint8_t comSettings, uint16_t maxWait ); //Configure UART1 port to output UBX, NMEA, RTCM3 or a combination thereof
- bool setUART2Output(uint8_t comSettings, uint16_t maxWait ); //Configure UART2 port to output UBX, NMEA, RTCM3 or a combination thereof
- bool setUSBOutput(uint8_t comSettings, uint16_t maxWait ); //Configure USB port to output UBX, NMEA, RTCM3 or a combination thereof
- bool setSPIOutput(uint8_t comSettings, uint16_t maxWait ); //Configure SPI port to output UBX, NMEA, RTCM3 or a combination thereof
-
- //Functions to turn on/off message types for a given port ID (see COM_PORT_I2C, etc above)
- bool configureMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint8_t sendRate, uint16_t maxWait );
- bool enableMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint8_t sendRate , uint16_t maxWait );
- bool disableMessage(uint8_t msgClass, uint8_t msgID, uint8_t portID, uint16_t maxWait );
- bool enableNMEAMessage(uint8_t msgID, uint8_t portID, uint8_t sendRate , uint16_t maxWait );
- bool disableNMEAMessage(uint8_t msgID, uint8_t portID, uint16_t maxWait );
- bool enableRTCMmessage(uint8_t messageNumber, uint8_t portID, uint8_t sendRate, uint16_t maxWait ); //Given a message number turns on a message ID for output over given PortID
- bool disableRTCMmessage(uint8_t messageNumber, uint8_t portID, uint16_t maxWait ); //Turn off given RTCM message from a given port
-
- //General configuration (used only on protocol v27 and higher - ie, ZED-F9P)
- //It is probably safe to assume that users of the ZED-F9P will be using I2C / Qwiic.
- //If they are using Serial then the higher baud rate will also help. So let's leave maxWait set to 250ms.
- uint8_t getVal8(uint16_t group, uint16_t id, uint8_t size, uint8_t layer , uint16_t maxWait ); //Returns the value at a given group/id/size location
- uint8_t setVal(uint32_t keyID, uint16_t value, uint8_t layer , uint16_t maxWait ); //Sets the 16-bit value at a given group/id/size location
- uint8_t setVal8(uint32_t keyID, uint8_t value, uint8_t layer , uint16_t maxWait ); //Sets the 8-bit value at a given group/id/size location
- uint8_t setVal16(uint32_t keyID, uint16_t value, uint8_t layer , uint16_t maxWait ); //Sets the 16-bit value at a given group/id/size location
- uint8_t setVal32(uint32_t keyID, uint32_t value, uint8_t layer , uint16_t maxWait ); //Sets the 32-bit value at a given group/id/size location
- uint8_t newCfgValset8(uint32_t keyID, uint8_t value, uint8_t layer ); //Define a new UBX-CFG-VALSET with the given KeyID and 8-bit value
- uint8_t newCfgValset16(uint32_t keyID, uint16_t value, uint8_t layer ); //Define a new UBX-CFG-VALSET with the given KeyID and 16-bit value
- uint8_t newCfgValset32(uint32_t keyID, uint32_t value, uint8_t layer ); //Define a new UBX-CFG-VALSET with the given KeyID and 32-bit value
- uint8_t addCfgValset8(uint32_t keyID, uint8_t value); //Add a new KeyID and 8-bit value to an existing UBX-CFG-VALSET ubxPacket
- uint8_t addCfgValset16(uint32_t keyID, uint16_t value); //Add a new KeyID and 16-bit value to an existing UBX-CFG-VALSET ubxPacket
- uint8_t addCfgValset32(uint32_t keyID, uint32_t value); //Add a new KeyID and 32-bit value to an existing UBX-CFG-VALSET ubxPacket
- uint8_t sendCfgValset8(uint32_t keyID, uint8_t value, uint16_t maxWait ); //Add the final KeyID and 8-bit value to an existing UBX-CFG-VALSET ubxPacket and send it
- uint8_t sendCfgValset16(uint32_t keyID, uint16_t value, uint16_t maxWait ); //Add the final KeyID and 16-bit value to an existing UBX-CFG-VALSET ubxPacket and send it
- uint8_t sendCfgValset32(uint32_t keyID, uint32_t value, uint16_t maxWait ); //Add the final KeyID and 32-bit value to an existing UBX-CFG-VALSET ubxPacket and send it
-
- //Functions used for RTK and base station setup
- //It is probably safe to assume that users of the RTK will be using I2C / Qwiic. So let's leave maxWait set to 250ms.
- bool getSurveyMode(uint16_t maxWait ); //Get the current TimeMode3 settings
- bool setSurveyMode(uint8_t mode, uint16_t observationTime, float requiredAccuracy, uint16_t maxWait ); //Control survey in mode
- bool enableSurveyMode(uint16_t observationTime, float requiredAccuracy, uint16_t maxWait ); //Begin Survey-In for NEO-M8P
- bool disableSurveyMode(uint16_t maxWait ); //Stop Survey-In mode
-
- bool getSurveyStatus(uint16_t maxWait); //Reads survey in status and sets the global variables
-
- uint32_t getPositionAccuracy(uint16_t maxWait ); //Returns the 3D accuracy of the current high-precision fix, in mm. Supported on NEO-M8P, ZED-F9P,
-
- uint8_t getProtocolVersionHigh(uint16_t maxWait ); //Returns the PROTVER XX.00 from UBX-MON-VER register
- uint8_t getProtocolVersionLow(uint16_t maxWait ); //Returns the PROTVER 00.XX from UBX-MON-VER register
- bool getProtocolVersion(uint16_t maxWait ); //Queries module, loads low/high bytes
-
- bool getRELPOSNED(uint16_t maxWait ); //Get Relative Positioning Information of the NED frame
-
- //void enableDebugging(Stream &debugPort, bool printLimitedDebug); //Given a port to print to, enable debug messages. Default to all, not limited.
- void disableDebugging(void); //Turn off debug statements
- void debugPrint(char *message); //Safely print debug statements
- void debugPrintln(char *message); //Safely print debug statements
- const char *statusString(sfe_ublox_status_e stat); //Pretty print the return value
-
-
- bool powerSaveMode(bool power_save, uint16_t maxWait );
- uint8_t getPowerSaveMode(uint16_t maxWait ); // Returns 255 if the sendCommand fails
-
- //Change the dynamic platform model using UBX-CFG-NAV5
- bool setDynamicModel(dynModel newDynamicModel, uint16_t maxWait );
- uint8_t getDynamicModel(uint16_t maxWait ); // Get the dynamic model - returns 255 if the sendCommand fails
-
- bool getEsfInfo(uint16_t maxWait);
- bool getEsfIns(uint16_t maxWait);
- bool getEsfDataInfo(uint16_t maxWait);
- bool getEsfRawDataInfo(uint16_t maxWait );
- sfe_ublox_status_e getSensState(uint8_t sensor, uint16_t maxWait );
- bool getVehAtt(uint16_t maxWait );
-
- // Change constellations
- bool setGPS_constellation_only(uint16_t maxWait);
-
- // Set power save config for the pico tracker lora
- bool set_powersave_config(uint16_t maxWait);
-
- //Functions
- bool checkUbloxInternal(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Checks module with user selected commType
- uint32_t extractLong(uint8_t spotToStart); //Combine four bytes from payload into long
- uint16_t extractInt(uint8_t spotToStart); //Combine two bytes from payload into int
- uint8_t extractByte(uint8_t spotToStart); //Get byte from payload
- int8_t extractSignedChar(uint8_t spotToStart); //Get signed 8-bit value from payload
- void addToChecksum(uint8_t incoming); //Given an incoming byte, adjust rollingChecksumA/B
-
-#endif
-#ifdef __cplusplus
-}
-#endif
-
diff --git a/src/peripherals/bsp.c b/src/peripherals/bsp.c
index c609547d2..2bd640062 100644
--- a/src/peripherals/bsp.c
+++ b/src/peripherals/bsp.c
@@ -20,7 +20,6 @@
/* Includes ------------------------------------------------------------------*/
#include
#include "bsp.h"
-#include "ublox.h"
#include "playback.h"
#include "nvmm.h"
#include "iwdg.h"
@@ -35,6 +34,12 @@
#include "position_time_encoder.h"
#include "string.h"
#include "eeprom_settings_manager.h"
+#include "cli.h"
+#include "i2c.h"
+#include "delay.h"
+#include "gps.h"
+
+extern Uart_t Uart1;
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
@@ -59,9 +64,6 @@ time_pos_fix_t current_position =
sensor_t sensor_data;
playback_key_info_t *playback_key_info_ptr;
-gps_info_t gps_info_latest;
-
-extern Gpio_t Load_enable;
double TEMPERATURE_Value;
@@ -102,21 +104,18 @@ void BSP_sensor_Read(void)
#endif
#if GPS_ENABLED
-
uint32_t time_out = read_tx_interval_in_eeprom(GPS_SEARCH_TIME_ADDR, GPS_SEARCH_TIMEOUT);
- get_location_fix(time_out);
- gps_info_latest = get_latest_gps_info();
IWDG_reset();
#endif
- if (get_latest_gps_status() == GPS_SUCCESS)
+ if (GpsHasFix() == true)
{
update_geofence_status();
}
/* read solar voltage under gps and no load */
uint16_t no_load_solar_voltage = BoardGetBatteryVoltage();
- uint16_t load_solar_voltage = get_load_solar_voltage();
+ uint16_t load_solar_voltage = BoardGetBatteryVoltage();
/* calculate days of playback available */
time_pos_fix_t oldest_timepos_record = get_oldest_pos_time();
@@ -124,6 +123,18 @@ void BSP_sensor_Read(void)
sensor_data.days_of_playback = (uint8_t)((most_recent_timepos_record.minutes_since_epoch - oldest_timepos_record.minutes_since_epoch) / MINUTES_IN_DAY);
+ double latitude = 0;
+ double longitude = 0;
+ GpsGetLatestGpsPositionDouble(&latitude, &longitude);
+ uint16_t altitudeGps = GpsGetLatestGpsAltitude(); // in m
+
+ gps_info_t gps_info_latest = {
+ .GPS_UBX_latitude_Float = latitude,
+ .GPS_UBX_longitude_Float = longitude,
+ .GPSaltitude_mm = altitudeGps * 1000,
+ .GPSsats = 0,
+ .unix_time = 16000000};
+
/* pretty print sensor values for debugging */
pretty_print_sensor_values(&TEMPERATURE_Value, &sensor_data.status_bitfields, &gps_info_latest, &no_load_solar_voltage, &load_solar_voltage);
@@ -155,9 +166,9 @@ void settings_crc_set()
void update_geofence_status()
{
/* Find out which region of world we are in and update region parm*/
-
- gps_info_t gps_info = get_latest_gps_info();
- update_geofence_position(gps_info.GPS_UBX_latitude_Float, gps_info.GPS_UBX_longitude_Float);
+ double latitude = 0, longitude = 0;
+ GpsGetLatestGpsPositionDouble(&latitude, &longitude);
+ update_geofence_position(latitude, longitude);
/* Save current polygon to eeprom only if gps fix was valid */
set_eeprom_stored_lorwan_region();
@@ -201,7 +212,7 @@ void save_data_to_nvm()
/* now save all this data to non volatile memory */
time_pos_fix_t most_recent = retrieve_eeprom_time_pos(0);
- if (gps_info_latest.latest_gps_status == GPS_SUCCESS)
+ if (GpsHasFix() == true)
{
/* After the time between saving(HOW_OFTEN_TO_SAVE_POS_TIM_TO_EEPROM) has elapsed, then
* increment the counter such that it can save to the next location
@@ -374,17 +385,6 @@ void BSP_sensor_Init(void)
#endif
-#if GPS_ENABLED
- printf("SELFTEST: Initialising GPS\n\r");
-
- GpioWrite(&Load_enable, 0); /* Enable power to GPS */
- gps_info_latest = get_latest_gps_info();
- //GPS SETUP
- setup_GPS();
-
- IWDG_reset();
-
-#endif
}
/**
@@ -636,4 +636,3 @@ int mod(int a, int b)
int r = a % b;
return r < 0 ? r + b : r;
}
-
diff --git a/src/peripherals/config.h b/src/peripherals/config.h
index f8cee4d53..7fa4ee922 100644
--- a/src/peripherals/config.h
+++ b/src/peripherals/config.h
@@ -42,7 +42,7 @@ extern "C"
#define GPS_ENABLED 1 /* Enable Ublox GPS. Init the GPS as well. Allowed values: 0 disabled , 1(default) enabled */
#define USE_LED 1 /* Enable LED blinky. Allowed values: 0 disabled , 1(default) enabled */
-#define USE_NVM_STORED_LORAWAN_REGION 1 /* Use LoRaWAN region stored in EEPROm. Allowed values: 0 disabled , 1(default) enabled. If not using EEPROM location, \
+#define USE_NVM_STORED_LORAWAN_REGION 0 /* Use LoRaWAN region stored in EEPROm. Allowed values: 0 disabled , 1(default) enabled. If not using EEPROM location, \
* use EU868 \
*/
@@ -80,7 +80,7 @@ extern "C"
/* WATCHDOG RELATED DEFINES */
/* ----------------------------------------------------------------------------------- */
-#define USE_WATCHDOG 1 /* Use watchdog. Allowed values: 0 disabled , 1(default) enabled */
+#define USE_WATCHDOG 0 /* Use watchdog. Allowed values: 0 disabled , 1(default) enabled */
/* TTN, Helium frame count settings. Set the frame count to start from for either network. */
#define HELIUM_FRAME_COUNT_START 731
@@ -96,7 +96,7 @@ extern "C"
* @brief Choose whether to go into Deep sleep or not
*
*/
-#define DEEP_SLEEP_ENABLE true
+#define DEEP_SLEEP_ENABLE false
/**
* @brief Choose weather to disable serial output to reduce peak currents
@@ -120,7 +120,7 @@ extern "C"
* @brief Define how quickly to return to searching for a GPS fix after transmitting
*
*/
-#define TX_INTERVAL_GPS_FIX_OK 2800 /* When fix was aquired, then sleep for this period (in milliseconds) before searching again */
+#define TX_INTERVAL_GPS_FIX_OK 5000 /* When fix was aquired, then sleep for this period (in milliseconds) before searching again */
/**
* @brief Lorawan defaults, normally will not be changed
diff --git a/src/peripherals/i2c_middleware.c b/src/peripherals/i2c_middleware.c
deleted file mode 100644
index 1f27d3bf2..000000000
--- a/src/peripherals/i2c_middleware.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- ******************************************************************************
- * @file : i2c_middleware.c
- * @brief : I2C middleware for this specific project, using HAL
- * libraries
- ******************************************************************************
- * Imperial College Space Society
- * Medad Newman, Richard Ibbotson
- *
- *
- ******************************************************************************
- */
-
-/* ==================================================================== */
-/* ========================== include files =========================== */
-/* ==================================================================== */
-
-/* Inclusion of system and local header files goes here */
-
-#include "i2c_middleware.h"
-#include "config.h"
-#include "stdio.h"
-#include "delay.h"
-// #include "iwdg.h"
-#include "board.h"
-#include "i2c.h"
-#include "deep_sleep_delay.h"
-
-extern I2c_t I2c;
-extern Gpio_t Load_enable;
-extern Gpio_t i2c_scl;
-extern Gpio_t i2c_sda;
-
-/* ==================================================================== */
-/* ============================ constants ============================= */
-/* ==================================================================== */
-
-/* #define and enum statements go here */
-
-/* ==================================================================== */
-/* ======================== global variables ========================== */
-/* ==================================================================== */
-
-/* Global variables definitions go here */
-
-/* ==================================================================== */
-/* ========================== private data ============================ */
-/* ==================================================================== */
-
-/* Definition of private datatypes go here */
-
-/* ==================================================================== */
-/* ====================== private functions =========================== */
-/* ==================================================================== */
-
-/* Function prototypes for private (static) functions go here */
-
-/* ==================================================================== */
-/* ===================== All functions by section ===================== */
-/* ==================================================================== */
-
-/* Functions definitions go here, organised into sections */
-
-/* rapidly toggle the i2c lines to get it unstuck
- * Workaround to solve this mysterious problem where the sda line
- * appears to get stuck low.
- */
-I2C_MIDDLEWARE_STATUS_t reinit_i2c()
-{
- /* Deinit i2c bus */
- I2cDeInit(&I2c);
-
- /* disable power to GPS */
- GpioWrite(&Load_enable, 1);
- DelayMs(100);
-
- /* Make I2C bus pins GPIO */
- GpioInit(&i2c_scl, PB_8, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1);
- GpioInit(&i2c_sda, PB_9, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1);
-
- /* set i2c pins low to ensure it cannot power up the core of the GPS */
- GpioWrite(&i2c_scl, 0);
- GpioWrite(&i2c_sda, 0);
-
- DelayMs(100);
-
- /* Enable power to GPS */
- GpioWrite(&Load_enable, 0);
- DelayMs(1000);
-
- /* send 9 clock pulses to the GPS ref: https://www.microchip.com/forums/FindPost/175578 */
- for (uint8_t i = 0; i < 9; i++)
- {
- GpioWrite(&i2c_scl, 0);
- DelayMs(1);
- GpioWrite(&i2c_scl, 1);
- DelayMs(1);
- }
-
- DelayMs(100);
-
- I2cInit(&I2c, I2C_1, PB_8, PB_9);
-
- return I2C_SUCCSS;
-}
diff --git a/src/peripherals/i2c_middleware.h b/src/peripherals/i2c_middleware.h
deleted file mode 100644
index 48574e786..000000000
--- a/src/peripherals/i2c_middleware.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- ******************************************************************************
- * @file : i2c_middleware.h
- * @brief : I2C middleware for this specific project, using HAL
- * libraries. The header file
- ******************************************************************************
- * Imperial College Space Society
- * Medad Newman, Richard Ibbotson
- *
- *
- ******************************************************************************
- */
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#ifndef I2C_MIDDLEWARE_H
-#define I2C_MIDDLEWARE_H
-
- /* ==================================================================== */
- /* ========================== include files =========================== */
- /* ==================================================================== */
-
- /* Inclusion of system and local header files goes here */
-
-#include
-#include
-
- /* ==================================================================== */
- /* ============================ constants ============================= */
- /* ==================================================================== */
-
- /* #define and enum statements go here */
-
- /* ==================================================================== */
- /* ========================== public data ============================= */
- /* ==================================================================== */
-
- /* Definition of public (external) data types go here */
-
- /**
- * I2C status
- */
- typedef enum
- {
- I2C_SUCCSS = 0,
- I2C_FAIL
- } I2C_MIDDLEWARE_STATUS_t;
-
- /* ==================================================================== */
- /* ======================= public functions =========================== */
- /* ==================================================================== */
-
- /* Function prototypes for public (external) functions go here */
-
- I2C_MIDDLEWARE_STATUS_t reinit_i2c(void);
-
-#endif // I2C_MIDDLEWARE_H
-#ifdef __cplusplus
-}
-#endif
diff --git a/src/peripherals/position_time_encoder.h b/src/peripherals/position_time_encoder.h
index 7f1939de3..f394c8f62 100644
--- a/src/peripherals/position_time_encoder.h
+++ b/src/peripherals/position_time_encoder.h
@@ -18,7 +18,7 @@ extern "C"
#define POSITION_TIME_H
#include "bsp.h"
-#include "ublox.h"
+#include "gps.h"
time_pos_fix_t encode_time_pos(gps_info_t gps_info);
gps_info_t decode_time_pos(time_pos_fix_t time_pos_fix);
diff --git a/src/peripherals/ublox.c b/src/peripherals/ublox.c
deleted file mode 100644
index 1d5849a1d..000000000
--- a/src/peripherals/ublox.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * ublox.c
- * Author: Medad Newman 23/12/19
- * Imperial College Space Society ( Medad Newman, Richard Ibbotson)
- *
- * modified from TT7's ublox code:
- * https://github.com/TomasTT7/TT7F-Float-Tracker/blob/99133b762c971b24040d007fff3f1a348941d788/Software/ARM_UBLOX.c
- * Author: Tomy2
- *
- */
-
-/* ==================================================================== */
-/* ========================== include files =========================== */
-/* ==================================================================== */
-
-/* Inclusion of system and local header files goes here */
-
-#include "ublox.h"
-#include "config.h"
-#include "utilities.h"
-#include "i2c.h"
-#include
-#include
-#include
-#include "iwdg.h"
-#include "delay.h"
-
-#include "SparkFun_Ublox_Arduino_Library.h"
-
-#include "i2c_middleware.h"
-extern I2c_t I2c;
-extern Gpio_t Led1;
-extern Gpio_t Gps_int;
-
-/* ==================================================================== */
-/* ============================ constants ============================= */
-/* ==================================================================== */
-
-/* #define and enum statements go here */
-#define SATS 4 // number of satellites required for positional solution
-
-/* ==================================================================== */
-/* ======================== global variables ========================== */
-/* ==================================================================== */
-
-/* Global variables definitions go here */
-
-uint16_t load_solar_voltage = 0;
-gps_info_t gps_info = {.unix_time = UINT16_MAX, .latest_gps_status = GPS_FAILURE};
-
-/* ==================================================================== */
-/* ========================== private data ============================ */
-/* ==================================================================== */
-
-/* Definition of private datatypes go here */
-
-/* ==================================================================== */
-/* ====================== private functions =========================== */
-/* ==================================================================== */
-
-/* Function prototypes for private (static) functions go here */
-
-uint32_t systimeMS_get(void);
-static gps_status_t display_still_searching(void);
-static gps_status_t display_fix_found(void);
-
-/* ==================================================================== */
-/* ===================== All functions by section ===================== */
-/* ==================================================================== */
-
-/* Functions definitions go here, organised into sections */
-
-uint32_t systimeMS_get()
-{
- return SysTimeToMs(SysTimeGet());
-}
-
-gps_status_t get_latest_gps_status(void)
-{
- return gps_info.latest_gps_status;
-}
-
-gps_info_t get_latest_gps_info(void)
-{
- return gps_info;
-}
-
-/* Get solar voltage when under load from GPS */
-uint16_t get_load_solar_voltage()
-{
- return load_solar_voltage;
-}
-
-/*
- * Sets up gps by putting in airbourne mode, setting to use GPS satellites only, turning off NMEA
- *
- */
-gps_status_t setup_GPS()
-{
- IWDG_reset();
-
- DelayMs(GPS_WAKEUP_TIMEOUT); // Wait for things to be setup
-
- /* Check if we are in airbourne mode. check if dynamic mode is correct. If its not, then setup the GPS */
- uint8_t newDynamicModel = getDynamicModel(defaultMaxWait);
-
- switch (newDynamicModel)
- {
- case DYN_MODEL_AIRBORNE1g:
- printf("The current dynamic model correct and is: %d\n", newDynamicModel);
- break;
-
- case 255:
- printf("***!!! Warning: getDynamicModel failed !!!***\n");
- reinit_i2c();
- break;
-
- default:
- printf("The current dynamic model is INCORRECT. The current dynamic model is: %d\n", newDynamicModel);
-
- // Limit i2c output to UBX, set dyanmic model and send power save config.
- bool success = setDynamicModel(DYN_MODEL_AIRBORNE1g, defaultMaxWait) && saveConfiguration(defaultMaxWait);
-
- if (success)
- {
- printf("GPS setup successfully\n");
- }
- else
- {
- printf("***GPS setup failed***\n");
- reinit_i2c();
- }
- break;
- }
-
- IWDG_reset();
-
- return GPS_SUCCESS;
-}
-
-/* Get the location fix. setup_GPS() must have been called prior to this call */
-gps_status_t get_location_fix(uint32_t timeout)
-{
-
- IWDG_reset();
-
- /* Set all the GPS info values to zeros */
- memset(&gps_info, 0, sizeof(gps_info_t));
-
- /* poll UBX-NAV-PVT until the module has fix */
- uint32_t startTime = systimeMS_get();
- while (systimeMS_get() - startTime < timeout)
- {
- IWDG_reset();
-
- display_still_searching();
-
- uint8_t temp_GPSfix_type = getFixType(defaultMaxWait);
- uint8_t temp_GPSsats = getSIV(defaultMaxWait);
- uint8_t temp_GPShour = getHour(defaultMaxWait);
- uint8_t temp_GPSminute = getMinute(defaultMaxWait);
- uint8_t temp_GPSsecond = getSecond(defaultMaxWait);
- uint8_t temp_GPSmillisecond = getMillisecond(defaultMaxWait);
-
- uint16_t temp_GPSyear = getYear(defaultMaxWait);
- uint8_t temp_GPSmonth = getMonth(defaultMaxWait);
- uint8_t temp_GPSday = getDay(defaultMaxWait);
- uint8_t temp_GPSfix_OK = getgnssFixOK(defaultMaxWait);
-
- SysTime_t stime = SysTimeGetMcuTime();
- printf("%3lds%03dms: ", stime.Seconds, stime.SubSeconds);
-
- uint32_t current_time = (systimeMS_get() - startTime) / 1000;
-
- printf("Fixtype: ");
- if (temp_GPSfix_type == 0)
- printf("No fix ");
- else if (temp_GPSfix_type == 1)
- printf("Dead reckoning ");
- else if (temp_GPSfix_type == 2)
- printf("2D ");
- else if (temp_GPSfix_type == 3)
- printf("3D ");
- else if (temp_GPSfix_type == 4)
- printf("GNSS+Dead reckoning ");
-
- printf(" Sats:%d ", temp_GPSsats);
- printf(" GPSfix_OK:%d ", temp_GPSfix_OK);
- printf(" GPS time: %02d/%02d/%04d, %02d:%02d:%02d.%04d ", temp_GPSday, temp_GPSmonth, temp_GPSyear, temp_GPShour, temp_GPSminute, temp_GPSsecond, temp_GPSmillisecond);
- printf(" GPS Search time[s]: %ld ", current_time);
-
- struct tm t;
- time_t t_of_day;
-
- t.tm_year = temp_GPSyear - 1900; // Year - 1900
- t.tm_mon = temp_GPSmonth - 1; // Month, where 0 = jan
- t.tm_mday = temp_GPSday; // Day of the month
- t.tm_hour = temp_GPShour;
- t.tm_min = temp_GPSminute;
- t.tm_sec = temp_GPSsecond;
- t.tm_isdst = 0; // Is DST on? 1 = yes, 0 = no, -1 = unknown
- t_of_day = mktime(&t);
-
- printf("Epoch[s]: %ld\n", (uint32_t)t_of_day);
-
- load_solar_voltage = BoardGetBatteryVoltage();
-
- if (temp_GPSsats >= SATS) // As long as we have 4 sats in solution, the fix is good enough. First time to fix is much more important than accuracy.
- {
- display_fix_found();
-
- gps_info.GPSsats = temp_GPSsats;
- gps_info.GPS_UBX_latitude_Float = (float)getLatitude(defaultMaxWait) / 10000000;
- gps_info.GPS_UBX_longitude_Float = (float)getLongitude(defaultMaxWait) / 10000000;
- gps_info.GPSaltitude_mm = getAltitude(defaultMaxWait);
- gps_info.unix_time = (uint32_t)t_of_day;
- gps_info.latest_gps_status = GPS_SUCCESS;
- return GPS_SUCCESS;
- }
- IWDG_reset();
- DelayMs(2000);
- IWDG_reset();
- }
-
- /* If fix taking too long,resend all the settings,
- * and put it to sleep.
- */
- setup_GPS();
-
- gps_info.latest_gps_status = GPS_FAILURE;
- return GPS_FAILURE;
-}
-
-/* Indicator led to indicate that still searching */
-static gps_status_t display_still_searching()
-{
- GpioWrite(&Led1, 1);
- DelayMs(100);
- GpioWrite(&Led1, 0);
-
- return GPS_SUCCESS;
-}
-
-/* Indicate that fix has been found */
-static gps_status_t display_fix_found()
-{
- for (uint8_t i = 0; i < 20; i++)
- {
- IWDG_reset();
-
- GpioWrite(&Led1, 1);
- DelayMs(50);
- GpioWrite(&Led1, 0);
- DelayMs(50);
- }
-
- return GPS_SUCCESS;
-}
diff --git a/src/peripherals/ublox.h b/src/peripherals/ublox.h
deleted file mode 100644
index 40a22d9c4..000000000
--- a/src/peripherals/ublox.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- ******************************************************************************
- * @file : ublox.h
- * @brief : Driver header file for ublox.c
- ******************************************************************************
- * Imperial College Space Society
- * Medad Newman, Richard Ibbotson
- *
- *
- ******************************************************************************
- */
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#ifndef UBLOX_H
-#define UBLOX_H
-
- /* ==================================================================== */
- /* ========================== include files =========================== */
- /* ==================================================================== */
-
- /* Inclusion of system and local header files goes here */
-
-#include
-
- /* ==================================================================== */
- /* ============================ constants ============================= */
- /* ==================================================================== */
-
- /* #define and enum statements go here */
-
- typedef enum
- {
- GPS_FAILURE = 0,
- GPS_SUCCESS
- } gps_status_t;
-
- typedef struct
- {
- float GPS_UBX_latitude_Float; // YY.YYYYYYY, in +/- DEGREES,
- float GPS_UBX_longitude_Float; // XXX.XXXXXXX, in +/- DEGREES,
- int32_t GPSaltitude_mm; // in millimeters
- uint8_t GPSsats;
- uint32_t unix_time;
- gps_status_t latest_gps_status;
-
- } gps_info_t;
-
- /* ==================================================================== */
- /* ========================== public data ============================= */
- /* ==================================================================== */
-
- /* Definition of public (external) data types go here */
-
- /* ==================================================================== */
- /* ======================= public functions =========================== */
- /* ==================================================================== */
-
- /* Function prototypes for public (external) functions go here */
-
- gps_status_t get_location_fix(uint32_t timeout);
- gps_status_t setup_GPS(void);
- gps_status_t get_latest_gps_status(void);
- uint16_t get_load_solar_voltage(void);
- gps_info_t get_latest_gps_info(void);
-
-#endif
-#ifdef __cplusplus
-}
-#endif
diff --git a/src/system/gps.h b/src/system/gps.h
index d94224aa3..4cbacbbbc 100644
--- a/src/system/gps.h
+++ b/src/system/gps.h
@@ -54,6 +54,15 @@ typedef struct
char NmeaDate[8];
}NmeaGpsData_t;
+typedef struct
+{
+ float GPS_UBX_latitude_Float; // YY.YYYYYYY, in +/- DEGREES,
+ float GPS_UBX_longitude_Float; // XXX.XXXXXXX, in +/- DEGREES,
+ int32_t GPSaltitude_mm; // in millimeters
+ uint8_t GPSsats;
+ uint32_t unix_time;
+} gps_info_t;
+
/*!
* \brief Initializes the handling of the GPS receiver
*/
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f37040d6f..60df69c86 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -91,7 +91,6 @@ set(MOCKS
eeprom-board-mock.cpp
# loramac-mock.cpp
systime-mock.cpp
- ublox-mock.cpp
nvm_images.cpp
gps_mock_utils.cpp
delay-board-mock.c
diff --git a/tests/ublox-mock.cpp b/tests/ublox-mock.cpp
deleted file mode 100644
index 88fa44e67..000000000
--- a/tests/ublox-mock.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#include "CppUTestExt/MockSupport.h"
-
-extern "C"
-{
-#include "ublox.h"
-}
-
-
-
-gps_status_t get_location_fix(uint32_t timeout)
-{
- return GPS_SUCCESS;
-}
-
-/*
- * sets up gps by putting in airbourne mode, setting to use GPS satellites only, turning off NMEA
- * Needs TO BE REFACTORED TO TIME OUT OR EXIT IF NO MESSAGED IS ReCEIVED BACK!
- */
-gps_status_t setup_GPS()
-{
- return GPS_SUCCESS;
-}
-
-/* Get solar voltage when under load from GPS */
-uint16_t get_load_solar_voltage()
-{
- return 2323;
-}
-
-gps_info_t get_latest_gps_info()
-{
- auto returnValue = mock().actualCall(__func__).returnPointerValue();
- return *(gps_info_t *)(returnValue);
-}
-
-gps_status_t get_latest_gps_status(void)
-{
- return GPS_SUCCESS;
-}
\ No newline at end of file