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",