diff --git a/boards/OpenIMU335.json b/boards/OpenIMU335.json
new file mode 100644
index 0000000..0ffff79
--- /dev/null
+++ b/boards/OpenIMU335.json
@@ -0,0 +1,38 @@
+{
+ "build": {
+ "core": "stm32",
+ "cpu": "cortex-m4",
+ "extra_flags": [
+ "-mcpu=cortex-m4",
+ "-mfloat-abi=softfp",
+ "-mfpu=fpv4-sp-d16",
+ "-DSTM32F4",
+ "-DSTM32F405RG",
+ "-DSTM32F405xx"
+ ],
+ "ldscript": "stm32f40x.ld",
+ "f_cpu": "120000000L",
+ "mcu": "stm32f405rg"
+ },
+ "debug": {
+ "default_tools": ["stlink"],
+ "openocd_target": "stm32f4x",
+ "jlink_device": "STM32F405RG",
+ "svd_path": "STM32F40x.svd"
+ },
+ "frameworks": [],
+ "name": "Aceinna MTLT335",
+ "upload": {
+ "offset_address": "0x08010000",
+ "maximum_ram_size": 131072,
+ "maximum_size": 1048576,
+ "protocols": [
+ "blackmagic",
+ "stlink",
+ "jlink"
+ ],
+ "protocol": "stlink"
+ },
+ "url": "https://www.aceinna.com/inertial-systems/",
+ "vendor": "Aceinna"
+}
diff --git a/examples/OpenIMU335RI/VG/.gitignore b/examples/OpenIMU335RI/VG/.gitignore
new file mode 100644
index 0000000..f53cace
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/.gitignore
@@ -0,0 +1,9 @@
+.pio/**
+.pio/libdeps/**
+.vscode/**
+.pioenvs/**
+.piolibdeps/**
+*.map
+.settings
+.cproject
+.project
diff --git a/examples/OpenIMU335RI/VG/.travis.yml b/examples/OpenIMU335RI/VG/.travis.yml
new file mode 100644
index 0000000..52072ef
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/.travis.yml
@@ -0,0 +1,55 @@
+# Continuous Integration (CI) is the practice, in software
+# engineering, of merging all developer working copies with a shared mainline
+# several times a day < http://docs.platformio.org/page/ci/index.html >
+#
+# Documentation:
+#
+# * Travis CI Embedded Builds with PlatformIO
+# < https://docs.travis-ci.com/user/integration/platformio/ >
+#
+# * PlatformIO integration with Travis CI
+# < http://docs.platformio.org/page/ci/travis.html >
+#
+# * User Guide for `platformio ci` command
+# < http://docs.platformio.org/page/userguide/cmd_ci.html >
+#
+#
+# Please choice one of the following templates (proposed below) and uncomment
+# it (remove "# " before each line) or use own configuration according to the
+# Travis CI documentation (see above).
+#
+
+
+#
+# Template #1: General project. Test it using existing `platformio.ini`.
+#
+
+# language: python
+# python:
+# - "2.7"
+#
+# install:
+# - pip install -U platformio
+#
+# script:
+# - platformio run
+
+
+#
+# Template #2: The project is intended to by used as a library with examples
+#
+
+# language: python
+# python:
+# - "2.7"
+#
+# env:
+# - PLATFORMIO_CI_SRC=path/to/test/file.c
+# - PLATFORMIO_CI_SRC=examples/file.ino
+# - PLATFORMIO_CI_SRC=path/to/test/directory
+#
+# install:
+# - pip install -U platformio
+#
+# script:
+# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N
diff --git a/examples/OpenIMU335RI/VG/boards/OpenIMU335.json b/examples/OpenIMU335RI/VG/boards/OpenIMU335.json
new file mode 100644
index 0000000..0ffff79
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/boards/OpenIMU335.json
@@ -0,0 +1,38 @@
+{
+ "build": {
+ "core": "stm32",
+ "cpu": "cortex-m4",
+ "extra_flags": [
+ "-mcpu=cortex-m4",
+ "-mfloat-abi=softfp",
+ "-mfpu=fpv4-sp-d16",
+ "-DSTM32F4",
+ "-DSTM32F405RG",
+ "-DSTM32F405xx"
+ ],
+ "ldscript": "stm32f40x.ld",
+ "f_cpu": "120000000L",
+ "mcu": "stm32f405rg"
+ },
+ "debug": {
+ "default_tools": ["stlink"],
+ "openocd_target": "stm32f4x",
+ "jlink_device": "STM32F405RG",
+ "svd_path": "STM32F40x.svd"
+ },
+ "frameworks": [],
+ "name": "Aceinna MTLT335",
+ "upload": {
+ "offset_address": "0x08010000",
+ "maximum_ram_size": 131072,
+ "maximum_size": 1048576,
+ "protocols": [
+ "blackmagic",
+ "stlink",
+ "jlink"
+ ],
+ "protocol": "stlink"
+ },
+ "url": "https://www.aceinna.com/inertial-systems/",
+ "vendor": "Aceinna"
+}
diff --git a/examples/OpenIMU335RI/VG/boards/stm32f40x.ld b/examples/OpenIMU335RI/VG/boards/stm32f40x.ld
new file mode 100644
index 0000000..1c0c9f6
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/boards/stm32f40x.ld
@@ -0,0 +1,202 @@
+/*
+*****************************************************************************
+**
+
+** File : LinkerScript.ld
+**
+** Abstract : Linker script for STM32F405RGx Device with
+** 1024KByte FLASH, 128KByte RAM
+**
+** Set heap size, stack size and stack location according
+** to application requirements.
+**
+** Set memory bank area and size if external memory is used.
+**
+** Target : STMicroelectronics STM32
+**
+**
+** Distribution: The file is distributed as is, without any warranty
+** of any kind.
+**
+*****************************************************************************
+** @attention
+**
+**
© COPYRIGHT(c) 2014 Ac6
+**
+** Redistribution and use in source and binary forms, with or without modification,
+** are permitted provided that the following conditions are met:
+** 1. Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+** 3. Neither the name of Ac6 nor the names of its contributors
+** may be used to endorse or promote products derived from this software
+** without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************************
+*/
+
+/* Entry Point */
+ENTRY(Reset_Handler)
+
+/* Highest address of the user mode stack */
+_estack = 0x2001ff00; /* end of RAM */
+/* Generate a link error if heap and stack don't fit into RAM */
+_Min_Heap_Size = 0x2000; /* required amount of heap */
+_Min_Stack_Size = 0x2000; /* required amount of stack */
+
+/* Specify the memory areas */
+MEMORY
+{
+FLASH (rx) : ORIGIN = 0x08010000, LENGTH = 448K
+EEPROM (rw) : ORIGIN = 0x08008000, LENGTH = 16K
+USER_EEPROM(rw) : ORIGIN = 0x0800C000, LENGTH = 16K
+RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
+}
+
+/* Define output sections */
+SECTIONS
+{
+ /* The startup code goes first into FLASH */
+ .isr_vector :
+ {
+ . = ALIGN(4);
+ KEEP(*(.isr_vector)) /* Startup code */
+ . = ALIGN(4);
+ } >FLASH
+
+ /* The program code and other data goes into FLASH */
+ .text :
+ {
+ . = ALIGN(4);
+ *(.text) /* .text sections (code) */
+ *(.text*) /* .text* sections (code) */
+ *(.glue_7) /* glue arm to thumb code */
+ *(.glue_7t) /* glue thumb to arm code */
+ *(.eh_frame)
+
+ KEEP (*(.init))
+ KEEP (*(.fini))
+
+ . = ALIGN(4);
+ _etext = .; /* define a global symbols at end of code */
+ } >FLASH
+
+ /* Constant data goes into FLASH */
+ .rodata :
+ {
+ . = ALIGN(4);
+ *(.rodata) /* .rodata sections (constants, strings, etc.) */
+ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
+ . = ALIGN(4);
+ } >FLASH
+
+ .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
+ .ARM : {
+ __exidx_start = .;
+ *(.ARM.exidx*)
+ __exidx_end = .;
+ } >FLASH
+
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array*))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ } >FLASH
+ .init_array :
+ {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array*))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ } >FLASH
+ .fini_array :
+ {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(SORT(.fini_array.*)))
+ KEEP (*(.fini_array*))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ } >FLASH
+
+ /* used by the startup to initialize data */
+ _sidata = LOADADDR(.data);
+
+ /* Initialized data sections goes into RAM, load LMA copy after code */
+ .data :
+ {
+ . = ALIGN(4);
+ _sdata = .; /* create a global symbol at data start */
+ *(.data) /* .data sections */
+ *(.data*) /* .data* sections */
+
+ . = ALIGN(4);
+ _edata = .; /* define a global symbol at data end */
+ } >RAM AT> FLASH
+
+
+ /* Uninitialized data section */
+ . = ALIGN(4);
+ .bss :
+ {
+ /* This is used by the startup in order to initialize the .bss secion */
+ _sbss = .; /* define a global symbol at bss start */
+ __bss_start__ = _sbss;
+ *(.bss)
+ *(.bss*)
+ *(COMMON)
+
+ . = ALIGN(4);
+ _ebss = .; /* define a global symbol at bss end */
+ __bss_end__ = _ebss;
+ } >RAM
+
+ /* User_heap_stack section, used to check that there is enough RAM left */
+ ._user_heap_stack :
+ {
+ . = ALIGN(8);
+ PROVIDE ( end = . );
+ PROVIDE ( _end = . );
+ . = . + _Min_Heap_Size;
+ . = . + _Min_Stack_Size;
+ . = ALIGN(8);
+ } >RAM
+
+ .eeprom 0x08008000:
+ {
+ . = ALIGN(4);
+ KEEP(*(.xbowEeprom)) /* keep my variable even if not referenced */
+ . = ALIGN(4);
+ _eeeprom = .; /* define a global symbols at end of code */
+ } >EEPROM
+
+ .usereeprom 0x0800C000:
+ {
+ . = ALIGN(4);
+ KEEP(*(.userEeprom)) /* keep my variable even if not referenced */
+ . = ALIGN(4);
+ _eusereeprom = .; /* define a global symbols at end of code */
+ } >USER_EEPROM
+
+ /* Remove information from the standard libraries */
+ /DISCARD/ :
+ {
+ libc.a ( * )
+ libm.a ( * )
+ libgcc.a ( * )
+ }
+
+ .ARM.attributes 0 : { *(.ARM.attributes) }
+}
diff --git a/examples/OpenIMU335RI/VG/lib/UARTComm/CommonMessages.c b/examples/OpenIMU335RI/VG/lib/UARTComm/CommonMessages.c
new file mode 100644
index 0000000..71e4afc
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/lib/UARTComm/CommonMessages.c
@@ -0,0 +1,464 @@
+/** ***************************************************************************
+ * @file UARTMessages.c
+ *
+ * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ ******************************************************************************/
+/*******************************************************************************
+Copyright 2018 ACEINNA, INC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*******************************************************************************/
+
+#include
+#include
+#include
+
+#include "algorithmAPI.h"
+#include "calibrationAPI.h"
+#include "sensorsAPI.h"
+#include "appVersion.h"
+
+#include "CommonMessages.h"
+#include "indices.h"
+
+#include "ekfAPI.h"
+#include "halAPI.h"
+#include "partNumber.h"
+#include "aceinna_sae_j1939.h"
+
+extern BOOL odoUpdate;
+/******************************************************************************
+ * @name FillPingPacketPayload - API call ro prepare user output packet
+ * @brief general handler
+ * @param [in] payload pointer to put user data to
+ * @param [in/out] number of bytes in user payload
+ * @retval N/A
+ ******************************************************************************/
+BOOL Fill_PingPacketPayload(uint8_t *payload, uint8_t *payloadLen)
+{
+ int len;
+ uint8_t *model = cal_GetUnitVersion();
+ unsigned int serialNum = cal_GetUnitSerialNum();
+ len = snprintf((char*)payload, 250, "%s %s %s SN:%u", model, PART_NUMBER_STRING, APP_VERSION_STRING, serialNum );
+ *payloadLen = len;
+ return TRUE;
+}
+
+/******************************************************************************
+ * @name FillVersionPacketPayload - API call ro prepare user output packet
+ * @brief general handler
+ * @param [in] payload pointer to put user data to
+ * @param [in/out] number of bytes in user payload
+ * @retval N/A
+ ******************************************************************************/
+BOOL Fill_VersionPacketPayload(uint8_t *payload, uint8_t *payloadLen)
+{
+ int len = snprintf((char*)payload, 250, "%s %s", APP_NAME_STRING, APP_VERSION_STRING);
+ *payloadLen = len;
+ return TRUE;
+}
+
+/******************************************************************************
+ * @name FillTestPacketPayload - API call ro prepare user output packet
+ * @brief general handler
+ * @param [in] payload pointer to put user data to
+ * @param [in/out] number of bytes in user payload
+ * @retval N/A
+ ******************************************************************************/
+BOOL Fill_zTPacketPayload(uint8_t *payload, uint8_t *payloadLen)
+{
+ static uint32_t _testVal = 0;
+ test_payload_t* pld = (test_payload_t*)payload;
+ pld->counter = _testVal++;
+ *payloadLen = sizeof(test_payload_t);
+ return TRUE;
+}
+
+/******************************************************************************
+ * @name FillTestPacketPayloadt - API call ro prepare user output packet
+ * @brief general handler
+ * @param [in] payload pointer to put user data to
+ * @param [in/out] number of bytes in user payload
+ * @retval N/A
+ ******************************************************************************/
+BOOL Fill_z1PacketPayload(uint8_t *payload, uint8_t *payloadLen)
+{
+ uint64_t tstamp;
+ double accels[NUM_AXIS];
+ double rates[NUM_AXIS];
+
+ data1_payload_t *pld = (data1_payload_t *)payload;
+
+// tstamp = platformGetDacqTimeStamp(); // time stamp of last sensor sample in microseconds from system start
+ tstamp = TIMER_GetCurrTimeStamp(); // current time stamp in microseconds from system start
+// tstamp /= 1000; // convert to miliseconds
+// timer = getSystemTime(); // OS timer value (tick defined in FreeRTOSConfig.h)
+ pld->timer = tstamp;
+ sens_GetAccelData_mPerSecSq(accels);
+ sens_GetRateData_degPerSec(rates);
+
+ for (int i = 0; i < NUM_AXIS; i++){
+ pld->accel_mpss[i] = (float)accels[i];
+ pld->rate_dps[i] = (float)rates[i];
+ pld->mag_G[i] = 0.0F;
+ }
+
+ *payloadLen = sizeof(data1_payload_t);
+ return TRUE;
+}
+
+
+/******************************************************************************
+ * @name FillTestPacketPayloadt - API call ro prepare user output packet
+ * @brief general handler
+ * @param [in] payload pointer to put user data to
+ * @param [in/out] number of bytes in user payload
+ * @retval N/A
+ ******************************************************************************/
+BOOL Fill_a1PacketPayload(uint8_t *payload, uint8_t *payloadLen)
+{
+ angle1_payload_t* pld = (angle1_payload_t*)payload;
+
+ // Variables used to hold the EKF values
+ real EulerAngles[NUM_AXIS];
+ real CorrRates_B[NUM_AXIS];
+ double accels[NUM_AXIS];
+ // Diagnostic flags
+ uint8_t OperMode, LinAccelSwitch, TurnSwitch;
+
+ EKF_GetAttitude_EA(EulerAngles);
+ EKF_GetCorrectedAngRates(CorrRates_B);
+ sens_GetAccelData_mPerSecSq(accels);
+ EKF_GetOperationalMode(&OperMode);
+ EKF_GetOperationalSwitches(&LinAccelSwitch, &TurnSwitch);
+
+ pld->itow = TIMER_GetCurrTimeStamp()/1000;
+ pld->dblItow = 1.0e-3 * pld->itow;
+ pld->roll = (float)EulerAngles[ROLL];
+ pld->pitch = (float)EulerAngles[PITCH];
+ pld->ekfOpMode = OperMode;
+ pld->accelLinSwitch = LinAccelSwitch;
+ pld->turnSwitch = TurnSwitch;
+
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->corrRates[i] = (float)CorrRates_B[i];
+ pld->accels[i] = (float)accels[i];
+ }
+
+ *payloadLen = sizeof(angle1_payload_t);
+
+ return TRUE;
+}
+
+/******************************************************************************
+ * @name FillTestPacketPayloadt - API call ro prepare user output packet
+ * @brief general handler
+ * @param [in] payload pointer to put user data to
+ * @param [in/out] number of bytes in user payload
+ * @retval N/A
+ ******************************************************************************/
+BOOL Fill_a2PacketPayload(uint8_t *payload, uint8_t *payloadLen)
+{
+ angle2_payload_t* pld = (angle2_payload_t*)payload;
+
+ // Variables used to hold the EKF values
+ real EulerAngles[NUM_AXIS];
+ real CorrRates_B[NUM_AXIS];
+ double accels[NUM_AXIS];
+
+ EKF_GetAttitude_EA(EulerAngles);
+ EKF_GetCorrectedAngRates(CorrRates_B);
+ sens_GetAccelData_mPerSecSq(accels);
+
+ pld->itow = TIMER_GetCurrTimeStamp()/1000;
+ pld->dblItow = 1.0e-3 * pld->itow;
+ pld->roll = (float)EulerAngles[ROLL];
+ pld->pitch = (float)EulerAngles[PITCH];
+ pld->yaw = (float)EulerAngles[YAW];
+
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->corrRates[i] = (float)CorrRates_B[i];
+ pld->accels[i] = (float)accels[i];
+ }
+
+ *payloadLen = sizeof(angle2_payload_t);
+
+ return TRUE;
+}
+
+/******************************************************************************
+ * @name Fills1PacketPayloadt - API call ro prepare user output packet
+ * @brief general handler
+ * @param [in] payload pointer to put user data to
+ * @param [in/out] number of bytes in user payload
+ * @retval N/A
+ ******************************************************************************/
+BOOL Fill_s1PacketPayload(uint8_t *payload, uint8_t *payloadLen)
+{
+ double accels[NUM_AXIS];
+ double mags[NUM_AXIS];
+ double rates[NUM_AXIS];
+ double temp;
+ scaled1_payload_t *pld = (scaled1_payload_t *)payload;
+ *payloadLen = sizeof(scaled1_payload_t);
+
+ sens_GetAccelData_mPerSecSq(accels);
+ sens_GetRateData_degPerSec(rates);
+ sens_GetMagData_G(mags);
+ sens_GetBoardTempData(&temp);
+
+ pld->tstmp = TIMER_GetCurrTimeStamp()/1000; // miliseconds
+ pld->dbTstmp = (double)pld->tstmp/1000; // seconds
+
+ for (int i = 0; i < NUM_AXIS; i++){
+ pld->accel_g[i] = (float)accels[i];
+ pld->rate_dps[i] = (float)rates[i];
+ pld->mag_G[i] = (float)mags[i];
+ }
+
+ pld->temp_C = (float)temp;
+
+ return TRUE;
+}
+
+/******************************************************************************
+ * @name Fille1PacketPayloadt - API call ro prepare user output packet - EKF data 1
+ * @brief general handler
+ * @param [in] payload pointer to put user data to
+ * @param [in/out] number of bytes in user payload
+ * @retval N/A
+ ******************************************************************************/
+BOOL Fill_e1PacketPayload(uint8_t *payload, uint8_t *payloadLen)
+{
+ // Variables used to hold the EKF values
+ uint8_t opMode, linAccelSw, turnSw;
+ double data[NUM_AXIS];
+ real EulerAngles[NUM_AXIS];
+
+ ekf1_payload_t *pld = (ekf1_payload_t *)payload;
+
+ *payloadLen = sizeof(ekf1_payload_t);
+ pld->tstmp = TIMER_GetCurrTimeStamp()/1000; // milliseconds
+ pld->dbTstmp = (double)TIMER_GetCurrTimeStamp()/1000000; // seconds
+
+ EKF_GetAttitude_EA(EulerAngles);
+ pld->roll = (float)EulerAngles[ROLL];
+ pld->pitch = (float)EulerAngles[PITCH];
+ pld->yaw = (float)EulerAngles[YAW];
+
+ sens_GetAccelData_g(data);
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->accels_g[i] = (float)data[i];
+ }
+
+ sens_GetRateData_degPerSec(data);
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->rates_dps[i] = data[i];
+ }
+
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->mags[i] = 0.0F;
+ }
+
+ float rateBias[NUM_AXIS];
+ EKF_GetEstimatedAngRateBias(rateBias);
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->rateBias[i] = (float)rateBias[i];
+ }
+
+ EKF_GetOperationalMode(&opMode);
+ EKF_GetOperationalSwitches(&linAccelSw, &turnSw);
+ pld->opMode = opMode;
+ pld->accelLinSwitch = linAccelSw;
+ pld->turnSwitch = turnSw;
+ return TRUE;
+}
+
+/******************************************************************************
+ * @name Fille2PacketPayloadt - API call ro prepare user output packet
+ * @brief general handler
+ * @param [in] payload pointer to put user data to
+ * @param [in/out] number of bytes in user payload
+ * @retval N/A
+ ******************************************************************************/
+BOOL Fill_e2PacketPayload(uint8_t *payload, uint8_t *payloadLen)
+{
+ float fData[3];
+ real rData[3];
+ double dData[3];
+
+ ekf2_payload_t *pld = (ekf2_payload_t *)payload;
+
+ *payloadLen = sizeof(ekf2_payload_t);
+ pld->tstmp = TIMER_GetCurrTimeStamp()/1000; // milliseconds
+ pld->dbTstmp = (double)TIMER_GetCurrTimeStamp()/1000000; // seconds
+
+ EKF_GetAttitude_EA(rData);
+ pld->roll = (float)rData[ROLL];
+ pld->pitch = (float)rData[PITCH];
+ pld->yaw = (float)rData[YAW];
+
+ sens_GetAccelData_g(dData);
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->accels_g[i] = (float)dData[i];
+ }
+
+ EKF_GetEstimatedAccelBias(fData);
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->accelBias[i] = fData[i];
+ }
+
+ sens_GetRateData_degPerSec(dData);
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->rates_dps[i] = (float)dData[i];
+ }
+
+ EKF_GetEstimatedAngRateBias(fData);
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->rateBias[i] = fData[i];
+ }
+
+
+ EKF_GetEstimatedVelocity(fData);
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->velocity[i] = fData[i];
+ }
+
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->mags[i] = 0.0F;
+ }
+
+ EKF_GetEstimatedLLA(dData);
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->pos[i] = dData[i];
+ }
+
+ uint8_t opMode, linAccelSw, turnSw;
+ EKF_GetOperationalMode(&opMode);
+ EKF_GetOperationalSwitches(&linAccelSw, &turnSw);
+
+ pld->opMode = opMode;
+ pld->accelLinSwitch = linAccelSw;
+ pld->turnSwitch = turnSw;
+
+ return TRUE;
+}
+
+/******************************************************************************
+ * @name Filld1PacketPayload - API call ro prepare user output packet - Aiding Signal Information 1
+ * @brief general handler
+ * @param [in] payload pointer to put user data to
+ * @param [in/out] number of bytes in user payload
+ * @retval N/A
+ ******************************************************************************/
+BOOL Fill_d1PacketPayload(uint8_t *payload, uint8_t *payloadLen)
+{
+ // Variables used to hold the EKF values
+ double data[NUM_AXIS];
+ real EulerAngles[NUM_AXIS];
+
+ aid1_payload_t *pld = (aid1_payload_t *)payload;
+
+ *payloadLen = sizeof(aid1_payload_t);
+
+ odoDataStruct_t* odo = GetOdometerPtr();
+ pld->update = odoUpdate;
+ odoUpdate = FALSE;
+ pld->v = odo->v;
+
+ EKF_GetAttitude_EA(EulerAngles);
+ pld->roll = (float)EulerAngles[ROLL];
+ pld->pitch = (float)EulerAngles[PITCH];
+
+ sens_GetAccelData_g(data);
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->accels[i] = (float)data[i];
+ }
+
+ sens_GetRateData_degPerSec(data);
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->rates[i] = data[i];
+ }
+
+ pld->itow = TIMER_GetCurrTimeStamp()/1000;
+ pld->dblItow = 1.0e-3 * pld->itow;
+ return TRUE;
+}
+
+/******************************************************************************
+ * @name Filld2PacketPayload - API call ro prepare user output packet - Aiding Signal Information 2
+ * @brief general handler
+ * @param [in] payload pointer to put user data to
+ * @param [in/out] number of bytes in user payload
+ * @retval N/A
+ ******************************************************************************/
+BOOL Fill_d2PacketPayload(uint8_t *payload, uint8_t *payloadLen)
+{
+ // Variables used to hold the EKF values
+ double data[NUM_AXIS];
+ real EulerAngles[NUM_AXIS];
+
+ aid2_payload_t *pld = (aid2_payload_t *)payload;
+
+ *payloadLen = sizeof(aid2_payload_t);
+
+ odoDataStruct_t* odo = GetOdometerPtr();
+ pld->update = odoUpdate;
+ odoUpdate = FALSE;
+ memcpy(pld->vehAccel,odo->vehAccel,sizeof(real)*3);
+
+ EKF_GetAttitude_EA(EulerAngles);
+ pld->roll = (float)EulerAngles[ROLL];
+ pld->pitch = (float)EulerAngles[PITCH];
+
+ sens_GetAccelData_g(data);
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->accels[i] = (float)data[i];
+ }
+
+ sens_GetRateData_degPerSec(data);
+ for(int i = 0; i < NUM_AXIS; i++){
+ pld->rates[i] = data[i];
+ }
+
+ pld->itow = TIMER_GetCurrTimeStamp()/1000;
+ pld->dblItow = 1.0e-3 * pld->itow;
+ return TRUE;
+}
+extern EcuConfigurationStruct *gEcuConfigPtr;
+/******************************************************************************
+ * @name Filld3PacketPayload - API call ro prepare user output packet - Aiding Signal Information 3
+ * @brief general handler
+ * @param [in] payload pointer to put user data to
+ * @param [in/out] number of bytes in user payload
+ * @retval N/A
+ ******************************************************************************/
+BOOL Fill_d3PacketPayload(uint8_t *payload, uint8_t *payloadLen)
+{
+ aid3_payload_t *pld = (aid3_payload_t *)payload;
+
+ *payloadLen = sizeof(aid3_payload_t);
+
+ OdoCfgStruct_t*odoCfg = GetOdometerCfgPtr();
+ pld->aidingSigSrcType = odoCfg->signalSource;
+ pld->aidingSigPGN = ((gEcuConfigPtr->aidingPF << 8) | (gEcuConfigPtr->aidingPS));
+ pld->odoCfgSwitch = odoCfg->odoCfgSwitch;
+ pld->msgRate = odoCfg->msgRate;
+ pld->transSigPGN = ((gEcuConfigPtr->drivingDirPF << 8)|(gEcuConfigPtr->drivingDirPS));
+ memcpy(pld->leverarmB, odoCfg->leverArmB, 3 * sizeof(real));
+ return TRUE;
+}
\ No newline at end of file
diff --git a/examples/OpenIMU335RI/VG/lib/UARTComm/CommonMessages.h b/examples/OpenIMU335RI/VG/lib/UARTComm/CommonMessages.h
new file mode 100644
index 0000000..d21c68c
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/lib/UARTComm/CommonMessages.h
@@ -0,0 +1,160 @@
+/** ***************************************************************************
+ * @file UARTMessages.h
+ *
+ * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ ******************************************************************************/
+/*******************************************************************************
+Copyright 2018 ACEINNA, INC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*******************************************************************************/
+#ifndef _UART_MESSAGES_H
+#define _UART_MESSAGES_H
+#include
+
+#pragma pack(1)
+
+// payload structure of standard IMU data message
+typedef struct {
+ uint32_t timer;
+ float accel_mpss[3];
+ float rate_dps[3];
+ float mag_G[3];
+}data1_payload_t;
+
+// payload structure of standard test message
+typedef struct {
+ uint32_t counter;
+}test_payload_t;
+
+// payload structure of standard unit attitude message
+typedef struct {
+ uint32_t itow;
+ double dblItow;
+ float roll;
+ float pitch;
+ float corrRates[3];
+ float accels[3];
+ uint8_t ekfOpMode;
+ uint8_t accelLinSwitch;
+ uint8_t turnSwitch;
+}angle1_payload_t;
+
+// payload structure of alternative IMU data message
+typedef struct {
+ uint32_t tstmp;
+ double dbTstmp;
+ float accel_g[3];
+ float rate_dps[3];
+ float mag_G[3];
+ float temp_C;
+}scaled1_payload_t;
+
+// payload structure of standard EKF message
+typedef struct {
+ uint32_t tstmp;
+ double dbTstmp;
+ float roll;
+ float pitch;
+ float yaw;
+ float accels_g[3];
+ float rates_dps[3];
+ float rateBias[3];
+ float mags[3];
+ uint8_t opMode;
+ uint8_t accelLinSwitch;
+ uint8_t turnSwitch;
+}ekf1_payload_t;
+
+// payload structure of enchanced EKF message
+typedef struct {
+ uint32_t tstmp;
+ double dbTstmp;
+ float roll;
+ float pitch;
+ float yaw;
+ float accels_g[3];
+ float accelBias[3];
+ float rates_dps[3];
+ float rateBias[3];
+ float velocity[3];
+ float mags[3];
+ double pos[3];
+ uint8_t opMode;
+ uint8_t accelLinSwitch;
+ uint8_t turnSwitch;
+}ekf2_payload_t;
+
+// payload structure of standard unit attitude message
+typedef struct {
+ uint32_t itow;
+ double dblItow;
+ float roll;
+ float pitch;
+ float yaw;
+ float corrRates[3];
+ float accels[3];
+}angle2_payload_t;
+
+
+typedef struct {
+ uint32_t itow;
+ double dblItow;
+ float roll;
+ float pitch;
+ float rates[3];
+ float accels[3];
+ float v;
+ BOOL update;
+}aid1_payload_t;
+
+typedef struct {
+ uint32_t itow;
+ double dblItow;
+ float rates[3];
+ float accels[3];
+ float roll;
+ float pitch;
+ float vehAccel[3];
+ BOOL update;
+}aid2_payload_t;
+
+typedef struct {
+ uint8_t aidingSigSrcType;
+ uint8_t msgRate;
+ uint16_t aidingSigPGN;
+ uint16_t transSigPGN;
+ uint8_t odoCfgSwitch;
+ float leverarmB[3];
+}aid3_payload_t;
+
+#pragma pack()
+
+BOOL Fill_PingPacketPayload(uint8_t *payload, uint8_t *payloadLen);
+BOOL Fill_VersionPacketPayload(uint8_t *payload, uint8_t *payloadLen);
+BOOL Fill_zTPacketPayload(uint8_t *payload, uint8_t *payloadLen);
+BOOL Fill_z1PacketPayload(uint8_t *payload, uint8_t *payloadLen);
+BOOL Fill_a1PacketPayload(uint8_t *payload, uint8_t *payloadLen);
+BOOL Fill_a2PacketPayload(uint8_t *payload, uint8_t *payloadLen);
+BOOL Fill_s1PacketPayload(uint8_t *payload, uint8_t *payloadLen);
+BOOL Fill_e1PacketPayload(uint8_t *payload, uint8_t *payloadLen);
+BOOL Fill_e2PacketPayload(uint8_t *payload, uint8_t *payloadLen);
+BOOL Fill_d1PacketPayload(uint8_t *payload, uint8_t *payloadLen);
+BOOL Fill_d2PacketPayload(uint8_t *payload, uint8_t *payloadLen);
+BOOL Fill_d3PacketPayload(uint8_t *payload, uint8_t *payloadLen);
+
+#endif
diff --git a/examples/OpenIMU335RI/VG/platformio.ini b/examples/OpenIMU335RI/VG/platformio.ini
new file mode 100644
index 0000000..4091297
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/platformio.ini
@@ -0,0 +1,43 @@
+; PlatformIO Project Configuration File
+;
+; Build options: build flags, source filter
+; Upload options: custom upload port, speed and extra flags
+; Library options: dependencies, extra library storages
+; Advanced options: extra scripting
+;
+; Please visit documentation for the other options and examples
+; http://docs.platformio.org/page/projectconf.html
+
+[env:OpenIMU335]
+platform = aceinna_imu
+board = OpenIMU335
+lib_archive = false
+;lib_deps=../../../openIMU335-lib
+lib_deps = OpenIMU335-base-library@1.1.13
+build_flags =
+ -D SAE_J1939
+ -D CAN_BUS_COMM
+ -D __FPU_PRESENT
+ -D ARM_MATH_CM4
+ -D USE_ALGORITHM
+; -D HSE_VALUE=24806000
+; -D DEBUG_ENABLED
+ -D MTLT335_V2
+ -D BOOT_PROCEED_FROM_BOOTLOADER=1
+ -D float32_t=float
+ -D float64_t=double
+; -D nullptr=NULL
+ -I .
+ -I include
+ -I src/user
+ -I lib/Serial
+ -I lib/Serial/include
+ -I lib/CAN_J1939
+ -I lib/CAN_J1939/include
+ -I src
+ -Og
+; -Wno-comment
+; -Wl,-Map,imu.map
+; -Wl,-Tstm32f40x.ld
+ -mthumb -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16
+
diff --git a/examples/OpenIMU335RI/VG/src/appVersion.h b/examples/OpenIMU335RI/VG/src/appVersion.h
new file mode 100644
index 0000000..52be3fe
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/appVersion.h
@@ -0,0 +1,16 @@
+/*****************************************************************************
+ * @file app_version.h
+ *
+ * @brief Application version information.
+ ******************************************************************************/
+#ifndef APP_VERSION_H
+#define APP_VERSION_H
+
+#include
+
+static int8_t const APP_NAME_STRING[] = "OpenIMU335RI VG";
+
+// WARNING !!! Leave space before 07 in APP_VERSION_STRING
+// Change only digits in APP_VERSION_STRING. Keep Existing format!!!!
+static int8_t const APP_VERSION_STRING[] = " 07.04.00";
+#endif
diff --git a/examples/OpenIMU335RI/VG/src/main.c b/examples/OpenIMU335RI/VG/src/main.c
new file mode 100644
index 0000000..ac09d8c
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/main.c
@@ -0,0 +1,46 @@
+#include "configurationAPI.h"
+#include "calibrationAPI.h"
+#include "taskDataAcquisition.h"
+#include "EcuSettings.h"
+#include "halAPI.h"
+#include "sensorsAPI.h"
+#include "osapi.h"
+#include "bitAPI.h"
+
+#ifndef UNIT_TEST
+/**********************************************
+* @brief
+*
+* @return int
+***********************************************/
+int main(void)
+{
+
+ uint32_t rate;
+ uint16_t chipMask;
+
+ BIT_Iinitialize();
+ ApplyFactoryConfiguration();
+ HW_Init();
+ cal_Init();
+ LoadEcuSettings();
+ BIT_UpdateConfiguredSensorChips();
+
+ OS_StartTimers(1000U);
+
+ sens_Init(&chipMask);
+ chipMask = (uint16_t)~chipMask & 0x07U;
+ BIT_UpdateSensorSelfTestStatus((uint8_t)chipMask);
+
+ rate = (uint32_t)config_GetBaudRate();
+ UART_Init(USER_SERIAL_PORT, rate);
+
+ TaskDataAcquisition();
+
+ // should never return here
+ while(rate){};
+
+ return 1;
+}
+
+#endif //UNIT_TEST
\ No newline at end of file
diff --git a/examples/OpenIMU335RI/VG/src/taskDataAcquisition.c b/examples/OpenIMU335RI/VG/src/taskDataAcquisition.c
new file mode 100644
index 0000000..e7d3625
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/taskDataAcquisition.c
@@ -0,0 +1,101 @@
+/*****************************************************************************
+ * @file taskDataAcquisition.c
+ *
+ * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ * sensor data acquisition task runs at 100Hz, gets the data for each sensor
+ * and applies available calibration
+ ******************************************************************************/
+/*******************************************************************************
+Copyright 2018 ACEINNA, INC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*******************************************************************************/
+
+
+#include "taskDataAcquisition.h"
+#include "osapi.h"
+#include "userAPI.h"
+#include "sensorsAPI.h"
+#include "calibrationAPI.h"
+#include "serialAPI.h"
+#include "halAPI.h"
+#include "bitAPI.h"
+#include "canJ1939API.h"
+#include "EcuSettings.h"
+
+/** ***************************************************************************
+ * @name TaskDataAcquisition() CALLBACK main loop
+ * @brief Get the sensor data at the specified frequency (based on the
+ * configuration of the accelerometer rate-sensor). Process and provide
+ * information to the user via the UART or SPI.
+ * @param N/A
+ *
+ ******************************************************************************/
+void TaskDataAcquisition()
+{
+ sens_InitDataStructures();
+ initUserDataProcessingEngine();
+
+ BIT_BegintPowerCheck();
+
+ while( 1 )
+ {
+
+
+ if(BIT_NeedResetFifo()){
+ BOOL const res = sens_ResetFifo();
+ if(res == TRUE){
+ BIT_ClearFifoResetEvents();
+ }
+ }
+
+ BIT_PerformPeriodicTest();
+
+ if(OS_IsDacqOverrun()){
+ BIT_DacqOverrun(TRUE);
+ }else{
+ BIT_DacqOverrun(FALSE);
+ }
+
+
+ OS_WaitForDacqTick();
+ HW_TP1_On();
+
+ TIMER_DacqStarted();
+
+ BIT_UpdateDaqCycleStartFlag();
+ HW_FeedWatchdog();
+
+ sens_SampleData();
+ cal_Apply();
+
+ // *****************************************************************
+ // At this point sensors data is in next units
+ // Acceleration - g's
+ // Rates - rad/s
+ //******************************************************************
+ inertialAndPositionDataProcessing(200);
+ HW_TP1_Off();
+
+ // Process commands and output continuous packets to UART
+ // Processing of user commands always goes first
+ ProcessUserCommands ();
+ SendContinuousPacket(200);
+ ProcessCANMessages();
+ UpdateEcuSettings();
+ }
+}
diff --git a/examples/OpenIMU335RI/VG/src/taskDataAcquisition.h b/examples/OpenIMU335RI/VG/src/taskDataAcquisition.h
new file mode 100644
index 0000000..11fa1ac
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/taskDataAcquisition.h
@@ -0,0 +1,7 @@
+
+#ifndef DACQ_TASK
+#define DACQ_TASK
+
+void TaskDataAcquisition();
+
+#endif
diff --git a/examples/OpenIMU335RI/VG/src/user/EcuSettings.c b/examples/OpenIMU335RI/VG/src/user/EcuSettings.c
new file mode 100644
index 0000000..8970ec2
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/user/EcuSettings.c
@@ -0,0 +1,908 @@
+/** ***************************************************************************
+ * @file ecu_configuration.c
+ *
+ * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ ******************************************************************************/
+/*******************************************************************************
+Copyright 2018 ACEINNA, INC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*******************************************************************************/
+
+#include "string.h"
+#include "algorithmAPI.h"
+#include "configurationAPI.h"
+
+#include "EcuSettings.h"
+#include "eepromAPI.h"
+#include "Indices.h"
+#include "bitAPI.h"
+#include "halAPI.h"
+#include "odoAPI.h"
+
+static void ApplySystemParameters(EcuConfigurationStruct* const pConfig);
+static void UpdateEcuInstanceSettings();
+BOOL OrientationToAscii(uint8_t *asciiOrien);
+
+
+
+static EcuConfigurationStruct gEcuConfig;
+EcuConfigurationStruct *gEcuConfigPtr = &gEcuConfig;
+int32_t ConfigSaveError = 0;
+
+static uint16_t newAddress = 0xFFFFU;
+static uint16_t newCanBaudRate = 0xFFFFU;
+static uint16_t newUartBaudRate = 0xFFFFU;
+static uint16_t newBehavior = 0xFFFFU;
+static uint16_t newEcuPacketRate = 0xFFFFU;
+static uint16_t newEcuPacketType = 0xFFFFU;
+static uint16_t newAccelFilter = 0xFFFFU;
+static uint16_t newRateFilter = 0xFFFFU;
+static uint16_t newOrientation = 0xFFFFU;
+
+// Default user configuration structure
+// Applied to unit upon reception of "zR" command
+// Do Not remove - just add extra parameters if needed
+// Change default settings if desired
+static ecu_settings_struct const DefaultEcuSettings = {
+ .dataCRC = 0,
+ .dataSize = sizeof(ecu_settings_struct),
+ .ecuAddress = 128,
+ .ecuBaudRate = ECU_BAUD_250K,
+ .ecuPacketRate = 100, // 100Hz
+ .ecuFilterFreqAccel = 25,
+ .ecuFilterFreqRate = 25,
+ .ecuPacketType = (
+ ACEINNA_SAE_J1939_PACKET_SLOPE_SENSOR2 |
+ ACEINNA_SAE_J1939_PACKET_ANGULAR_RATE |
+// ACEINNA_SAE_J1939_PACKET_ANGULAR_RATE_HR |
+// ACEINNA_SAE_J1939_PACKET_ACCELERATION_HR |
+ ACEINNA_SAE_J1939_PACKET_ACCELERATION |
+ 0
+ ),
+ .ecuOrientation = 0, // +X +Y +Z
+ .userBehavior =
+ (uint16_t)(USER_BEHAVIOR_ENABLE_DYN_MOTION |
+ USER_BEHAVIOR_SWAP_PITCH_AND_ROLL |
+ USER_BEHAVIOR_ENABLE_AUTO_BAUD |
+ USER_BEHAVIOR_SWAP_ACCEL_FRAME |
+ USER_BEHAVIOR_USE_RAW_ACCEL_FOR_ALG |
+ USER_BEHAVIOR_RUN_ALGORITHM_MASK),
+
+ .statusPs = 0,
+ .algResetPs = 0,
+ .saveCfgPs = 0,
+ .packetRatePs = 0,
+ .packetTypePs = 0,
+ .filterPs = 0,
+ .orientationPs = 0,
+ .userBehvPs = 0,
+ .algoCoefOfReduceQ = 10,
+ .algoLinAccelSwitchDelay = 2000,
+ .algoRateIntegrationTime = 2000,
+ .addressChanged = 0,
+ .masterStatusPs = 0,
+ .hwStatusPs = 0,
+ .swStatusPs = 0,
+ .algoCtrlPs = 0,
+ .hrRatePs = 0,
+ .hrAccelPs = 0,
+ .aidLvarmPs = 0,
+ .aidConfigPs = 0,
+ .dm1ConfigPs = 0,
+ .odoLeverArmX = 0,
+ .odoLeverArmY = 0,
+ .odoLeverArmZ = 0,
+// DM1 configuration related parameters
+ .lamp_status = 0x04, // amber light on
+ .flash_status = 0xFF, // undefined
+ .SPN = 0x07F4B3, // 521395 - default SPN of message DM1
+ .FMI1 = 12, // Failure Mode Identifier for DTC1
+ .FMI2 = 14, // Failure Mode Identifier for DTC2
+// Priorities of messages
+ .ariMsgPriority = 3,
+ .accsMsgPriority = 2,
+ .ssi2MsgPriority = 3,
+
+
+// UART - related parameters
+ .uartCfg.userUartBaudRate = 115200,
+ .uartCfg.userPacketType = "", // do not apply
+ .uartCfg.userPacketRate = -1, // do not apply
+ .uartCfg.lpfAccelFilterFreq = -1, // do not apply
+ .uartCfg.lpfRateFilterFreq = -1, // do not apply
+ .uartCfg.orientation = "+Z+Z+Z", // do not apply
+
+};
+
+static ecu_settings_struct gEcuSettings;
+static uint32_t setStat = 0U;
+userUartConfig_t *pUserUartConfig = &gEcuSettings.uartCfg;
+
+
+/******************************************************************************
+ * @brief
+ * @param fSave [in] sample new data to push onto the queue
+ *
+ ******************************************************************************/
+static BOOL LoadDefaultEcuSettings(BOOL const fSave)
+{
+ // Load default user configuration
+ memcpy(&gEcuSettings, &DefaultEcuSettings, sizeof(ecu_settings_struct));
+
+ if(!fSave){
+ return TRUE;
+ }
+
+ return SaveEcuSettings(TRUE, FALSE);
+
+}
+
+/*******************************************
+ * @brief
+ *
+ * @param config ==
+********************************************/
+void ApplyDm1ConfigFromEeprom(uint64_t config)
+{
+ gEcuSettings.lamp_status = config & 0xFF; // byte 0
+ gEcuSettings.flash_status = (config >> 8) & 0xFF; // byte 1
+ gEcuSettings.SPN = (config >> 16) & 0xFFFFFF; // byte 2 - 4
+ gEcuSettings.FMI1 = (config >> 40) & 0xFF; // byte 5
+ gEcuSettings.FMI2 = (config >> 48) & 0xFF; // byte6
+}
+
+
+/*******************************************
+ * @brief
+ *
+ * @return uint64_t
+********************************************/
+uint64_t PrepareDm1ConfigToEeprom()
+{
+ uint64_t config = 0;
+ config <<= 8;
+ config |= gEcuSettings.FMI2;
+ config <<= 8;
+ config |= gEcuSettings.FMI1;
+ config <<= 24;
+ config |= (gEcuSettings.SPN & 0x00FFFFFF);
+ config <<= 8;
+ config |= gEcuSettings.flash_status;
+ config <<= 8;
+ config |= gEcuSettings.lamp_status;
+
+ return config;
+}
+
+
+
+/******************************************************************************
+ * @brief
+ *
+ ******************************************************************************/
+void LoadEcuSettings()
+{
+ uint16_t size = (uint16_t)sizeof(gEcuSettings); // total size in bytes
+ BOOL const factoryMode = EEPROM_IsFactoryMode(); // should be always FALSE when vital system parameters are intact
+ BOOL const configLoaded = EEPROM_IsConfigLoaded(size);
+
+ uint8_t ecuAddr;
+ uint64_t dm1Config;
+
+ BOOL res;
+ // Validate checksum of user configuration structure
+ BOOL const configValid = EEPROM_ValidateUserConfig(&size);
+
+ if(!configValid){
+ // Load default configuration if user configuration
+ // did not pass validation
+ setStat += LoadDefaultEcuSettings(FALSE);
+ BIT_SetInvalidConfigStatus();
+ }else{
+ // Here we have validated User configuration
+ setStat += (uint32_t)EEPROM_LoadUserConfig((void*)&gEcuSettings, &size);
+ if(configLoaded){
+ res = EEPROM_InvalidateConfigSignature(size);
+ if(res){
+ setStat += EEPROM_SaveEcuAddress(gEcuSettings.ecuAddress);
+ }
+ }
+ }
+
+ res = EEPROM_GetLastSavedEcuAddress(&ecuAddr);
+
+ if(res){
+ gEcuSettings.ecuAddress = ecuAddr;
+ }
+
+ res = EEPROM_GetLastSavedDM1Config(&dm1Config);
+
+ if(res){
+ ApplyDm1ConfigFromEeprom(dm1Config);
+ }
+
+
+ // assign new actual size
+ gEcuSettings.dataSize = sizeof(ecu_settings_struct);
+
+ memset(&gEcuConfig, 0, sizeof(gEcuConfig));
+
+ // Apply parameters from NV memory to ECU configuration structure
+ ApplyEcuSettings();
+
+ BIT_SetFMICodes(gEcuConfig.FMI1, gEcuConfig.FMI2);
+
+ if(!factoryMode)
+ {
+ // User Filters and orientation
+ ApplySystemParameters(&gEcuConfig);
+ // UART settings
+ UserInitConfigureUart();
+ }
+
+ UpdateEcuInstanceSettings();
+}
+
+/*******************************************
+ * @brief
+ *
+********************************************/
+void BackFillUartDataStructure()
+{
+ OrientationToAscii(pUserUartConfig->orientation);
+ pUserUartConfig->lpfAccelFilterFreq = config_GetFilterFreq(ACCEL_SENSOR, 0U);
+ pUserUartConfig->lpfRateFilterFreq = config_GetFilterFreq(RATE_SENSOR, 0U);
+}
+
+
+
+/** ***************************************************************************
+ * @name SaveUserConfig - saving of user configuration structure un the
+ * predefined flash sector
+ * @brief
+ *
+ * @param fDefault [in]
+ * @return error (0), no error (1)
+ ******************************************************************************/
+
+BOOL SaveEcuSettings(BOOL const fDefault, BOOL const fromUart)
+{
+ uint16_t size;
+ BOOL status;
+
+ if (!fDefault)
+ {
+ gEcuSettings.ecuAddress = gEcu.addr;
+ if(gEcu.newAddr != 0U){
+ gEcuSettings.ecuAddress = gEcu.newAddr;
+ }
+ gEcuSettings.ecuBaudRate = gEcu.baudrate;
+ gEcuSettings.ecuPacketRate = gEcuConfigPtr->packet_rate_div == 0? 0 : 100/gEcuConfigPtr->packet_rate_div;
+ gEcuSettings.ecuPacketType = gEcuConfigPtr->packet_type;
+ gEcuSettings.userBehavior = gEcuConfigPtr->user_behavior;
+ if(!fromUart){
+ // populate from CAN bus side
+ gEcuSettings.ecuOrientation = gEcuConfigPtr->orien_bits;
+ gEcuSettings.ecuFilterFreqAccel = gEcuConfigPtr->accel_cut_off;
+ gEcuSettings.ecuFilterFreqRate = gEcuConfigPtr->rate_cut_off;
+ }else{
+ // populate from config structure whatever propagated from UART commands
+ gEcuSettings.ecuOrientation = config_GetOrientation();
+ gEcuSettings.ecuFilterFreqAccel = config_GetFilterFreq(ACCEL_SENSOR, 0U);
+ gEcuSettings.ecuFilterFreqRate = config_GetFilterFreq(RATE_SENSOR, 0U);
+ }
+ gEcuSettings.algoLinAccelSwitchDelay = gEcuConfigPtr->limitAccelSwitchDelay;
+ gEcuSettings.algoRateIntegrationTime = gEcuConfigPtr->limitRateIntegrationTime;
+ gEcuSettings.algoCoefOfReduceQ = gEcuConfigPtr->coefOfReduceQ;
+
+ gEcuSettings.algResetPs = gEcuConfigPtr->alg_reset_ps;
+ gEcuSettings.saveCfgPs = gEcuConfigPtr->save_cfg_ps;
+ gEcuSettings.packetRatePs = gEcuConfigPtr->packet_rate_ps;
+ gEcuSettings.packetTypePs = gEcuConfigPtr->packet_type_ps;
+ gEcuSettings.filterPs = gEcuConfigPtr->digital_filter_ps;
+ gEcuSettings.orientationPs = gEcuConfigPtr->orientation_ps;
+ gEcuSettings.userBehvPs = gEcuConfigPtr->user_behavior_ps;
+ gEcuSettings.masterStatusPs = gEcuConfigPtr->master_status_ps;
+ gEcuSettings.hwStatusPs = gEcuConfigPtr->hw_status_ps;
+ gEcuSettings.swStatusPs = gEcuConfigPtr->sw_status_ps;
+ gEcuSettings.algoCtrlPs = gEcuConfigPtr->algo_control_ps;
+ gEcuSettings.hrRatePs = gEcuConfigPtr->hr_rate_ps;
+ gEcuSettings.hrAccelPs = gEcuConfigPtr->hr_accel_ps;
+ // Odometer lever arm
+ gEcuSettings.odoLeverArmX = gEcuConfigPtr->odoLeverArmX;
+ gEcuSettings.odoLeverArmY = gEcuConfigPtr->odoLeverArmY;
+ gEcuSettings.odoLeverArmZ = gEcuConfigPtr->odoLeverArmZ;
+ // Aiding signal configuration settings
+ gEcuSettings.signalSource = gEcuConfigPtr->signalSource;
+ gEcuSettings.aidingPF = gEcuConfigPtr->aidingPF;
+ gEcuSettings.aidingPS = gEcuConfigPtr->aidingPS;
+ gEcuSettings.aidingMsgRate = gEcuConfigPtr->aidingMsgRate;
+ gEcuSettings.drivingDirPF = gEcuConfigPtr->drivingDirPF;
+ gEcuSettings.drivingDirPS = gEcuConfigPtr->drivingDirPS;
+ gEcuSettings.odoCfgSwitch = gEcuConfigPtr->odoCfgSwitch;
+ // new configurable ps
+ gEcuSettings.aidLvarmPs = gEcuConfigPtr->aid_lvarm_ps;
+ gEcuSettings.aidConfigPs = gEcuConfigPtr->aid_config_ps;
+ // DM1 config parameters
+ gEcuSettings.dm1ConfigPs = gEcuConfigPtr->dm1_config_ps;
+ gEcuSettings.lamp_status = gEcuConfigPtr->lamp_status;
+ gEcuSettings.flash_status = gEcuConfigPtr->flash_status;
+ gEcuSettings.FMI1 = gEcuConfigPtr->FMI1;
+ gEcuSettings.FMI2 = gEcuConfigPtr->FMI2;
+ gEcuSettings.SPN = gEcuConfigPtr->SPN;
+ // priority of messages
+ gEcuSettings.ariMsgPriority = gEcuConfigPtr->ariPriority;
+ gEcuSettings.accsMsgPriority = gEcuConfigPtr->accsPriority;
+ gEcuSettings.ssi2MsgPriority = gEcuConfigPtr->ssi2Priority;
+
+ if(!fromUart){
+ BackFillUartDataStructure();
+ }
+ }
+
+ config_ApplyEcuAddress((uint8_t)gEcuSettings.ecuAddress);
+ config_ApplyEcuBaudrate((uint8_t)gEcuSettings.ecuBaudRate);
+
+ size = (uint16_t)sizeof(ecu_settings_struct);
+ status = EEPROM_SaveEcuSettings((uint8_t *)&gEcuSettings, size);
+
+ if(status == FALSE){
+ if(!fDefault){
+ gEcuSettings.ecuAddress = gEcu.addr;
+ }
+ }
+
+ EEPROM_SaveEcuAddress(gEcuSettings.ecuAddress);
+ uint64_t config = PrepareDm1ConfigToEeprom();
+ EEPROM_SaveDM1Config(config);
+
+ return status;
+
+}
+
+/*******************************************
+ * @brief
+ *
+ * @param ecuAddress ==
+ * @return BOOL
+********************************************/
+BOOL SaveEcuAddress(uint8_t ecuAddress)
+{
+ gEcuSettings.ecuAddress = ecuAddress;
+ config_ApplyEcuAddress((uint8_t)gEcuSettings.ecuAddress);
+ return EEPROM_SaveEcuAddress(ecuAddress);
+}
+
+/*******************************************
+ * @brief
+ *
+ * @param baudrate ==
+********************************************/
+extern void UpdateEcuBaudrate(uint16_t baudrate)
+{
+ gEcuSettings.ecuBaudRate = baudrate;
+ config_ApplyEcuBaudrate((uint8_t)gEcuSettings.ecuBaudRate);
+}
+
+
+ /******************************************************************************
+ * @brief
+ * @return address
+ ******************************************************************************/
+uint8_t GetEcuAddress()
+{
+ return (uint8_t)gEcuSettings.ecuAddress;
+}
+
+/**********************************************
+* @brief Set the Ecu Baudrate object
+*
+* @param baudrate --
+***********************************************/
+void SetEcuBaudrate(uint16_t const baudrate)
+{
+ newCanBaudRate = baudrate;
+}
+
+
+/**********************************************
+* @brief Set the Ecu Address object
+*
+* @param address ---
+***********************************************/
+void SetEcuAddress(uint16_t const address)
+{
+ newAddress = address;
+}
+
+/*******************************************
+ * @brief Set the Ecu Behavior object
+ *
+ * @param behavior ==
+********************************************/
+void SetEcuBehavior(uint16_t const behavior)
+{
+ newBehavior = behavior;
+}
+
+/*******************************************
+ * @brief Set the Ecu Packet Type object
+ *
+ * @param type ==
+********************************************/
+void SetEcuPacketType(uint16_t const type)
+{
+ newEcuPacketType = type;
+}
+
+/*******************************************
+ * @brief Set the Ecu Packet Rate object
+ *
+ * @param rate ==
+********************************************/
+BOOL SetEcuPacketRate(uint16_t const rate)
+{
+ if(rate){
+ if((rate > 100) || ((100 % rate) != 0)){ // should be even to 100
+ return FALSE;
+ }
+ }
+ newEcuPacketRate = rate;
+ return TRUE;
+}
+
+
+/*******************************************
+ * @brief Set the Ecu Orientation object
+ *
+ * @param orient ==
+********************************************/
+void SetEcuOrientation(uint16_t const orient)
+{
+ newOrientation = orient;
+}
+
+/*******************************************
+ * @brief Set the User Uart Baud Rate object
+ *
+ * @param baudRate ==
+********************************************/
+void SetUserUartBaudRate(uint16_t const baudRate)
+{
+ newUartBaudRate = baudRate;
+}
+
+
+/*******************************************
+ * @brief Set the Ecu Accel Filter object
+ *
+ * @param filter ==
+********************************************/
+void SetEcuAccelFilter(uint16_t const filter)
+{
+ newAccelFilter = filter;
+}
+
+/*******************************************
+ * @brief Set the Ecu Rate Filter object
+ *
+ * @param filter ==
+********************************************/
+void SetEcuRateFilter(uint16_t const filter)
+{
+ newRateFilter = filter;
+}
+
+
+/*******************************************
+ * @brief
+ *
+********************************************/
+void UpdateEcuSettings()
+{
+ BOOL fSave = FALSE;
+ BOOL fBaudRate = FALSE;
+ BOOL fAddress = FALSE;
+ BOOL fBehavior = FALSE;
+ BOOL fAccelLpf = FALSE;
+ BOOL fRateLpf = FALSE;
+ BOOL fOrientation = FALSE;
+ BOOL fPacketRate = FALSE;
+ BOOL fPacketType = FALSE;
+ BOOL fUartBaudRate = FALSE;
+
+ if(newCanBaudRate != 0xFFFFU){
+ gEcuSettings.ecuBaudRate = newCanBaudRate & 0x03U;
+ newCanBaudRate = 0xFFFFU;
+ fBaudRate = TRUE;
+ fSave = TRUE;
+ }
+
+ if(newUartBaudRate != 0xFFFFU){
+ gEcuSettings.uartCfg.userUartBaudRate = newUartBaudRate;
+ newUartBaudRate = 0xFFFFU;
+ fUartBaudRate = TRUE;
+ fSave = TRUE;
+ }
+
+ if(newAddress != 0xFFFFU){
+ gEcuSettings.ecuAddress = newAddress & 0xFFU;
+ fAddress = TRUE;
+ newAddress = 0xFFFFU;
+ fSave = TRUE;
+ }
+
+ if(newBehavior != 0xFFFFU){
+ gEcuSettings.userBehavior = newBehavior;
+ fBehavior = TRUE;
+ newBehavior = 0xFFFF;
+ fSave = TRUE;
+ }
+
+ if(newAccelFilter != 0xFFFFU){
+ gEcuSettings.ecuFilterFreqAccel = newAccelFilter;
+ gEcuSettings.uartCfg.lpfAccelFilterFreq = 0xFF; // invalidate
+ fAccelLpf = TRUE;
+ newAccelFilter = 0xFFFF;
+ fSave = TRUE;
+ }
+
+ if(newRateFilter != 0xFFFFU){
+ gEcuSettings.ecuFilterFreqRate = newRateFilter;
+ gEcuSettings.uartCfg.lpfRateFilterFreq = 0xFF; // invalidate
+ fRateLpf = TRUE;
+ newRateFilter = 0xFFFF;
+ fSave = TRUE;
+ }
+
+ if(newOrientation != 0xFFFFU){
+ gEcuSettings.ecuOrientation = newOrientation;
+ gEcuSettings.uartCfg.orientation[0] = 0; // invalidate
+ fOrientation = TRUE;
+ newOrientation = 0xFFFF;
+ fSave = TRUE;
+ }
+
+ if(newEcuPacketRate != 0xFFFFU){
+ gEcuSettings.ecuPacketRate = newEcuPacketRate;
+ fPacketRate = TRUE;
+ newEcuPacketRate = 0xFFFF;
+ fSave = TRUE;
+ }
+
+ if(newEcuPacketType != 0xFFFFU){
+ gEcuSettings.ecuPacketType = newEcuPacketType;
+ fPacketType = TRUE;
+ newEcuPacketType = 0xFFFF;
+ fSave = TRUE;
+ }
+
+ if (fSave)
+ {
+
+ HW_FeedWatchdog();
+ uint32_t const size = sizeof(ecu_settings_struct);
+ BOOL const status = EEPROM_SaveEcuSettings((uint8_t *)&gEcuSettings, size);
+
+ if (fAddress)
+ {
+ config_ApplyEcuAddress((uint8_t)gEcuSettings.ecuAddress);
+ EEPROM_SaveEcuAddress(gEcuSettings.ecuAddress);
+ }
+ if (fBaudRate)
+ {
+ config_ApplyEcuBaudrate((uint8_t)gEcuSettings.ecuBaudRate);
+ }
+ if (fBehavior)
+ {
+ config_ApplyEcuUnitBehavior(gEcuSettings.userBehavior);
+ }
+ if (fAccelLpf)
+ {
+ config_SelectUserLPFilter(ACCEL_SENSOR, gEcuSettings.ecuFilterFreqAccel, TRUE);
+ }
+ if (fRateLpf)
+ {
+ config_SelectUserLPFilter(RATE_SENSOR, gEcuSettings.ecuFilterFreqRate, TRUE);
+ }
+ if (fOrientation)
+ {
+ config_ApplyCanOrientation(gEcuSettings.ecuOrientation);
+ }
+ if (fPacketRate)
+ {
+ config_ApplyCanPacketRate(gEcuSettings.ecuPacketRate);
+ }
+ if (fPacketType)
+ {
+ config_ApplyCanPacketType(gEcuSettings.ecuPacketType);
+ }
+ if (fUartBaudRate)
+ {
+ config_SetBaudRate(gEcuSettings.uartCfg.userUartBaudRate, TRUE);
+ }
+
+
+ if (!status)
+ {
+ ConfigSaveError++;
+ }
+ }
+}
+
+
+
+/**********************************************
+* @brief Get the Ecu Baud Rate object
+*
+* @return int32_t
+***********************************************/
+int32_t GetEcuBaudRate()
+{
+ return gEcuSettings.ecuBaudRate;
+}
+
+/******************************************************************************
+ * @brief
+ *
+ ******************************************************************************/
+void ApplyEcuSettings()
+{
+ EcuConfigurationStruct* const pEcuConfig = gEcuConfigPtr;
+
+ // Add/Remove/Verify ECU-specific parameters here
+ pEcuConfig->packet_rate_div = gEcuSettings.ecuPacketRate == 0? 0 : 100U/gEcuSettings.ecuPacketRate; //++
+ pEcuConfig->accel_cut_off = gEcuSettings.ecuFilterFreqAccel;
+ pEcuConfig->rate_cut_off = gEcuSettings.ecuFilterFreqRate;
+ pEcuConfig->packet_type = gEcuSettings.ecuPacketType; //++
+ pEcuConfig->orien_bits = gEcuSettings.ecuOrientation;
+ pEcuConfig->user_behavior = gEcuSettings.userBehavior;
+ pEcuConfig->limitAccelSwitchDelay = gEcuSettings.algoLinAccelSwitchDelay;
+ pEcuConfig->limitRateIntegrationTime = gEcuSettings.algoRateIntegrationTime;
+ pEcuConfig->coefOfReduceQ = gEcuSettings.algoCoefOfReduceQ;
+
+ pEcuConfig->alg_reset_ps = gEcuSettings.algResetPs; //++
+ pEcuConfig->save_cfg_ps = gEcuSettings.saveCfgPs; //++
+ pEcuConfig->packet_type_ps = gEcuSettings.packetTypePs; //++
+ pEcuConfig->packet_rate_ps = gEcuSettings.packetRatePs; //++
+ pEcuConfig->digital_filter_ps = gEcuSettings.filterPs; //++
+ pEcuConfig->orientation_ps = gEcuSettings.orientationPs; //++
+ pEcuConfig->user_behavior_ps = gEcuSettings.userBehvPs; //++
+ pEcuConfig->master_status_ps = gEcuSettings.masterStatusPs;
+ pEcuConfig->hw_status_ps = gEcuSettings.hwStatusPs;
+ pEcuConfig->sw_status_ps = gEcuSettings.swStatusPs;
+ pEcuConfig->hr_accel_ps = gEcuSettings.hrAccelPs;
+ pEcuConfig->hr_rate_ps = gEcuSettings.hrRatePs;
+ pEcuConfig->algo_control_ps = gEcuSettings.algoCtrlPs;
+ pEcuConfig->ecuBaudrate = gEcuSettings.ecuBaudRate;
+ pEcuConfig->ecuAddress = gEcuSettings.ecuAddress;
+
+ // Odometer lever arm
+ pEcuConfig->odoLeverArmX = gEcuSettings.odoLeverArmX;
+ pEcuConfig->odoLeverArmY = gEcuSettings.odoLeverArmY;
+ pEcuConfig->odoLeverArmZ = gEcuSettings.odoLeverArmZ;
+ // Aiding signal configuration settings
+ pEcuConfig->signalSource = gEcuSettings.signalSource;
+ pEcuConfig->aidingPF = gEcuSettings.aidingPF;
+ pEcuConfig->aidingPS = gEcuSettings.aidingPS;
+ pEcuConfig->aidingMsgRate = gEcuSettings.aidingMsgRate;
+ pEcuConfig->drivingDirPF = gEcuSettings.drivingDirPF;
+ pEcuConfig->drivingDirPS = gEcuSettings.drivingDirPS;
+ pEcuConfig->odoCfgSwitch = gEcuSettings.odoCfgSwitch;
+ // new configurable ps
+ pEcuConfig->aid_lvarm_ps = gEcuSettings.aidLvarmPs;
+ pEcuConfig->aid_config_ps = gEcuSettings.aidConfigPs;
+ pEcuConfig->dm1_config_ps = gEcuSettings.dm1ConfigPs;
+ // DM1 config parameters
+ pEcuConfig->dm1_config_ps = gEcuSettings.dm1ConfigPs;
+ pEcuConfig->lamp_status = gEcuSettings.lamp_status;
+ pEcuConfig->flash_status = gEcuSettings.flash_status;
+ pEcuConfig->FMI1 = gEcuSettings.FMI1;
+ pEcuConfig->FMI2 = gEcuSettings.FMI2;
+ pEcuConfig->SPN = gEcuSettings.SPN;
+ // priority of messages
+ pEcuConfig->ariPriority = gEcuSettings.ariMsgPriority;
+ pEcuConfig->accsPriority = gEcuSettings.accsMsgPriority;
+ pEcuConfig->ssi2Priority = gEcuSettings.ssi2MsgPriority;
+
+ // Propagate parameters to common configuration area
+
+ config_ApplyEcuAddress(gEcuSettings.ecuAddress);
+ config_ApplyEcuBaudrate(gEcuSettings.ecuBaudRate);
+ config_ApplyEcuUnitBehavior(gEcuSettings.userBehavior);
+ config_ApplyCanPacketRate(gEcuSettings.ecuPacketRate);
+ config_ApplyCanPacketType(gEcuSettings.ecuPacketType);
+ config_SelectUserLPFilter(ACCEL_SENSOR, gEcuSettings.ecuFilterFreqAccel, TRUE);
+ config_SelectUserLPFilter(RATE_SENSOR, gEcuSettings.ecuFilterFreqRate, TRUE);
+ config_ApplyCanOrientation(gEcuSettings.ecuOrientation);
+ OdoUpdateConfig(gEcuConfigPtr->aidingMsgRate, gEcuConfigPtr->signalSource ,gEcuConfigPtr->odoCfgSwitch);
+ OdoUpdateLeverArmConfig(&(gEcuConfigPtr->odoLeverArmX));
+ ecu_set_address(gEcuSettings.ecuAddress);
+ ecu_set_baudrate(gEcuSettings.ecuBaudRate);
+
+}
+
+ /******************************************************************************
+ * @brief
+ * @return detect enabled
+ ******************************************************************************/
+BOOL CanBaudRateDetectionEnabled()
+{
+ if((gEcuConfigPtr->user_behavior & (uint16_t)USER_BEHAVIOR_ENABLE_AUTO_BAUD) != 0U){
+ return TRUE;
+ }
+ return FALSE;
+
+}
+
+ /******************************************************************************
+ * @brief
+ * @return use algo
+ ******************************************************************************/
+BOOL UseAlgorithm()
+{
+ if((gEcuConfigPtr->user_behavior & (uint16_t)USER_BEHAVIOR_RUN_ALGORITHM_MASK) != 0U){
+ return TRUE;
+ };
+
+ return FALSE;
+}
+
+ /******************************************************************************
+ * @brief
+ * @return send rates
+ ******************************************************************************/
+BOOL SendRawRates()
+{
+ if((gEcuConfigPtr->user_behavior & (uint16_t)USER_BEHAVIOR_SEND_RAW_RATES) != 0U){
+ return TRUE;
+ }
+ return FALSE;
+
+}
+
+ /******************************************************************************
+ * @brief
+ * @return swap pich
+ ******************************************************************************/
+BOOL SwapPitchAndRoll()
+{
+ if((gEcuConfigPtr->user_behavior & (uint16_t)USER_BEHAVIOR_SWAP_PITCH_AND_ROLL) != 0U){
+ return TRUE;
+ }
+ return FALSE;
+}
+
+ /******************************************************************************
+ * @brief
+ * @return swap Frame
+ ******************************************************************************/
+BOOL SwapAccelFrame()
+{
+ if ((gEcuConfigPtr->user_behavior & (uint16_t)USER_BEHAVIOR_SWAP_ACCEL_FRAME) != 0U) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+ /******************************************************************************
+ * @brief
+ * @return swap bytes
+ ******************************************************************************/
+BOOL SwapBytesInRequest()
+{
+ if ((gEcuConfigPtr->user_behavior & (uint16_t)USER_BEHAVIOR_SWAP_BYTES_IN_REQUEST) != 0U) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/******************************************************************************
+ * @brief
+ * @param pConfig [in]
+ *
+ ******************************************************************************/
+static void ApplySystemParameters(EcuConfigurationStruct* const pConfig)
+{
+ setStat += (uint32_t)config_SelectUserLPFilter(RATE_SENSOR, pConfig->rate_cut_off, TRUE);
+ setStat += (uint32_t)config_SelectUserLPFilter(ACCEL_SENSOR, pConfig->accel_cut_off, TRUE);
+ setStat += (uint32_t)config_ApplyOrientation(pConfig->orien_bits, TRUE);
+}
+
+
+/*******************************************
+ * @brief
+ *
+********************************************/
+static void UpdateEcuInstanceSettings()
+{
+ ecu_set_address(config_GetEcuAddress());
+ ecu_set_baudrate(config_GetEcuBaudRate());
+}
+
+ /******************************************************************************
+ * @brief
+ * @return divider
+ ******************************************************************************/
+int32_t GetCANPacketRateDivider()
+{
+ return gEcuConfigPtr->packet_rate_div;
+}
+
+ /******************************************************************************
+ * @brief
+ * @return detectMode
+ ******************************************************************************/
+BOOL GetAlgorithmLinAccelDetectMode()
+{
+ if((gEcuConfig.user_behavior & (uint16_t)USER_BEHAVIOR_USE_RAW_ACCEL_FOR_ALG) != 0U){
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+ /******************************************************************************
+ * @brief
+ * @return predictMode
+ ******************************************************************************/
+BOOL GetAlgorithmAccelPredictMode()
+{
+ if((gEcuConfig.user_behavior & (uint16_t)USER_BEHAVIOR_USE_RAW_RATE_TO_PREDICT_ACCEL) != 0U){
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+ /******************************************************************************
+ * @brief
+ * @return time
+ ******************************************************************************/
+float32_t GetAlgorithmCoefOfReduceQ()
+{
+ // 0.0001 to 1 (1 to 10000)
+ return (float32_t)gEcuConfig.coefOfReduceQ/10000.0F;
+}
+
+ /******************************************************************************
+ * @brief
+ * @return time
+ ******************************************************************************/
+float32_t GetAlgorithmAccelSwitchDelay()
+{
+ // 0.01 to 10 (100 to 10000)
+ return (float32_t)gEcuConfig.limitAccelSwitchDelay/1000.0F;
+}
+
+ /******************************************************************************
+ * @brief
+ * @return time
+ ******************************************************************************/
+float32_t GetAlgorithmRateIntegrationTime()
+{
+ // 0.01 to 10 (100 to 10000)
+ return (float32_t)gEcuConfig.limitRateIntegrationTime/1000.0F;
+}
+
+
diff --git a/examples/OpenIMU335RI/VG/src/user/EcuSettings.h b/examples/OpenIMU335RI/VG/src/user/EcuSettings.h
new file mode 100644
index 0000000..467c0f8
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/user/EcuSettings.h
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * File: ecu_settings.h
+ * Created on JAn 25, 2017
+ ******************************************************************************/
+/*******************************************************************************
+Copyright 2020 ACEINNA, INC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*******************************************************************************/
+
+#ifndef ECU_SETTINGS_H
+#define ECU_SETTINGS_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+#include
+
+#include "GlobalConstants.h"
+#include "aceinna_sae_J1939.h"
+#include "UserConfigurationUart.h"
+
+/// User defined configuration strucrture
+///Please notice, that parameters are 64 bit to accomodate float64_t types as well as longer string types
+#pragma pack(1)
+typedef struct {
+ uint64_t dataCRC; // CRC of user configuration structure CRC-16
+ uint64_t dataSize; // Size of the user configuration structure
+ userUartConfig_t uartCfg; // user UART configuration structure
+ uint16_t ecuAddress; // ecu address
+ uint16_t ecuBaudRate; // ecu baudrate - 250, 500, 1000
+ uint16_t ecuPacketRate; // CAN packet rate (100Hz tick)
+ uint16_t ecuFilterFreqAccel; // accels cutoff frequency for digital filter
+ uint16_t ecuFilterFreqRate; // rates cutoff frequency for digital filter
+ uint16_t ecuPacketType; // packet types being transmitted
+ uint16_t ecuOrientation; // unit orientation
+ //0 +Z +Y +X
+ //9 +Z -Y -X
+ // 35 +Z +X +Y
+ // 42 +Z -X +Y
+ // 65 -Z +Y -X
+ // 72 -Z -Y +X
+ // 98 -Z +X +Y
+ // 107 -Z -X -Y
+ // 133 +X +Y -Z
+ // 140 +X -Y +Z
+ // 146 +X +Z +Y
+ // 155 +X -Z -Y
+ // 196 -X +Y +Z
+ // 205 -X -Y -Z
+ // 211 -X +Z -Y
+ // 218 -X -Z +Y
+ // 273 +Y +Z -X
+ // 280 +Y -Z +X
+ // 292 +Y +X +Z
+ // 301 +Y -X -Z
+ // 336 -Y +Z +X
+ // 345 -Y -Z -X
+ // 357 -Y +X -Z
+ // 364 -Y -X +Z
+ uint16_t userBehavior; // user algorithm behaviour
+ uint8_t statusPs; // ps value of status message
+ uint8_t algResetPs; // ps value of alg reset
+
+ uint8_t saveCfgPs; // ps value of config save
+ uint8_t packetRatePs; // ps value of packet type
+ uint8_t packetTypePs; // ps value of packet type
+ uint8_t filterPs; // ps value of lpf
+ uint8_t orientationPs; // ps value of orientation
+ uint8_t userBehvPs; // ps value of user behavior
+ uint8_t masterStatusPs; // ps value of status
+ uint8_t hwStatusPs; // ps value of status
+ uint8_t swStatusPs; // ps value of status
+ uint8_t algoCtrlPs; // ps value of algorithm control
+ uint8_t hrRatePs; // ps value of hr rate message
+ uint8_t hrAccelPs; // ps value of hr accelrate message
+ uint16_t algoCoefOfReduceQ;
+ uint16_t algoLinAccelSwitchDelay;
+ uint16_t algoRateIntegrationTime;
+ uint8_t addressChanged; // ps value of hr accelrate message
+// Odometer lever arm
+ int16_t odoLeverArmX;
+ int16_t odoLeverArmY;
+ int16_t odoLeverArmZ;
+// Aiding signal configuration settings
+ uint8_t signalSource;
+ uint8_t aidingPF;
+ uint8_t aidingPS;
+ uint8_t aidingMsgRate;
+ uint8_t drivingDirPF;
+ uint8_t drivingDirPS;
+ uint8_t odoCfgSwitch;
+// DM1 message configurable parameters
+ uint8_t lamp_status; // status of warning indicators
+ uint8_t flash_status; // flash control of warning indicators
+ uint32_t SPN; // SPN of message DM1
+ uint8_t FMI1; // Failure Mode Identifier for DTC1
+ uint8_t FMI2; // Failure Mode Identifier for DTC2
+// new configurable ps
+ uint8_t aidLvarmPs;
+ uint8_t aidConfigPs;
+ uint8_t dm1ConfigPs;
+//
+ uint8_t ariMsgPriority; // priority of ARI message
+ uint8_t accsMsgPriority; // priority of ACCS message
+ uint8_t ssi2MsgPriority; // priority of SSI2 message
+
+} ecu_settings_struct;
+#pragma pack()
+
+enum {
+ INVALID_PARAM = -1,
+ INVALID_VALUE = -2,
+ INVALID_PAYLOAD_SIZE = -3,
+};
+
+enum {
+ USER_BEHAVIOR_RESTART_ON_OVERRANGE = 0x0001,
+ USER_BEHAVIOR_ENABLE_DYN_MOTION = 0x0002,
+ USER_BEHAVIOR_SEND_RAW_RATES = 0x0004,
+ USER_BEHAVIOR_SWAP_PITCH_AND_ROLL = 0x0008,
+ USER_BEHAVIOR_ENABLE_AUTO_BAUD = 0x0010,
+ USER_BEHAVIOR_ENABLE_TERM_RESISTOR = 0x0020,
+ USER_BEHAVIOR_SWAP_ACCEL_FRAME = 0x0040,
+ USER_BEHAVIOR_USE_RAW_ACCEL_FOR_ALG = 0x0080,
+ USER_BEHAVIOR_USE_RAW_RATE_TO_PREDICT_ACCEL = 0x0100,
+ USER_BEHAVIOR_SWAP_BYTES_IN_REQUEST = 0x0200,
+ USER_BEHAVIOR_RUN_ALGORITHM_MASK = 0x8000,
+};
+
+/**
+ * @brief
+ *
+ * @param fDefault
+ * @return BOOL
+ */
+extern BOOL SaveEcuSettings(BOOL fDefault, BOOL fromUart);
+
+/**
+ * @brief
+ *
+ */
+extern void ApplyEcuSettings();
+
+/**
+ * @brief
+ *
+ */
+extern void LoadEcuSettings(void);
+
+/**
+ * @brief
+ *
+ * @return int32_t
+ */
+extern int32_t GetCANPacketRateDivider();
+
+/**
+ * @brief Get the Ecu Address object
+ *
+ * @return uint8_t
+ */
+extern uint8_t GetEcuAddress();
+
+/**
+ * @brief Get the Ecu Baud Rate object
+ *
+ * @return int32_t
+ */
+extern int32_t GetEcuBaudRate();
+
+/**
+ * @brief
+ *
+ * @return BOOL
+ */
+extern BOOL CanBaudRateDetectionEnabled();
+
+/**
+ * @brief
+ *
+ * @return BOOL
+ */
+extern BOOL UseAlgorithm();
+
+/**
+ * @brief
+ *
+ * @return BOOL
+ */
+extern BOOL SendRawRates();
+
+/**
+ * @brief
+ *
+ * @return BOOL
+ */
+extern BOOL SwapPitchAndRoll();
+
+/**
+ * @brief
+ *
+ * @return BOOL
+ */
+extern BOOL SwapAccelFrame(); // NED to NWU
+
+/**
+ * @brief
+ *
+ * @return BOOL
+ */
+extern BOOL SwapBytesInRequest(); // LSB with MSB
+
+/**
+ * @brief Set the Ecu Baudrate object
+ *
+ * @param baudrate
+ */
+extern void SetEcuBaudrate(uint16_t baudrate);
+
+/**
+ * @brief Set the Ecu Address object
+ *
+ * @param address
+ */
+extern void SetEcuAddress(uint16_t address);
+
+
+/*******************************************
+ * @brief Set the Ecu Behavior object
+ *
+ * @param behavior ==
+********************************************/
+void SetEcuBehavior(uint16_t const behavior);
+
+
+/*******************************************
+ * @brief Set the Ecu Packet Type object
+ *
+ * @param type ==
+********************************************/
+void SetEcuPacketType(uint16_t const type);
+
+/*******************************************
+ * @brief Set the Ecu Packet Rate Divider object
+ *
+ * @param rate ==
+ * @return BOOL
+********************************************/
+BOOL SetEcuPacketRate(uint16_t const rate);
+
+
+/*******************************************
+ * @brief Set the Ecu Orientation object
+ *
+ * @param orient ==
+********************************************/
+void SetEcuOrientation(uint16_t const orient);
+
+
+/*******************************************
+ * @brief Set the Ecu Accel Filter object
+ *
+ * @param filter ==
+********************************************/
+void SetEcuAccelFilter(uint16_t const filter);
+
+
+/*******************************************
+ * @brief Set the Ecu Rate Filter object
+ *
+ * @param filter ==
+********************************************/
+void SetEcuRateFilter(uint16_t const filter);
+
+
+/*******************************************
+ * @brief Set the User Uart Baud Rate object
+ *
+ * @param baudRate ==
+********************************************/
+void SetUserUartBaudRate(uint16_t const baudRate);
+
+
+/*******************************************
+ * @brief
+ *
+********************************************/
+extern void UpdateEcuSettings();
+
+/*******************************************
+ * @brief
+ *
+ * @param baudrate ==
+********************************************/
+extern void UpdateEcuBaudrate(uint16_t baudrate);
+
+
+/*******************************************
+ * @brief
+ *
+ * @param ecuAddress ==
+ * @return BOOL
+********************************************/
+BOOL SaveEcuAddress(uint8_t ecuAddress);
+
+
+extern int32_t ConfigSaveError;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USER_CONFIGURATION_H */
+
+
diff --git a/examples/OpenIMU335RI/VG/src/user/UserAlgorithm.c b/examples/OpenIMU335RI/VG/src/user/UserAlgorithm.c
new file mode 100644
index 0000000..1b42dd0
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/user/UserAlgorithm.c
@@ -0,0 +1,84 @@
+/** ***************************************************************************
+ * @file UserAlgorithm.c
+ *
+ * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ ******************************************************************************/
+/*******************************************************************************
+Copyright 2018 ACEINNA, INC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*******************************************************************************/
+
+#include
+#include
+
+#include "GlobalConstants.h"
+
+#include "userAPI.h"
+#include "ekfAPI.h"
+
+
+/******************************************************************************
+ * @brief
+ *
+ ******************************************************************************/
+static void Algorithm()
+{
+ // Aceinna VG/AHRS/INS algorithm
+ EKF_Algorithm();
+}
+
+/******************************************************************************
+ * @brief
+ *
+ ******************************************************************************/
+void InitUserAlgorithm()
+{
+ // Initialize algorithm variables
+ EKF_Initialize((uint32_t)FREQ_200_HZ, MTLT335);
+}
+
+
+/******************************************************************************
+ * @brief
+ * @param accels [in]
+ * @param rates [in]
+ * @param mags [in]
+ * @param gps [in]
+ * @param odo [in]
+ * @param ppsDetected [in]
+ *
+ ******************************************************************************/
+void RunUserNavAlgorithm(float64_t accels[],
+ float64_t rates[],
+ float64_t mags[],
+ gpsDataStruct_t* const gps,
+ odoDataStruct_t* const odo,
+ BOOL const ppsDetected)
+{
+ // Populate the EKF input data structure
+ EKF_SetInputStruct(accels, rates, mags, gps, odo, ppsDetected);
+
+ // Call the desired algorithm based on the EKF with different
+ // calling rates and different settings.
+ Algorithm();
+
+ // Fill the output data structure with the EKF states and other
+ // desired information
+ EKF_SetOutputStruct();
+
+}
diff --git a/examples/OpenIMU335RI/VG/src/user/UserAlgorithm.h b/examples/OpenIMU335RI/VG/src/user/UserAlgorithm.h
new file mode 100644
index 0000000..729e8df
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/user/UserAlgorithm.h
@@ -0,0 +1,29 @@
+/*
+ * File: UserAlgorithm.h
+ * Author: joemotyka
+ *
+ * Created on June 28, 2018, 12:23 AM
+ */
+
+#ifndef USER_ALGORITHM_H
+#define USER_ALGORITHM_H
+
+#include
+
+ // IMU data structure
+typedef struct {
+ // Timer output counter
+// uint32_t timerCntr, dTimerCntr;
+
+ // Algorithm states
+ float64_t accel_g[3];
+ float64_t rate_radPerSec[3];
+ float64_t rate_degPerSec[3];
+ float64_t mag_G[3];
+ float64_t temp_C;
+} IMUDataStruct;
+
+extern IMUDataStruct gIMU;
+
+#endif /* _USER_ALGORITHM_H_ */
+
diff --git a/examples/OpenIMU335RI/VG/src/user/UserConfigurationUart.c b/examples/OpenIMU335RI/VG/src/user/UserConfigurationUart.c
new file mode 100644
index 0000000..7148468
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/user/UserConfigurationUart.c
@@ -0,0 +1,602 @@
+/** ***************************************************************************
+ * @file UserConfiguration.c
+ *
+ * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ ******************************************************************************/
+/*******************************************************************************
+Copyright 2018 ACEINNA, INC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*******************************************************************************/
+
+#include "string.h"
+#include "magAPI.h"
+#include "configurationAPI.h"
+#include "UserConfigurationUart.h"
+#include "UserMessagingUART.h"
+#include "Indices.h"
+#include "eepromAPI.h"
+#include "EcuSettings.h"
+
+uint8_t UserDataBuffer[4096];
+
+
+/*******************************************
+ * @brief
+ *
+ * @param pSettings ==
+********************************************/
+void GetCurrentUartSettings(userUartConfig_t *pSettings)
+{
+ memcpy(pSettings, pUserUartConfig, sizeof(userUartConfig_t));
+}
+
+/*******************************************
+ * @brief
+ *
+ * @param pSettings ==
+********************************************/
+void FillCurrentUartSettings(userUartConfig_t *pSettings)
+{
+ memcpy(pUserUartConfig, pSettings, sizeof(userUartConfig_t));
+}
+
+
+/** ***************************************************************************
+ * @name UpdateUserUartParameter - updating of uart configuration parameter based of user preferences
+ * @brief
+ *
+ * @param [in] number - parameter number in user configuration structure
+ * @param [in] data - value of the parameter in little endian format
+ * @retval error (1), no error (0)
+ ******************************************************************************/
+// NEEDS TO BE CHECKED
+BOOL UpdateUserUartParameter(uint32_t number, uint64_t data, BOOL fApply)
+{
+ BOOL result = TRUE;
+ uint64_t *ptr = (uint64_t *)pUserUartConfig;
+
+ if(number < USER_UART_START || number >= USER_UART_MAX_PARAM ){
+ return FALSE;
+ }
+
+ switch (number) {
+ case USER_UART_BAUD_RATE:
+ result = config_SetBaudRate((int32_t)data, fApply);
+ if(result){
+ pUserUartConfig->userUartBaudRate = (int32_t)data;
+ }
+ break;
+ case USER_UART_PACKET_TYPE:
+ result = SetUserPacketType((uint8_t*)&data, fApply);
+ if(result){
+ *(uint64_t*)pUserUartConfig->userPacketType = data;
+ }
+ break;
+ case USER_UART_PACKET_RATE:
+ result = config_SetPacketRate((uint32_t)data, fApply);
+ if(result){
+ pUserUartConfig->userPacketRate = (int32_t)data;
+ }
+ break;
+ case USER_UART_LPF_ACCEL_TYPE:
+ result = config_SelectUserLPFilter(ACCEL_SENSOR, (int32_t)data, TRUE);
+ if(result){
+ pUserUartConfig->lpfAccelFilterFreq = (int32_t)data;
+ }
+ break;
+ case USER_UART_LPF_RATE_TYPE:
+ result = config_SelectUserLPFilter(RATE_SENSOR, (int32_t)data, TRUE);
+ if(result){
+ pUserUartConfig->lpfRateFilterFreq = (int32_t)data;
+ }
+ break;
+ case USER_UART_ORIENTATION:
+ result = ApplyUserUartOrientation((uint16_t*)&data, TRUE);
+ if(result){
+ *(int64_t*)pUserUartConfig->orientation = data;
+ }
+ break;
+ // case USER_XXX: add function calls here if parameter XXXX
+ // required be updated on the fly
+ // break;
+ default:
+ result = TRUE;
+ break;
+ }
+
+ if(result == TRUE){
+ ptr[number] = data;
+ }
+
+ return result;
+}
+
+
+void UserInitConfigureUart()
+{
+
+ uint64_t *ptr = (uint64_t*)pUserUartConfig;
+
+ // apply UART parameters to the platform
+ for(int i = USER_UART_BAUD_RATE; i <= USER_UART_PACKET_RATE; i++){
+ UpdateUserUartParameter(i, ptr[i], TRUE);
+ }
+ // Fill parameters for UART communication
+ BackFillUartDataStructure();
+
+}
+
+/*******************************************
+ * @brief
+ *
+ * @param pld ==
+ * @param payloadLen ==
+ * @return BOOL
+********************************************/
+BOOL UpdateUserUartConfig(userConfigPayload* pld, uint8_t *payloadLen)
+{
+ uint32_t offset, i;
+ BOOL offsetValid = TRUE;
+ BOOL lenValid = TRUE;
+ BOOL numValid = TRUE;
+ BOOL ret = TRUE;
+ int32_t result = 0;
+
+ // Validate parameters numbers and quantity
+ if(pld->numParams >= USER_UART_MAX_PARAM){
+ lenValid = FALSE;
+ result = INVALID_PAYLOAD_SIZE;
+ }
+
+
+ if((pld->numParams + pld->paramOffset) >= USER_UART_MAX_PARAM){
+ numValid = FALSE;
+ result = INVALID_PARAM;
+ }
+
+ if(offsetValid && numValid && lenValid){
+ // Validate parameters values first
+ offset = pld->paramOffset;
+ for (i = 0; i < pld->numParams && ret; i++){
+ ret = UpdateUserUartParameter(offset, pld->parameters[i], FALSE);
+ offset++;
+ }
+ if(ret == TRUE){
+ // Apply parameters values here
+ offset = pld->paramOffset;
+ for (i = 0; i < pld->numParams; i++){
+ ret = UpdateUserUartParameter(offset, pld->parameters[i], TRUE);
+ offset++;
+ }
+ }
+ }
+
+ if(ret == FALSE){
+ result = INVALID_VALUE;
+ }
+
+ pld->numParams = result;
+ *payloadLen = 4;
+
+ return TRUE;
+}
+
+/*******************************************
+ * @brief
+ *
+ * @param pld ==
+ * @param payloadLen ==
+ * @return BOOL
+********************************************/
+BOOL UpdateUserUartParam(userParamPayload* pld, uint8_t *payloadLen)
+{
+ BOOL offsetValid;
+ BOOL ret = TRUE;
+ int32_t result = 0;
+
+ offsetValid = pld->paramNum <= USER_UART_MAX_PARAM;
+
+ if(offsetValid){
+ // Validate parameter first
+ ret = UpdateUserUartParameter(pld->paramNum, pld->parameter, FALSE);
+ if(ret == TRUE){
+ // Apply parameter if valid
+ ret = UpdateUserUartParameter(pld->paramNum, pld->parameter, TRUE);
+ }else{
+ result = INVALID_VALUE;
+ }
+ } else {
+ result = INVALID_PARAM;
+ }
+
+ pld->paramNum = result;
+ *payloadLen = 4;
+
+ return TRUE;
+}
+
+
+/** ****************************************************************************
+ * @name UpdateAllUserParams
+ * @brief writes user data into user configuration structure, validates data if
+ * required, updates system parameters
+ *
+ * @param [in] pointer to userData payload in the packet
+ * @retval N/A
+ ******************************************************************************/
+BOOL UpdateAllUserUartParams(allUserParamsPayload* pld, uint8_t *payloadLen)
+{
+ uint32_t offset, i;
+ BOOL numValid = TRUE;
+ BOOL ret = TRUE;
+ int32_t result = 0;
+
+ int numParams = (*payloadLen)/8;
+
+ if(numParams > USER_UART_MAX_PARAM){
+ numValid = FALSE;
+ result = INVALID_PAYLOAD_SIZE;
+ }
+
+
+ if(numValid){
+ // Validate parameters here
+ offset = 0;
+ for (i = 0; i < numParams && ret; i++){
+ ret = UpdateUserUartParameter(offset, pld->parameters[i], FALSE);
+ offset++;
+ }
+ if(ret == TRUE){
+ // Apply parameters here
+ offset = 0;
+ for (i = 0; i < numParams; i++){
+ UpdateUserUartParameter(offset, pld->parameters[i], TRUE);
+ offset++;
+ }
+ }
+ }
+
+ if(ret == FALSE){
+ result = INVALID_VALUE;
+ }
+
+ pld->parameters[0] = result;
+ *payloadLen = 4; // return error code
+
+ return TRUE;
+
+}
+
+
+
+/*******************************************************************************
+ * @name GetUserUartConfig
+ * @brief Retrieves specified number of user configuration parameters data for
+ * sending to the external host starting from specified offset in user
+ * configuration structure (refer to UserConfigParamOffset structure for
+ * specific value of offsets)
+ * @param [in] pointer to userData payload in the packet
+ * @retval N/A
+ ******************************************************************************/
+BOOL GetUserUartConfig(userConfigPayload* pld, uint8_t *payloadLen)
+{
+ uint32_t offset, i;
+ BOOL lenValid = TRUE;
+ uint64_t *ptr = (uint64_t *)pUserUartConfig;
+
+ lenValid = (pld->numParams + pld->paramOffset) <= USER_UART_MAX_PARAM;
+
+ if(lenValid){
+ offset = pld->paramOffset;
+ for (i = 0; i < pld->numParams; i++, offset++)
+ {
+ pld->parameters[i] = ptr[offset];
+ }
+ *payloadLen = (pld->numParams + 1) * 8;
+ } else {
+ *payloadLen = 4;
+ pld->numParams = INVALID_PARAM;
+ }
+
+ return TRUE;
+
+}
+
+/*******************************************
+ * @brief Get the User Param object
+ *
+ * @param pld ==
+ * @param payloadLen ==
+ * @return BOOL
+********************************************/
+BOOL GetUserUartParam(userParamPayload* pld, uint8_t *payloadLen)
+{
+ uint32_t offset;
+ BOOL offsetValid;
+ uint64_t *ptr = (uint64_t *)pUserUartConfig;
+
+ offsetValid = pld->paramNum < USER_UART_MAX_PARAM;
+
+ if(offsetValid){
+ offset = pld->paramNum;
+ pld->parameter = ptr[offset];
+ *payloadLen = 8 + 4; // parameter + number
+ } else {
+ *payloadLen = 4; // number
+ pld->paramNum = INVALID_PARAM; // invalid
+ }
+
+ return TRUE;
+
+}
+
+/*******************************************
+ * @brief Get the All User Params object
+ *
+ * @param pld ==
+ * @param payloadLen ==
+ * @return BOOL
+********************************************/
+BOOL GetAllUserUartParams(allUserParamsPayload* pld, uint8_t *payloadLen)
+{
+ uint32_t offset, i, numParams;
+ uint64_t *ptr = (uint64_t *)pUserUartConfig;
+
+ numParams = USER_UART_MAX_PARAM;
+
+ offset = 0;
+
+ for (i = 0; i < numParams; i++, offset++){
+ pld->parameters[i] = ptr[offset];
+ }
+
+ *payloadLen = numParams* 8;
+
+ return TRUE;
+}
+
+
+/*******************************************
+ * @brief
+ *
+ * @param input ==
+ * @param fApply ==
+ * @return BOOL
+********************************************/
+BOOL ApplyUserUartOrientation(uint16_t *input, BOOL fApply)
+{
+ BOOL res;
+ uint32_t orientation = 0;
+ uint16_t sel;
+ volatile int i,j;
+
+ for(i = FORWARD; i <= DOWN; i++){
+ sel = input[i];
+ j = i;
+ switch(sel){
+ case PLUS_X:
+ switch(j){
+ case FORWARD:
+ orientation |= FWD_X_PLUS_MASK;
+ break;
+ case RIGHT:
+ orientation |= RIGHT_X_PLUS_MASK;
+ break;
+ case DOWN:
+ orientation |= DOWN_X_PLUS_MASK;
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+ case PLUS_Y:
+ switch(j){
+ case FORWARD:
+ orientation |= FWD_Y_PLUS_MASK;
+ break;
+ case RIGHT:
+ orientation |= RIGHT_Y_PLUS_MASK;
+ break;
+ case DOWN:
+ orientation |= DOWN_Y_PLUS_MASK;;
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+ case PLUS_Z:
+ switch(j){
+ case FORWARD:
+ orientation |= FWD_Z_PLUS_MASK;
+ break;
+ case RIGHT:
+ orientation |= RIGHT_Z_PLUS_MASK;
+ break;
+ case DOWN:
+ orientation |= DOWN_Z_PLUS_MASK;
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+ case MINUS_X:
+ switch(j){
+ case FORWARD:
+ orientation |= FWD_X_MINUS_MASK;
+ break;
+ case RIGHT:
+ orientation |= RIGHT_X_MINUS_MASK;
+ break;
+ case DOWN:
+ orientation |= DOWN_X_MINUS_MASK;
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+ case MINUS_Y:
+ switch(j){
+ case FORWARD:
+ orientation |= FWD_Y_MINUS_MASK;
+ break;
+ case RIGHT:
+ orientation |= RIGHT_Y_MINUS_MASK;
+ break;
+ case DOWN:
+ orientation |= DOWN_Y_MINUS_MASK;
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+ case MINUS_Z:
+ switch(j){
+ case FORWARD:
+ orientation |= FWD_Z_MINUS_MASK;
+ break;
+ case RIGHT:
+ orientation |= RIGHT_Z_MINUS_MASK;
+ break;
+ case DOWN:
+ orientation |= DOWN_Z_MINUS_MASK;
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+
+ }
+
+ res = config_ApplyOrientation(orientation, fApply);
+
+ if (res == FALSE || !fApply) {
+ return res;
+ }
+
+ return TRUE;
+
+}
+
+/*******************************************
+ * @brief
+ *
+ * @param asciiOrien ==
+ * @return BOOL
+********************************************/
+BOOL OrientationToAscii(uint8_t *asciiOrien)
+{
+
+ uint64_t orientation = 0LL;
+
+ uint16_t tmp = config_GetOrientation();
+ uint16_t fwdSign;
+ uint16_t rightSign;
+ uint16_t downSign;
+ uint16_t fwdAxis;
+ uint16_t rightAxis;
+ uint16_t downAxis;
+
+// Forward axis
+ fwdSign = tmp & 0x0001U;
+
+ if(fwdSign == 0){
+ fwdSign = 0x2B;
+ }else {
+ fwdSign = 0x2D;
+ }
+ fwdAxis = (tmp >> 1U) & 0x0003U;
+
+ switch(fwdAxis){
+ case 0:
+ fwdAxis = 0x58; // X
+ break;
+ case 1:
+ fwdAxis = 0x59; // Y
+ break;
+ case 2:
+ fwdAxis = 0x5A; // Z
+ break;
+ case 3:
+ return FALSE; // invalid
+ }
+
+// Right axis
+
+ rightSign = (tmp >> 3U) & 0x0001U;
+ rightAxis = (tmp >> 4U) & 0x0003U;
+
+ if(rightSign == 0){
+ rightSign = 0x2B;
+ }else {
+ rightSign = 0x2D;
+ }
+
+ switch(rightAxis){
+ case 0:
+ rightAxis = 0x59; // Y
+ break;
+ case 1:
+ rightAxis = 0x5A; // Z
+ break;
+ case 2:
+ rightAxis = 0x58; // X
+ break;
+ case 3:
+ return FALSE; // invalid
+ }
+
+// Down axis
+ downSign = (tmp >> 6U) & 0x0001U;
+ downAxis = (tmp >> 7U) & 0x0003U;
+
+ if(downSign == 0){
+ downSign = 0x2B;
+ }else {
+ downSign = 0x2D;
+ }
+
+ switch(downAxis){
+ case 0:
+ downAxis = 0x5A; // Z
+ break;
+ case 1:
+ downAxis = 0x58; // X
+ break;
+ case 2:
+ downAxis = 0x59; // Y
+ break;
+ case 3:
+ return FALSE; // invalid
+ }
+
+ orientation = ((uint64_t)fwdSign) |
+ ((uint64_t)fwdAxis << 8) |
+ ((uint64_t)rightSign << 16) |
+ ((uint64_t)rightAxis << 24) |
+ ((uint64_t)downSign << 32) |
+ ((uint64_t)downAxis << 40) ;
+
+ memcpy(asciiOrien, (uint8_t *)&orientation, 8);
+ return TRUE;
+
+}
+
+
diff --git a/examples/OpenIMU335RI/VG/src/user/UserConfigurationUart.h b/examples/OpenIMU335RI/VG/src/user/UserConfigurationUart.h
new file mode 100644
index 0000000..31249cb
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/user/UserConfigurationUart.h
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * File: UserConfigurationUart.h
+ * Created on Jan 25, 2020
+ ******************************************************************************/
+/*******************************************************************************
+Copyright 2020 ACEINNA, INC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*******************************************************************************/
+
+#ifndef USER_CONFIGURATION_UART_H
+#define USER_CONFIGURATION_UART_H
+
+#include
+
+
+/// User defined configuration strucrture
+///Please notice, that parameters are 64 bit to accomodate double types as well as longer string types
+
+typedef struct {
+ int64_t reserved[2];
+ int64_t userUartBaudRate; /// baudrate of user UART, bps.
+ /// valid options are:
+ /// 4800
+ /// 9600
+ /// 19200
+ /// 38400
+ /// 57600
+ /// 115200
+ /// 230400
+ uint8_t userPacketType[8]; /// User packet to be continiously sent by unit
+ /// Packet types defined in structure UserOutPacketType
+ /// in file UserMessaging.h
+
+ int64_t userPacketRate; /// Packet rate for continiously output packet, Hz.
+ /// Valid settings are: 0 ,2, 5, 10, 20, 25, 50, 100, 200
+
+ int64_t lpfAccelFilterFreq; /// built-in lpf filter cutoff frequency selection for accelerometers
+ int64_t lpfRateFilterFreq; /// built-in lpf filter cutoff frequency selection for rate sensors
+ /// Options are:
+ /// 0 - Filter turned off
+ /// 50 - Butterworth LPF 50HZ
+ /// 20 - Butterworth LPF 20HZ
+ /// 10 - Butterworth LPF 10HZ
+ /// 05 - Butterworth LPF 5HZ
+ /// 02 - Butterworth LPF 2HZ
+ /// 25 - Butterworth LPF 25HZ
+ /// 40 - Butterworth LPF 40HZ
+
+ uint8_t orientation[8];
+
+
+ //***************************************************************************************
+ // here is the border between arbitrary parameters and platform configuration parameters
+ //***************************************************************************************
+
+ // place new arbitrary configuration parameters here
+ // parameter size should even to 8 bytes
+ // Add parameter offset in UserConfigParamOffset structure if validation or
+ // special processing required
+
+} userUartConfig_t;
+
+extern userUartConfig_t *pUserUartConfig;
+
+enum{
+//*****************************************************************************************
+// These parateters are not saved into eeprom as of yet
+ USER_UART_START , // 0
+ USER_UART_RSVD , // 1
+ USER_UART_BAUD_RATE , // 2
+ USER_UART_PACKET_TYPE , // 3
+ USER_UART_PACKET_RATE , // 4
+ USER_UART_LPF_ACCEL_TYPE , // 5 prefered LPF filter type for accelerometer
+ USER_UART_LPF_RATE_TYPE , // 6 prefered LPF filter type for rate sensor
+ USER_UART_ORIENTATION , // 7 unit orientation
+ USER_UART_MAX_PARAM // 8
+};
+
+extern int userPacketOut;
+
+#define USER_OK 0x00
+#define USER_NAK 0x80
+#define USER_INVALID 0x81
+
+#define FORWARD 0
+#define RIGHT 1
+#define DOWN 2
+
+
+#define PLUS_X 0x582B
+#define PLUS_Y 0x592B
+#define PLUS_Z 0x5A2B
+#define MINUS_X 0x582D
+#define MINUS_Y 0x592D
+#define MINUS_Z 0x5A2D
+
+
+#define FWD_X_PLUS_MASK 0x00000000
+#define FWD_X_MINUS_MASK 0x00000001
+#define FWD_Y_PLUS_MASK 0x00000002
+#define FWD_Y_MINUS_MASK 0x00000003
+#define FWD_Z_PLUS_MASK 0x00000004
+#define FWD_Z_MINUS_MASK 0x00000005
+
+#define RIGHT_X_PLUS_MASK 0x00000020
+#define RIGHT_X_MINUS_MASK 0x00000028
+#define RIGHT_Y_PLUS_MASK 0x00000000
+#define RIGHT_Y_MINUS_MASK 0x00000008
+#define RIGHT_Z_PLUS_MASK 0x00000010
+#define RIGHT_Z_MINUS_MASK 0x00000018
+
+#define DOWN_X_PLUS_MASK 0x00000080
+#define DOWN_X_MINUS_MASK 0x000000C0
+#define DOWN_Y_PLUS_MASK 0x00000100
+#define DOWN_Y_MINUS_MASK 0x00000140
+#define DOWN_Z_PLUS_MASK 0x00000000
+#define DOWN_Z_MINUS_MASK 0x00000040
+
+BOOL ApplyUserUartOrientation(uint16_t *input, BOOL fApply);
+void GetCurrentUartSettings(userUartConfig_t *pSettings);
+void UserInitConfigureUart();
+void FillCurrentUartSettings(userUartConfig_t *pSettings);
+void BackFillUartDataStructure();
+
+#endif /* USER_CONFIGURATION_UART_H */
+
+
diff --git a/examples/OpenIMU335RI/VG/src/user/UserMessagingUART.c b/examples/OpenIMU335RI/VG/src/user/UserMessagingUART.c
new file mode 100644
index 0000000..6dbd4ae
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/user/UserMessagingUART.c
@@ -0,0 +1,420 @@
+/** ***************************************************************************
+ * @file UserConfiguration.c
+ *
+ * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ ******************************************************************************/
+/*******************************************************************************
+Copyright 2018 ACEINNA, INC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*******************************************************************************/
+
+#include
+#include
+#include
+
+#include "algorithmAPI.h"
+#include "sensorsAPI.h"
+#include "userAPI.h"
+#include "appVersion.h"
+
+#include "UserMessagingUART.h"
+#include "UserConfigurationUart.h"
+
+#include "Indices.h" // For X_AXIS, etc
+#include "CommonMessages.h"
+#include "configurationAPI.h"
+#include "halAPI.h"
+#include "EcuSettings.h"
+
+
+
+
+/// List of allowed packet codes
+usr_packet_t userInputPackets[] = {
+ {USR_IN_NONE, {0,0}},
+ {USR_IN_PING, "pG"},
+ {USR_IN_UPDATE_CONFIG, "uC"},
+ {USR_IN_UPDATE_PARAM, "uP"},
+ {USR_IN_UPDATE_ALL, "uA"},
+ {USR_IN_SAVE_CONFIG, "sC"},
+ {USR_IN_GET_CONFIG, "gC"},
+ {USR_IN_GET_PARAM, "gP"},
+ {USR_IN_GET_ALL, "gA"},
+ {USR_IN_GET_VERSION, "gV"},
+ {USR_IN_RESET, "rS"},
+// place new input packet code here, before USR_IN_MAX
+ {USR_IN_MAX, {0xff, 0xff}}, // ""
+};
+
+
+// packet codes here should be unique -
+// should not overlap codes for input packets and system packets
+// First byte of Packet code should have value >= 0x61
+usr_packet_t userOutputPackets[] = {
+// Packet Type Packet Code
+ {USR_OUT_NONE, {0x00, 0x00}},
+ {USR_OUT_TEST, "zT"},
+ {USR_OUT_DATA1, "z1"},
+ {USR_OUT_DATA2, "z2"},
+// place new type and code here
+ {USR_OUT_SCALED1, "s1"},
+ {USR_OUT_ANG1, "a1"},
+ {USR_OUT_ANG2, "a2"},
+ {USR_OUT_AID1, "d1"},
+ {USR_OUT_AID2, "d2"},
+ {USR_OUT_AID3, "d3"},
+ {USR_OUT_MAX, {0xff, 0xff}}, // ""
+};
+
+volatile char *info;
+static int _userPayloadLen = 0;
+static int _outputPacketType = USR_OUT_MAX;
+static int _inputPacketType = USR_IN_MAX;
+
+
+/*******************************************
+ * @brief
+ *
+ * @param receivedCode ==
+ * @return int
+********************************************/
+int32_t CheckUserPacketType(uint16_t receivedCode)
+{
+ int res = UCB_ERROR_INVALID_TYPE;
+ usr_packet_t *packet = &userInputPackets[1];
+ uint16_t code;
+
+ // validate packet code here and memorise for further processing
+ while(packet->packetType != USR_IN_MAX){
+ code = (packet->packetCode[0] << 8) | packet->packetCode[1];
+ if(code == receivedCode){
+ _inputPacketType = packet->packetType;
+ return UCB_USER_IN;
+ }
+ packet++;
+ }
+
+ packet = &userOutputPackets[1];
+
+ // validate packet code here and memorize for further processing
+ while(packet->packetType != USR_OUT_MAX){
+ code = (packet->packetCode[0] << 8) | packet->packetCode[1];
+ if(code == receivedCode){
+ _outputPacketType = packet->packetType;
+ return UCB_USER_OUT;
+ }
+ packet++;
+ }
+
+ return res;
+}
+
+
+void UserPacketTypeToBytes(uint8_t bytes[])
+{
+ if(_inputPacketType && _inputPacketType < USR_IN_MAX){
+ // response to request. Return same packet code
+ bytes[0] = userInputPackets[_inputPacketType].packetCode[0];
+ bytes[1] = userInputPackets[_inputPacketType].packetCode[1];
+ _inputPacketType = USR_IN_MAX; // wait for next input packet
+ return;
+ }
+
+ if(_outputPacketType && _outputPacketType < USR_OUT_MAX){
+ // continuous packet
+ bytes[0] = userOutputPackets[_outputPacketType].packetCode[0];
+ bytes[1] = userOutputPackets[_outputPacketType].packetCode[1];
+ }else {
+ bytes[0] = 0;
+ bytes[1] = 0;
+ }
+
+}
+
+
+/** ***************************************************************************
+ * @name setUserPacketType - set user output packet type
+ * @brief
+ * @param [in] packet type
+ * @retval - TRUE if success, FALSE otherwise
+ ******************************************************************************/
+BOOL SetUserPacketType(uint8_t *data, BOOL fApply)
+{
+ int type = -1;
+ uint16_t *code = (uint16_t*)data;
+ uint16_t tmp;
+ BOOL result = TRUE;
+
+ usr_packet_t *packet = &userOutputPackets[1];
+ for(int i = 0; i < USR_OUT_MAX; i++, packet++){
+ if(*code == *((uint16_t*)packet->packetCode)){
+ type = packet->packetType;
+ break;
+ }
+ }
+
+ switch(type){
+ case USR_OUT_TEST: // simple test packet to check communication
+ _outputPacketType = type;
+ _userPayloadLen = USR_OUT_TEST_PAYLOAD_LEN;
+ break;
+ case USR_OUT_DATA1: // packet with sensors data. Change at will
+ _outputPacketType = type;
+ _userPayloadLen = USR_OUT_DATA1_PAYLOAD_LEN;
+ break;
+ case USR_OUT_DATA2: // packet with arbitrary data
+ _outputPacketType = type;
+ _userPayloadLen = sizeof(data2_payload_t);
+ break;
+ case USR_OUT_SCALED1: // packet with arbitrary data
+ _outputPacketType = type;
+ _userPayloadLen = USR_OUT_SCALED1_PAYLOAD_LEN;
+ case USR_OUT_ANG1: // packet with sensors data. Change at will
+ _outputPacketType = type;
+ _userPayloadLen = USR_OUT_ANG1_PAYLOAD_LEN;
+ break;
+ case USR_OUT_ANG2: // packet with sensors data. Change at will
+ _outputPacketType = type;
+ _userPayloadLen = USR_OUT_ANG2_PAYLOAD_LEN;
+ break;
+ case USR_OUT_AID1:
+ _outputPacketType = type;
+ _userPayloadLen = USR_OUT_AID1_PAYLOAD_LEN;
+ break;
+ case USR_OUT_AID2:
+ _outputPacketType = type;
+ _userPayloadLen = USR_OUT_AID2_PAYLOAD_LEN;
+ break;
+ case USR_OUT_AID3:
+ _outputPacketType = type;
+ _userPayloadLen = USR_OUT_AID3_PAYLOAD_LEN;
+ break;
+ default:
+ result = FALSE;
+ break;
+ }
+
+ if(result == FALSE){
+ return FALSE;
+ }
+
+ tmp = (data[0] << 8) | data[1];
+
+ result = config_SetOutputPacketCode(tmp, fApply);
+
+ return result;
+}
+
+
+/** ***************************************************************************
+ * @name getUserPayloadLength - get user payload length for sanity check
+ * @brief
+ *
+ * @retval - user payload length
+ ******************************************************************************/
+int32_t GetUserPayloadLength(void)
+{
+ // ATTENTION: return actual user payload length, if user packet used
+ return _userPayloadLen;
+}
+
+/*******************************************
+ * @brief
+ *
+ * @param ptrUcbPacket ==
+ * @return int
+********************************************/
+int32_t HandleUserInputPacket(UcbPacketStruct *ptrUcbPacket)
+{
+ BOOL valid = TRUE;
+ int ret = USER_PACKET_OK;
+
+ // Fill existing data before update
+ BackFillUartDataStructure();
+
+ /// call appropriate function based on packet type
+ switch (_inputPacketType) {
+ case USR_IN_RESET:
+ HW_SystemReset();
+ break;
+ case USR_IN_PING:
+ {
+ uint8_t len;
+ Fill_PingPacketPayload(ptrUcbPacket->payload, &len);
+ ptrUcbPacket->payloadLength = len;
+ }
+ // leave all the same - it will be bounced back unchanged
+ break;
+ case USR_IN_GET_VERSION:
+ {
+ uint8_t len;
+ Fill_VersionPacketPayload(ptrUcbPacket->payload, &len);
+ ptrUcbPacket->payloadLength = len;
+ }
+ break;
+ case USR_IN_SAVE_CONFIG:
+ // payload length does not change
+ if(!SaveEcuSettings(FALSE, TRUE)){
+ valid = FALSE;
+ }
+ break;
+ case USR_IN_UPDATE_CONFIG:
+ UpdateUserUartConfig((userConfigPayload*)ptrUcbPacket->payload, &ptrUcbPacket->payloadLength);
+ break;
+ case USR_IN_UPDATE_PARAM:
+ UpdateUserUartParam((userParamPayload*)ptrUcbPacket->payload, &ptrUcbPacket->payloadLength);
+ break;
+ case USR_IN_UPDATE_ALL:
+ UpdateAllUserUartParams((allUserParamsPayload*)ptrUcbPacket->payload, &ptrUcbPacket->payloadLength);
+ break;
+ case USR_IN_GET_CONFIG:
+ if(!GetUserUartConfig((userConfigPayload*)ptrUcbPacket->payload, &ptrUcbPacket->payloadLength)){
+ valid = FALSE;
+ }
+ break;
+ case USR_IN_GET_PARAM:
+ if(!GetUserUartParam((userParamPayload*)ptrUcbPacket->payload, &ptrUcbPacket->payloadLength)){
+ valid = FALSE;
+ }
+ break;
+ case USR_IN_GET_ALL:
+ if(!GetAllUserUartParams((allUserParamsPayload*)ptrUcbPacket->payload, &ptrUcbPacket->payloadLength)){
+ valid = FALSE;
+ }
+ break;
+ default:
+ /// default handler - unknown packet
+ valid = FALSE;
+ break;
+ }
+
+ if(!valid){
+ ptrUcbPacket->payloadLength = 0;
+ ret = USER_PACKET_ERROR;
+ }
+
+ ptrUcbPacket->packetType = UCB_USER_OUT; // do not remove - done for proper packet routing
+
+ return ret;
+}
+
+
+/******************************************************************************
+ * @name HandleUserOutputPacket - API call ro prepare continuous user output packet
+ * @brief general handler
+ * @param [in] payload pointer to put user data to
+ * @param [in/out] number of bytes in user payload
+ * @retval N/A
+ ******************************************************************************/
+BOOL HandleUserOutputPacket(uint8_t *payload, uint8_t *payloadLen)
+{
+ static uint32_t _testVal = 0;
+ static uint64_t ppsTstamp = 0;
+ BOOL ret = TRUE;
+
+ switch (_outputPacketType) {
+ case USR_OUT_TEST:
+ {
+ uint32_t *testParam = (uint32_t*)(payload);
+ *payloadLen = USR_OUT_TEST_PAYLOAD_LEN;
+ *testParam = _testVal++;
+ }
+ break;
+
+ case USR_OUT_DATA1:
+ {
+ uint8_t len;
+ Fill_z1PacketPayload(payload, &len);
+ *payloadLen = len;
+ }
+ break;
+ case USR_OUT_DATA2:
+ {
+ data2_payload_t *pld = (data2_payload_t *)payload;
+ pld->timer = TIMER_GetCurrTimeStamp()/1000; // in miliseconds
+ pld->c = 'A';
+ pld->s = 1234;
+ pld->i = -5;
+ ppsTstamp = TIMER_GetCurrTimeStamp()/1000000; // in seconds
+ pld->ll = ppsTstamp; // time stamp of last PPS edge in microseconds from system start
+ pld->d = 1.23456789;
+ *payloadLen = sizeof(data2_payload_t);
+ }
+ break;
+ case USR_OUT_SCALED1:
+ {
+ uint8_t len;
+ Fill_s1PacketPayload(payload, &len);
+ *payloadLen = len;
+ }
+ break;
+ case USR_OUT_ANG1:
+ {
+ // Variables used to hold the EKF values
+ uint8_t len;
+ Fill_a1PacketPayload(payload, &len);
+ *payloadLen = len;
+ }
+ break;
+ case USR_OUT_ANG2:
+ {
+ uint8_t len;
+
+ Fill_a2PacketPayload(payload, &len);
+ *payloadLen = len;
+ }
+ break;
+ // place additional user packet preparing calls here
+ // case USR_OUT_XXXX:
+ // *payloadLen = YYYY; // total user payload length, including user packet type
+ // payload[0] = ZZZZ; // user packet type
+ // prepare dada here
+ // break;
+
+ case USR_OUT_AID1:
+ {
+ uint8_t len;
+ Fill_d1PacketPayload(payload, &len);
+ *payloadLen = len;
+ break;
+ }
+ case USR_OUT_AID2:
+ {
+ uint8_t len;
+ Fill_d2PacketPayload(payload, &len);
+ *payloadLen = len;
+ break;
+ }
+ case USR_OUT_AID3:
+ {
+ uint8_t len;
+ Fill_d3PacketPayload(payload, &len);
+ *payloadLen = len;
+ break;
+ }
+ default:
+ {
+ *payloadLen = 0;
+ ret = FALSE;
+ }
+ break; /// unknown user packet, will send error in response
+ }
+
+ return ret;
+}
+
diff --git a/examples/OpenIMU335RI/VG/src/user/UserMessagingUART.h b/examples/OpenIMU335RI/VG/src/user/UserMessagingUART.h
new file mode 100644
index 0000000..bbbbbb8
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/user/UserMessagingUART.h
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * File: UserConfiguration.h
+ * Created on Jan 25, 2017
+ ******************************************************************************/
+/*******************************************************************************
+Copyright 2018 ACEINNA, INC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*******************************************************************************/
+
+#ifndef _USER_MESSAGING_UART_H
+#define _USER_MESSAGING_UART_H
+
+#include
+
+#include "GlobalConstants.h"
+#include "serialAPI.h"
+
+#define USER_PACKET_OK 0
+#define UNKNOWN_USER_PACKET 1
+#define USER_PACKET_ERROR 2
+
+// here is definition for packet rate divider
+// considering that data acquisition task runs at 200 Hz
+typedef enum {
+ PACKET_RATE_INVALID = -1,
+ PACKET_RATE_QUIET = 0, // quiet mode
+ PACKET_RATE_200HZ = 200, // packet rate 200 Hz
+ PACKET_RATE_100HZ = 100, // packet rate 100 Hz
+ PACKET_RATE_50HZ = 50, // packet rate 50 Hz
+ PACKET_RATE_25HZ = 25, // packet rate 25 Hz
+ PACKET_RATE_20HZ = 20, // packet rate 20 Hz
+ PACKET_RATE_10HZ = 10, // packet rate 10 Hz
+ PACKET_RATE_5HZ = 5, // packet rate 5 Hz
+ PACKET_RATE_2HZ = 2, // packet rate 2 Hz
+ PACKET_RATE_1HZ = 1, // packet rate 1 Hz
+} packet_rate_t;
+
+
+// User Input packet payload has next structure:
+// number offset
+// of of first
+// parameters parameter
+// U2 U2 U4/I4/F
+// XXXX YYYY [parameters]
+// User input packet codes, change at will
+typedef enum {
+ USR_IN_NONE = 0 ,
+ USR_IN_PING ,
+ USR_IN_UPDATE_CONFIG ,
+ USR_IN_UPDATE_PARAM ,
+ USR_IN_UPDATE_ALL ,
+ USR_IN_SAVE_CONFIG ,
+ USR_IN_GET_CONFIG ,
+ USR_IN_GET_PARAM ,
+ USR_IN_GET_ALL ,
+ USR_IN_GET_VERSION ,
+ USR_IN_RESET ,
+ // add new packet type here, before USR_IN_MAX
+ USR_IN_MAX ,
+}UserInPacketType;
+
+// User output packet codes, change at will
+typedef enum {
+ USR_OUT_NONE = 0, // 0
+ USR_OUT_TEST, // 1
+ USR_OUT_DATA1, // 2
+ USR_OUT_DATA2, // 3
+// add new output packet type here, before USR_OUT_MAX
+ USR_OUT_SCALED1, // 4
+ USR_OUT_ANG1, // 5
+ USR_OUT_ANG2, // 6
+ USR_OUT_AID1, // 7
+ USR_OUT_AID2, // 8
+ USR_OUT_AID3, // 9
+ USR_OUT_MAX
+} UserOutPacketType;
+
+
+// total size of user packet structure should not exceed 255 bytes
+#pragma pack(1)
+typedef struct {
+ uint8_t packetPayload[252]; // maximum 252 bytes
+} userPacket;
+#define MAX_NUMBER_OF_USER_PARAMS_IN_THE_PACKET 30
+#define FIRST_30_PARAMS 0xFFFFFFFF
+
+// example of user payload structure
+typedef struct {
+ uint32_t numParams; // number of consecutive parameters to update (little endian)
+ uint32_t paramOffset; // parameter number in parameters structure (little endian)
+ uint64_t parameters[MAX_NUMBER_OF_USER_PARAMS_IN_THE_PACKET]; // up to 30 64-bit parameters (little endian)
+}userConfigPayload;
+
+#pragma pack(1)
+// example of user payload structure
+typedef struct {
+ uint32_t paramNum; // parameter number in parameters structure (little endian)
+ uint64_t parameter; // up to 30 64-bit parameters (little endian)
+}userParamPayload;
+#pragma pack()
+
+// example of user payload structure
+typedef struct {
+ uint64_t parameters[MAX_NUMBER_OF_USER_PARAMS_IN_THE_PACKET]; // up to 30 64-bit parameters (little endian)
+}allUserParamsPayload;
+
+#pragma pack(1)
+typedef struct {
+ uint32_t timer;
+ uint8_t c;
+ short s;
+ int i;
+ long long ll;
+ double d;
+}data2_payload_t;
+
+#pragma pack()
+
+
+typedef struct {
+ uint16_t packetType;
+ uint8_t packetCode[2];
+}usr_packet_t;
+
+
+#define USR_OUT_TEST_PAYLOAD_LEN (4) // test parameter (uint32_t)
+#define USR_OUT_DATA1_PAYLOAD_LEN (4*10) // 1 integer +3accels (float LE) + 3gyros (float LE) + 3 mags (floatLE)
+#define USR_OUT_SCALED1_PAYLOAD_LEN (52) // See UserMessaging.c for make-up of Scaled1 message
+#define USR_OUT_ANG1_PAYLOAD_LEN (47) // See message loading code,HandleUserOutputPacket(), for information
+#define USR_OUT_ANG2_PAYLOAD_LEN (48)
+#define USR_OUT_AID1_PAYLOAD_LEN (56)
+#define USR_OUT_AID2_PAYLOAD_LEN (64)
+#define USR_OUT_AID3_PAYLOAD_LEN (11)
+
+
+#define USER_OK 0x00
+#define USER_NAK 0x80
+#define USER_INVALID 0x81
+
+extern int userPacketOut;
+
+extern int getUserPayloadLength(void);
+extern void WriteResultsIntoOutputStream(void *results);
+
+
+extern BOOL UpdateUserUartConfig(userConfigPayload* pld, uint8_t *payloadLen);
+extern BOOL GetUserUartConfig(userConfigPayload* pld, uint8_t *payloadLen);
+extern void UserInitConfigureUart();
+extern BOOL UpdateUserUartParam(userParamPayload* pld, uint8_t *payloadLen);
+extern BOOL UpdateAllUserUartParams(allUserParamsPayload* pld, uint8_t *payloadLen);
+extern BOOL GetUserUartParam(userParamPayload* pld, uint8_t *payloadLen);
+extern BOOL GetAllUserUartParams(allUserParamsPayload* pld, uint8_t *payloadLen);
+
+#endif /* USER_CONFIGURATION_H */
diff --git a/examples/OpenIMU335RI/VG/src/user/dataProcessingAndPresentation.c b/examples/OpenIMU335RI/VG/src/user/dataProcessingAndPresentation.c
new file mode 100644
index 0000000..748a236
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/user/dataProcessingAndPresentation.c
@@ -0,0 +1,137 @@
+/*****************************************************************************
+ * @file dataProcessingAndPresentation.c
+ *
+ * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ * contains of data post-processing framework
+ ******************************************************************************/
+/*******************************************************************************
+Copyright 2018 ACEINNA, INC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*******************************************************************************/
+
+#include
+#include "userAPI.h"
+#include "sensorsAPI.h"
+#include "gpsAPI.h"
+#include "ekfAPI.h"
+#include "odoAPI.h"
+#include "UserAlgorithm.h"
+#include "EcuSettings.h"
+
+gpsDataStruct_t gGPS;
+IMUDataStruct gIMU;
+odoDataStruct_t gOdo;
+
+/* *
+ ******************
+ *
+ Sensors data processing flow (from left to right)
+
+Raw *************** Filtered * ************ Calibrated **************** ********************* Data
+Data * Built-in * Raw Data * * Data * User Filter s* * Algorithm * Output
+****** LP Filter ************* Calibration ************* (if desired) ***** (Kalman Filter ********
+ * * * * * * * or user Algorithm)*
+ ************* * ************** **************** *********************
+ ^^^^^^^
+ Can be selected during
+ initialization or turned
+ OFF
+*///<--------------------- Cyclical processing at 100 or 200 Hz in Data Acquisition Task -------------->
+
+
+// Next function is common for all platforms, but implementation of the methods inside is platform-dependent
+// Call to this function made from DataAcquisitionTask during initialization phase
+// All user algorithm and data structures should be initialized here, if used
+void initUserDataProcessingEngine()
+{
+ // Initializa global variables of sensor data
+ memset(&gGPS, 0, sizeof(gGPS));
+ memset(&gIMU, 0, sizeof(gIMU));
+
+ InitUserAlgorithm(); // default implementation located in file user_algorithm.c
+}
+
+
+// Notes:
+// 1) 'inertialAndPositionDataProcessing' is common for all platforms, but implementation
+// of the methods inside is platform and user-dependent.
+// 2) 'DataAcquisitionTask' calls this function after retrieving samples of current
+// sensors data and applying corresponding calibration
+// 3) 'dacqRate' is rate with which new set of sensors data arrives
+void inertialAndPositionDataProcessing(int32_t const dacqRate)
+{
+ static uint8_t initAlgo = 1U;
+ static uint8_t algoCntr = 0U;
+ static uint8_t algoCntrLimit = 0U;
+
+ if(!UseAlgorithm()){
+ return;
+ }
+
+
+ if (initAlgo)
+ {
+ // Reset 'initAlgo' so this is not executed more than once. This
+ // prevents the algorithm from being switched during run-time.
+ initAlgo = 0U;
+ uint32_t const algoFreq = EKF_GetCallingFreq();
+
+ // Set the variables that control the algorithm execution rate
+ float32_t const algoCntrLimit_f = ((float32_t)dacqRate / (float32_t)algoFreq) + 0.5F;
+ algoCntrLimit = (uint8_t)(algoCntrLimit_f);
+
+ if (algoCntrLimit < 1U)
+ {
+ // If this logic is reached, also need to adjust the algorithm
+ // parameters to match the modified calling freq (or stop the
+ // program to indicate that the user must adjust the program)
+ algoCntrLimit = 1U;
+ }
+ algoCntr = algoCntrLimit;
+ }
+ // call the algorithm
+ algoCntr++;
+
+ if (algoCntr >= algoCntrLimit)
+ {
+
+ // Reset counter
+ algoCntr = 0U;
+
+ // Obtain accelerometer data [g]
+ sens_GetAccelData_g(gIMU.accel_g);
+
+ // Obtain rate-sensor data [rad/sec]
+ sens_GetRateData_radPerSec(gIMU.rate_radPerSec);
+
+ // Obtain magnetometer data [G]
+ sens_GetMagData_G(gIMU.mag_G);
+
+ // Obtain board temperature data [degC]
+ sens_GetBoardTempData(&gIMU.temp_C);
+
+ // Obtain aiding signal data.
+ GetOdometerData(&gOdo);
+
+ // Execute user algorithm (default implementation located in file user_algorithm.c)
+ RunUserNavAlgorithm(gIMU.accel_g, gIMU.rate_radPerSec, gIMU.mag_G, &gGPS, &gOdo, FALSE);
+ }
+}
+
+
+
diff --git a/examples/OpenIMU335RI/VG/src/user/gpsAPI.h b/examples/OpenIMU335RI/VG/src/user/gpsAPI.h
new file mode 100644
index 0000000..3b74b37
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/user/gpsAPI.h
@@ -0,0 +1,88 @@
+/** ***************************************************************************
+ * @file gps.h GPS Driver for Inertial/GPS NAV.
+ *
+ * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ * @brief This is a generalized GPS interface, taken loosely from the DMU440
+ * project possibly implemented using the Origin ORG4475 GPS module (or NovAtel
+ * or uBlox) the GPS may communicated via SPI or UART, that is passed in on init
+ * 03.2007 DA Cleaned up, Doxygenized, and finalized for NAV440 release.
+ *****************************************************************************/
+/*******************************************************************************
+Copyright 2018 ACEINNA, INC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*******************************************************************************/
+
+#ifndef GPS_API_H
+#define GPS_API_H
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Fix type
+enum
+{
+
+ INVALID = 0, // GNSS not fixed yet
+ SPP = 1, // Single Point Positioning
+ DGPS = 2, // Pseudorange Differential
+ PPP = 3, // Precise Point Positioning
+ RTK_FIX = 4, // RTK Fixed
+ RTK_FLOAT = 5, // RTK Float
+ DEAD_REC = 6, // Dead Reckoning (will be considered as INVALID)
+ MANUAL = 7, // Manual Input Mode (will be considered as INVALID)
+ SIMULATION = 8, // Simulation Mode (will be considered as INVALID)
+};
+
+typedef struct {
+ uint8_t gpsFixType; // 1 if data is valid
+ uint8_t gpsUpdate; // 1 if contains new data
+ uint8_t numSatellites; // num of satellites in the solution
+ uint32_t itow; // gps Time Of Week, miliseconds
+
+ float64_t latitude; // latitude , degrees
+ float64_t longitude; // longitude, degrees
+ float64_t vNed[3]; // velocities, m/s NED (North East Down) x, y, z
+ float64_t trueCourse; // [deg]
+ float64_t rawGroundSpeed; // [m/s]
+ float64_t altitude; // above WGS84 ellipsoid [m]
+ float64_t GPSSecondFraction;
+
+
+ uint8_t GPSmonth; // mm
+ uint8_t GPSday; // dd
+ uint8_t GPSyear; // yy last two digits of year
+ char GPSHour; // hh
+ char GPSMinute; // mm
+ char GPSSecond; // ss
+
+ float32_t GPSHorizAcc;
+ float32_t GPSVertAcc;
+ float32_t HDOP;
+ float32_t geoidAboveEllipsoid; // [m] Height of geoid (mean sea level) above WGS84 ellipsoid
+} gpsDataStruct_t;
+
+extern gpsDataStruct_t gGPS;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GPS_API_H */
diff --git a/examples/OpenIMU335RI/VG/src/user/userAPI.h b/examples/OpenIMU335RI/VG/src/user/userAPI.h
new file mode 100644
index 0000000..a0c63c3
--- /dev/null
+++ b/examples/OpenIMU335RI/VG/src/user/userAPI.h
@@ -0,0 +1,69 @@
+/** ******************************************************************************
+ * @file userAPI.h API functions for Interfacing with user algorithm
+ *
+ * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ *****************************************************************************/
+/*******************************************************************************
+Copyright 2018 ACEINNA, INC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*******************************************************************************/
+
+#ifndef USER_API_H
+#define USER_API_H
+
+#include
+#include "gpsAPI.h"
+#include "odoAPI.h"
+
+/*******************************************
+ * @brief
+ *
+ * @param dacqRate ==
+********************************************/
+void inertialAndPositionDataProcessing(int32_t const dacqRate);
+
+/*******************************************
+ * @brief
+ *
+ * @param accels ==
+ * @param rates ==
+ * @param mags ==
+ * @param gps ==
+ * @param odo ==
+ * @param ppsDetected ==
+********************************************/
+void RunUserNavAlgorithm(float64_t accels[],
+ float64_t rates[],
+ float64_t mags[],
+ gpsDataStruct_t* const gps,
+ odoDataStruct_t* const odo,
+ BOOL const ppsDetected);
+
+/*******************************************
+ * @brief
+ *
+********************************************/
+void InitUserAlgorithm();
+
+/*******************************************
+ * @brief
+ *
+********************************************/
+void initUserDataProcessingEngine();
+
+#endif
diff --git a/platform.json b/platform.json
index c1d7dd0..cd968fd 100644
--- a/platform.json
+++ b/platform.json
@@ -20,7 +20,7 @@
"type": "git",
"url": "https://github.com/aceinna/platform-aceinna_imu.git"
},
- "version": "1.3.5",
+ "version": "1.3.6",
"packages": {
"toolchain-gccarmnoneeabi": {
"type": "toolchain",