From 2238a13099e241e572e27f90f981f0d8bb846799 Mon Sep 17 00:00:00 2001 From: Arnaud Taffanel Date: Tue, 3 Jul 2018 14:15:31 +0200 Subject: [PATCH] #345: Add drivers for Bosch BMI088 and BMP388 --- Makefile | 2 + src/drivers/bosch/interface/bmi088.h | 516 +++++ src/drivers/bosch/interface/bmi088_defs.h | 896 ++++++++ src/drivers/bosch/interface/bmi088_fifo.h | 549 +++++ src/drivers/bosch/interface/bmp3.h | 322 +++ src/drivers/bosch/interface/bmp3_defs.h | 731 ++++++ src/drivers/bosch/src/bmi088_accel.c | 1117 ++++++++++ src/drivers/bosch/src/bmi088_fifo.c | 1804 +++++++++++++++ src/drivers/bosch/src/bmi088_gyro.c | 718 ++++++ src/drivers/bosch/src/bmp3.c | 2459 +++++++++++++++++++++ src/hal/interface/sensors_bosch.h | 13 +- 11 files changed, 9126 insertions(+), 1 deletion(-) create mode 100644 src/drivers/bosch/interface/bmi088.h create mode 100644 src/drivers/bosch/interface/bmi088_defs.h create mode 100644 src/drivers/bosch/interface/bmi088_fifo.h create mode 100644 src/drivers/bosch/interface/bmp3.h create mode 100644 src/drivers/bosch/interface/bmp3_defs.h create mode 100644 src/drivers/bosch/src/bmi088_accel.c create mode 100644 src/drivers/bosch/src/bmi088_fifo.c create mode 100644 src/drivers/bosch/src/bmi088_gyro.c create mode 100644 src/drivers/bosch/src/bmp3.c diff --git a/Makefile b/Makefile index 651e4a4ab4..5dc6473898 100644 --- a/Makefile +++ b/Makefile @@ -127,7 +127,9 @@ PROJ_OBJ_CF2 += ak8963.o eeprom.o maxsonar.o piezo.o PROJ_OBJ_CF2 += uart_syslink.o swd.o uart1.o uart2.o watchdog.o PROJ_OBJ_CF2 += cppm.o PROJ_OBJ_CF2 += bmi055_accel.o bmi055_gyro.o bmi160.o bmp280.o bstdr_comm_support.o bmm150.o +PROJ_OBJ_CF2 += bmi088_accel.o bmi088_gyro.o bmi088_fifo.o bmp3.o PROJ_OBJ_CF2 += pca9685.o vl53l0x.o pca95x4.o vl53l1x.o pmw3901.o + # USB Files PROJ_OBJ_CF2 += usb_bsp.o usblink.o usbd_desc.o usb.o diff --git a/src/drivers/bosch/interface/bmi088.h b/src/drivers/bosch/interface/bmi088.h new file mode 100644 index 0000000000..fdac2a3881 --- /dev/null +++ b/src/drivers/bosch/interface/bmi088.h @@ -0,0 +1,516 @@ +/* + * + **************************************************************************** + * Copyright (C) 2015 - 2016 Bosch Sensortec GmbH + * + * File : bmi088.h + * + * Date: 30 Oct 2017 + * + * Revision: $ + * + * Usage: Sensor Driver for BMI088 family of sensors + * + **************************************************************************** + * + * Disclaimer + * + * Common: + * Bosch Sensortec products are developed for the consumer goods industry. + * They may only be used within the parameters of the respective valid + * product data sheet. Bosch Sensortec products are provided with the + * express understanding that there is no warranty of fitness for a + * particular purpose.They are not fit for use in life-sustaining, + * safety or security sensitive systems or any system or device + * that may lead to bodily harm or property damage if the system + * or device malfunctions. In addition,Bosch Sensortec products are + * not fit for use in products which interact with motor vehicle systems. + * The resale and or use of products are at the purchasers own risk and + * his own responsibility. The examination of fitness for the intended use + * is the sole responsibility of the Purchaser. + * + * The purchaser shall indemnify Bosch Sensortec from all third party + * claims, including any claims for incidental, or consequential damages, + * arising from any product use not covered by the parameters of + * the respective valid product data sheet or not approved by + * Bosch Sensortec and reimburse Bosch Sensortec for all costs in + * connection with such claims. + * + * The purchaser must monitor the market for the purchased products, + * particularly with regard to product safety and inform Bosch Sensortec + * without delay of all security relevant incidents. + * + * Engineering Samples are marked with an asterisk (*) or (e). + * Samples may vary from the valid technical specifications of the product + * series. They are therefore not intended or fit for resale to third + * parties or for use in end products. Their sole purpose is internal + * client testing. The testing of an engineering sample may in no way + * replace the testing of a product series. Bosch Sensortec assumes + * no liability for the use of engineering samples. + * By accepting the engineering samples, the Purchaser agrees to indemnify + * Bosch Sensortec from all claims arising from the use of engineering + * samples. + * + * Special: + * This software module (hereinafter called "Software") and any information + * on application-sheets (hereinafter called "Information") is provided + * free of charge for the sole purpose to support your application work. + * The Software and Information is subject to the following + * terms and conditions: + * + * The Software is specifically designed for the exclusive use for + * Bosch Sensortec products by personnel who have special experience + * and training. Do not use this Software if you do not have the + * proper experience or training. + * + * This Software package is provided `` as is `` and without any expressed + * or implied warranties,including without limitation, the implied warranties + * of merchantability and fitness for a particular purpose. + * + * Bosch Sensortec and their representatives and agents deny any liability + * for the functional impairment + * of this Software in terms of fitness, performance and safety. + * Bosch Sensortec and their representatives and agents shall not be liable + * for any direct or indirect damages or injury, except as + * otherwise stipulated in mandatory applicable law. + * + * The Information provided is believed to be accurate and reliable. + * Bosch Sensortec assumes no responsibility for the consequences of use + * of such Information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of Bosch. Specifications mentioned in the Information are + * subject to change without notice. + **************************************************************************/ +/*! \file bmi088.h + \brief Sensor Driver for BMI088 family of sensors */ +#ifndef BMI088_H_ +#define BMI088_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + /*********************************************************************/ + /* header files */ +#include "bmi088_defs.h" + /*********************************************************************/ + /* (extern) variable declarations */ + + /*********************************************************************/ + /* function prototype declarations */ + + /*********************** BMI088 Accelerometer function prototypes ************************/ + + /*! + * @brief This API is the entry point for accel sensor. + * It performs the selection of I2C/SPI read mechanism according to the + * selected interface and reads the chip-id of accel sensor. + * + * @param[in,out] dev : Structure instance of bmi088_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_accel_init(struct bmi088_dev *dev); + + /*! + * @brief This API is used to write the binary configuration in the sensor + * + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_write_config_file(struct bmi088_dev *dev); + + /*! + * @brief This API reads the data from the given register address of accel sensor. + * + * @param[in] reg_addr : Register address from where the data to be read + * @param[out] data : Pointer to data buffer to store the read data. + * @param[in] len : No. of bytes of data to be read. + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_get_accel_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, struct bmi088_dev *dev); + + /*! + * @brief This API writes the given data to the register address + * of accel sensor. + * + * @param[in] reg_addr : Register address to where the data to be written. + * @param[in] data : Pointer to data buffer which is to be written + * in the sensor. + * @param[in] len : No. of bytes of data to write. + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_set_accel_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, struct bmi088_dev *dev); + + /*! + * @brief This API reads the error status from the accel sensor. + * + * Below table mention the types of error which can occur in the sensor + *@verbatim + ************************************************************************* + * Error | Description + *************************|*********************************************** + * | Fatal Error, chip is not in operational + * fatal | state (Boot-, power-system). + * | This flag will be reset only by + * | power-on-reset or soft reset. + *************************|*********************************************** + * cmd | Command execution failed. + *************************|*********************************************** + * | Value Name Description + * error_code | 000 no_error no error + * | 001 accel_err error in + * | ACCEL_CONF + ************************************************************************* + *@endverbatim + * + * @param[in,out] err_reg : Pointer to structure variable which stores the + * error status read from the sensor. + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_get_accel_error_status(struct bmi088_err_reg *err_reg, struct bmi088_dev *dev); + + /*! + * @brief This API reads the status of the accel sensor. + * + * Below table lists the sensor status flags + *@verbatim + ************************************************************************* + * Status | Description + ***********************************|************************************* + * drdy_accel | Data ready for Accel. + ************************************************************************* + *@endverbatim + * + * @param[in] status : Variable used to store the sensor status flags + * which is read from the sensor. + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_get_accel_status(uint8_t *status, struct bmi088_dev *dev); + + /*! + * @brief This API resets the accel sensor. + * + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_accel_soft_reset(struct bmi088_dev *dev); + + /*! + * @brief This API sets the Output data rate, range and bandwidth + * of accel sensor. + * + * @param[in] dev : Structure instance of bmi088_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_set_accel_meas_conf(struct bmi088_dev *dev); + + /*! + * @brief This API sets the power mode of the accel sensor. + * + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_set_accel_power_mode(struct bmi088_dev *dev); + + /*! + * @brief This API reads the accel data from the sensor, + * store it in the bmi088_sensor_data structure instance + * passed by the user. + * + * @param[out] accel : Structure pointer to store accel data + * @param[in] dev : Structure instance of bmi088_dev. + * + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_get_accel_data(struct bmi088_sensor_data *accel, struct bmi088_dev *dev); + + /*! + * @brief This API configures the necessary accel interrupt + * based on the user settings in the bmi088_int_cfg + * structure instance. + * + * @param[in] int_config : Structure instance of bmi088_int_cfg. + * @param[in] dev : Structure instance of bmi088_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_set_accel_int_config(const struct bmi088_int_cfg *int_config, struct bmi088_dev *dev); + + /*! + * @brief This API switches accel sensor on or off. + * + * @param[in] dev : Structure instance of bmi088_dev. + * @param[in] switch_input : Input to switch accel on or off + * Value | Description + * ---------|-------------------- + * 0 | BMI088_ACCEL_POWER_DISABLE + * 4 | BMI088_ACCEL_POWER_ENABLE + * + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_accel_switch_control(struct bmi088_dev *dev, uint8_t switch_input); + + /*! + * @brief This API reads the temperature of the sensor in � Celcius. + * + * @param[in] dev : Structure instance of bmi088_dev. + * @param[out] sensor_temp : Pointer to store sensor temperature in � Celcius + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_get_sensor_temperature(struct bmi088_dev *dev, float *sensor_temp); + + /*! + * @brief This API reads the sensor time of the sensor. + * + * @param[in] dev : Structure instance of bmi088_dev. + * @param[out] sensor_time : Pointer to store sensor time + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_get_sensor_time(struct bmi088_dev *dev, uint32_t *sensor_time); + + /*! + * @brief This API checks whether the self test functionality of the sensor + * is working or not + * + * @param[in] result : Pointer variable used to store the result of self test + * operation. + * result | Description + * ---------|-------------------- + * 0 | BMI088_SELFTEST_PASS + * -1 | BMI088_SELFTEST_FAIL + * + * @param[in] dev : Structure instance of bmi088_dev + * + * @return results of self test + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_perform_accel_selftest(int8_t *result, struct bmi088_dev *dev); + + /*! + * @brief This API enables or disables the Accel Self test feature in the + * sensor. + * + * @param[in] selftest : Variable used to enable or disable + * the Accel self test feature + * Value | Description + * --------|--------------- + * 0x00 | BMI088_ACCEL_SWITCH_OFF_SELF_TEST + * 0x0D | BMI088_ACCEL_POSITIVE_SELF_TEST + * 0x09 | BMI088_ACCEL_NEGATIVE_SELF_TEST + * + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_set_accel_selftest(uint8_t selftest, struct bmi088_dev *dev); + + /*********************** BMI088 Gyroscope function prototypes ************************/ + + /*! + * @brief This API is the entry point for gyro sensor. + * It performs the selection of I2C/SPI read mechanism according to the + * selected interface and reads the chip-id of gyro sensor. + * + * @param[in,out] dev : Structure instance of bmi088_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_gyro_init(struct bmi088_dev *dev); + + /*! + * @brief This API reads the data from the given register address of gyro sensor. + * + * @param[in] reg_addr : Register address from where the data to be read + * @param[out] data : Pointer to data buffer to store the read data. + * @param[in] len : No. of bytes of data to be read. + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_get_gyro_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, struct bmi088_dev *dev); + + /*! + * @brief This API writes the given data to the register address + * of gyro sensor. + * + * @param[in] reg_addr : Register address to where the data to be written. + * @param[in] data : Pointer to data buffer which is to be written + * in the sensor. + * @param[in] len : No. of bytes of data to write. + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_set_gyro_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, struct bmi088_dev *dev); + + /*! + * @brief This API resets the gyro sensor. + * + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_gyro_soft_reset(struct bmi088_dev *dev); + + /*! + * @brief This API sets the output data rate, range and bandwidth + * of gyro sensor. + * + * @param[in] dev : Structure instance of bmi088_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_set_gyro_meas_conf(struct bmi088_dev *dev); + + /*! + * @brief This API sets the power mode of the gyro sensor. + * + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_set_gyro_power_mode(struct bmi088_dev *dev); + + /*! + * @brief This API reads the gyro data from the sensor, + * store it in the bmi088_sensor_data structure instance + * passed by the user. + * + * @param[out] gyro : Structure pointer to store gyro data + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_get_gyro_data(struct bmi088_sensor_data *gyro, struct bmi088_dev *dev); + + /*! + * @brief This API configures the necessary gyro interrupt + * based on the user settings in the bmi088_int_cfg + * structure instance. + * + * @param[in] int_config : Structure instance of bmi088_int_cfg. + * @param[in] dev : Structure instance of bmi088_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_set_gyro_int_config(const struct bmi088_int_cfg *int_config, struct bmi088_dev *dev); + + /*! + * @brief This API enables or disables the Gyro Self test feature in the + * sensor. + * + * @param[in] selftest : Variable used to enable or disable + * the Gyro self test feature + * Value | Description + * --------|--------------- + * 0x00 | BMI088_DISABLE + * 0x01 | BMI088_ENABLE + * + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_set_gyro_selftest(uint8_t selftest, struct bmi088_dev *dev); + + /*! + * @brief This API checks whether the self test functionality of the + * gyro sensor is working or not + * + * @param[in] result : Pointer variable used to store the result of + * self test operation + * result | Description + * ---------|-------------------- + * 0 | BMI088_SELFTEST_PASS + * -1 | BMI088_SELFTEST_FAIL + * + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ + uint16_t bmi088_perform_gyro_selftest(int8_t *result, struct bmi088_dev *dev); + +#ifdef __cplusplus +} +#endif + +#endif +/* End of BMI088_H_ */ diff --git a/src/drivers/bosch/interface/bmi088_defs.h b/src/drivers/bosch/interface/bmi088_defs.h new file mode 100644 index 0000000000..a4f2aae35e --- /dev/null +++ b/src/drivers/bosch/interface/bmi088_defs.h @@ -0,0 +1,896 @@ +/** + * Copyright (C) 2015 - 2016 Bosch Sensortec GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 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. + * + * Neither the name of the copyright holder nor the names of the + * 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 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 + * + * The information provided is believed to be accurate and reliable. + * The copyright holder assumes no responsibility + * for the consequences of use + * of such information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of the copyright holder. + * + * @file bmi088_defs.h + * @date Oct 5, 2016 + * @version + * @brief + * + */ + +/*! + * @defgroup bmi088_defs + * @brief + * @{*/ + +#ifndef BMI088_DEFS_H_ +#define BMI088_DEFS_H_ + +/*********************************************************************/ +/**\ header files */ +#ifdef __KERNEL__ +#include +#else +#include +#include +#include +#endif + +/*********************************************************************/ +/* macro definitions */ + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* + #if (LONG_MAX) > 0x7fffffff + #define __have_long64 1 + #elif (LONG_MAX) == 0x7fffffff + #define __have_long32 1 + #endif + */ + +#if !defined(UINT8_C) +#define INT8_C(x) x +#if (INT_MAX) > 0x7f +#define UINT8_C(x) x +#else +#define UINT8_C(x) x##U +#endif +#endif + +#if !defined(UINT16_C) +#define INT16_C(x) x +#if (INT_MAX) > 0x7fff +#define UINT16_C(x) x +#else +#define UINT16_C(x) x##U +#endif +#endif + +#if !defined(INT32_C) && !defined(UINT32_C) +#if __have_long32 +#define INT32_C(x) x##L +#define UINT32_C(x) x##UL +#else +#define INT32_C(x) x +#define UINT32_C(x) x##U +#endif +#endif + +#if !defined(INT64_C) && !defined(UINT64_C) +#if __have_long64 +#define INT64_C(x) x##L +#define UINT64_C(x) x##UL +#else +#define INT64_C(x) x##LL +#define UINT64_C(x) x##ULL +#endif +#endif + + /*************************** Sensor macros *****************************/ + + /* Test for an endian machine */ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define LITTLE_ENDIAN 1 +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define BIG_ENDIAN 1 +#else +#error "Code does not support Endian format of the processor" +#endif + + /*************************** BMI088 Accelerometer Macros *****************************/ + + /** Register map */ + /* Accel registers */ + + /**\name Accel Chip Id register */ +#define BMI088_ACCEL_CHIP_ID_REG UINT8_C(0x00) + + /**\name Accel Error condition register */ +#define BMI088_ACCEL_ERR_REG UINT8_C(0x02) + + /**\name Accel Status flag register */ +#define BMI088_ACCEL_STATUS_REG UINT8_C(0x03) + + /**\name Accel X LSB data register */ +#define BMI088_ACCEL_X_LSB_REG UINT8_C(0x12) + + /**\name Accel X MSB data register */ +#define BMI088_ACCEL_X_MSB_REG UINT8_C(0x13) + + /**\name Accel Y LSB data register */ +#define BMI088_ACCEL_Y_LSB_REG UINT8_C(0x14) + + /**\name Accel Y MSB data register */ +#define BMI088_ACCEL_Y_MSB_REG UINT8_C(0x15) + + /**\name Accel Z LSB data register */ +#define BMI088_ACCEL_Z_LSB_REG UINT8_C(0x16) + + /**\name Accel Z MSB data register */ +#define BMI088_ACCEL_Z_MSB_REG UINT8_C(0x17) + + /**\name Sensor time byte 0 register */ +#define BMI088_ACCEL_SENSORTIME_0_REG UINT8_C(0x18) + + /**\name Sensor time byte 1 register */ +#define BMI088_ACCEL_SENSORTIME_1_REG UINT8_C(0x19) + + /**\name Sensor time byte 2 register */ +#define BMI088_ACCEL_SENSORTIME_2_REG UINT8_C(0x1A) + + /**\name Accel Interrupt status register */ +#define BMI088_ACCEL_INT_STAT_1_REG UINT8_C(0x1D) + + /**\name Sensor temperature MSB data register */ +#define BMI088_TEMP_MSB_REG UINT8_C(0x22) + + /**\name Sensor temperature LSB data register */ +#define BMI088_TEMP_LSB_REG UINT8_C(0x23) + + /**\name Accel Fifo Length 0 register */ +#define BMI088_ACCEL_FIFO_LENGTH_0_REG UINT8_C(0x24) + + /**\name Accel Fifo Length 1 register */ +#define BMI088_ACCEL_FIFO_LENGTH_1_REG UINT8_C(0x25) + + /**\name Accel Fifo data register */ +#define BMI088_ACCEL_FIFO_DATA_REG UINT8_C(0x26) + + /**\name Accel Internal status register */ +#define BMI088_ACCEL_INTERNAL_STAT_REG UINT8_C(0x2A) + + /**\name Accel configuration register */ +#define BMI088_ACCEL_CONF_REG UINT8_C(0x40) + + /**\name Accel range setting register */ +#define BMI088_ACCEL_RANGE_REG UINT8_C(0x41) + + /**\name Accel Fifo Down register */ +#define BMI088_ACCEL_FIFO_DOWN_REG UINT8_C(0x45) + + /**\name Accel Fifo Watermark 0 register */ +#define BMI088_ACCEL_FIFO_WTM_0_REG UINT8_C(0x46) + + /**\name Accel Fifo Watermark 1 register */ +#define BMI088_ACCEL_FIFO_WTM_1_REG UINT8_C(0x47) + + /**\name Accel Fifo Config 0 register */ +#define BMI088_ACCEL_FIFO_CONFIG_0_REG UINT8_C(0x48) + + /**\name Accel Fifo Config 1 register */ +#define BMI088_ACCEL_FIFO_CONFIG_1_REG UINT8_C(0x49) + + /**\name Accel Interrupt pin 1 configuration register */ +#define BMI088_ACCEL_INT1_IO_CONF_REG UINT8_C(0x53) + + /**\name Accel Interrupt pin 2 configuration register */ +#define BMI088_ACCEL_INT2_IO_CONF_REG UINT8_C(0x54) + + /**\name Accel Interrupt map register */ +#define BMI088_ACCEL_INT1_INT2_MAP_DATA_REG UINT8_C(0x58) + + /**\name Accel Init control register */ +#define BMI088_ACCEL_INIT_CTRL_REG UINT8_C(0x59) + + /**\name Accel Self test register */ +#define BMI088_ACCEL_SELF_TEST_REG UINT8_C(0x6D) + + /**\name Accel Power mode configuration register */ +#define BMI088_ACCEL_PWR_CONF_REG UINT8_C(0x7C) + + /**\name Accel Power control (switch on or off ) register */ +#define BMI088_ACCEL_PWR_CTRL_REG UINT8_C(0x7D) + + /**\name Accel Soft reset register */ +#define BMI088_ACCEL_SOFTRESET_REG UINT8_C(0x7E) + + /**\name Accel unique chip identifier */ +#define BMI088_ACCEL_CHIP_ID UINT8_C(0x1E) + + /**\name Accel I2C slave address */ +#define BMI088_ACCEL_I2C_ADDR_PRIMARY UINT8_C(0x18) +#define BMI088_ACCEL_I2C_ADDR_SECONDARY UINT8_C(0x19) + + /**\name Feature Config related Registers */ +#define BMI088_ACCEL_RESERVED_5B_REG UINT8_C(0x5B) +#define BMI088_ACCEL_RESERVED_5C_REG UINT8_C(0x5C) +#define BMI088_ACCEL_FEATURE_CFG_REG UINT8_C(0x5E) + + /**\name Interrupt masks */ +#define BMI088_ACCEL_DATA_READY_INT UINT8_C(0x80) + + /**\name Accel Bandwidth */ +#define BMI088_ACCEL_BW_OSR4 UINT8_C(0x00) +#define BMI088_ACCEL_BW_OSR2 UINT8_C(0x01) +#define BMI088_ACCEL_BW_NORMAL UINT8_C(0x02) + + /**\name Accel Range */ +#define BMI088_ACCEL_RANGE_3G UINT8_C(0x00) +#define BMI088_ACCEL_RANGE_6G UINT8_C(0x01) +#define BMI088_ACCEL_RANGE_12G UINT8_C(0x02) +#define BMI088_ACCEL_RANGE_24G UINT8_C(0x03) + + /**\name Accel Output data rate */ +#define BMI088_ACCEL_ODR_12_5_HZ UINT8_C(0x05) +#define BMI088_ACCEL_ODR_25_HZ UINT8_C(0x06) +#define BMI088_ACCEL_ODR_50_HZ UINT8_C(0x07) +#define BMI088_ACCEL_ODR_100_HZ UINT8_C(0x08) +#define BMI088_ACCEL_ODR_200_HZ UINT8_C(0x09) +#define BMI088_ACCEL_ODR_400_HZ UINT8_C(0x0A) +#define BMI088_ACCEL_ODR_800_HZ UINT8_C(0x0B) +#define BMI088_ACCEL_ODR_1600_HZ UINT8_C(0x0C) + + /**\name Accel Self test */ +#define BMI088_ACCEL_SWITCH_OFF_SELF_TEST UINT8_C(0x00) +#define BMI088_ACCEL_POSITIVE_SELF_TEST UINT8_C(0x0D) +#define BMI088_ACCEL_NEGATIVE_SELF_TEST UINT8_C(0x09) + + /**\name Accel Power mode */ +#define BMI088_ACCEL_PM_ACTIVE UINT8_C(0x00) +#define BMI088_ACCEL_PM_SUSPEND UINT8_C(0x03) + + /**\name Accel Power control settings */ +#define BMI088_ACCEL_POWER_DISABLE UINT8_C(0x00) +#define BMI088_ACCEL_POWER_ENABLE UINT8_C(0x04) + + /**\name Accel Soft reset delay */ +#define BMI088_ACCEL_SOFTRESET_DELAY UINT8_C(1) + + /**\name Mask definitions for ACCEL_ERR_REG register */ +#define BMI088_FATAL_ERR_MASK UINT8_C(0x01) +#define BMI088_CMD_ERR_MASK UINT8_C(0x02) +#define BMI088_ERR_CODE_MASK UINT8_C(0x1C) + + /**\name Position definitions for ACCEL_ERR_REG register */ +#define BMI088_FATAL_ERR_POS UINT8_C(0) +#define BMI088_CMD_ERR_POS UINT8_C(1) +#define BMI088_ERR_CODE_POS UINT8_C(2) + + /**\name Mask definition for FIFO BYTE COUNTER register */ +#define BMI088_FIFO_BYTE_COUNTER_MSB_MASK UINT8_C(0x3F) + + /**\name Position definition for FIFO BYTE COUNTER register */ +#define BMI088_FIFO_BYTE_COUNTER_MSB_POS UINT8_C(0) + + /**\name Mask definitions for odr, bandwidth and range */ +#define BMI088_ACCEL_ODR_MASK UINT8_C(0x0F) +#define BMI088_ACCEL_BW_MASK UINT8_C(0x70) +#define BMI088_ACCEL_RANGE_MASK UINT8_C(0x03) + + /**\name Position definitions for odr, bandwidth and range */ +#define BMI088_ACCEL_ODR_POS UINT8_C(0) +#define BMI088_ACCEL_BW_POS UINT8_C(4) +#define BMI088_ACCEL_RANGE_POS UINT8_C(0) + + /**\name Mask definitions for FIFO_DOWNS register */ +#define BMI088_ACCEL_FIFO_FILT_DOWN_MASK UINT8_C(0x70) +#define BMI088_ACCEL_FIFO_FILT_DATA_MASK UINT8_C(0x80) + + /**\name Position definitions for FIFO_DOWNS register */ +#define BMI088_ACCEL_FIFO_FILT_DOWN_POS UINT8_C(4) +#define BMI088_ACCEL_FIFO_FILT_DATA_POS UINT8_C(7) + + /**\name Mask definitions for INT1_IO_CONF register */ +#define BMI088_ACCEL_INT1_LVL_MASK UINT8_C(0x02) +#define BMI088_ACCEL_INT1_OD_MASK UINT8_C(0x04) +#define BMI088_ACCEL_INT1_IO_MASK UINT8_C(0x08) + + /**\name Position definitions for INT1_IO_CONF register */ +#define BMI088_ACCEL_INT1_LVL_POS UINT8_C(1) +#define BMI088_ACCEL_INT1_OD_POS UINT8_C(2) +#define BMI088_ACCEL_INT1_IO_POS UINT8_C(3) + + /**\name Mask definitions for INT2_IO_CONF register */ +#define BMI088_ACCEL_INT2_LVL_MASK UINT8_C(0x02) +#define BMI088_ACCEL_INT2_OD_MASK UINT8_C(0x04) +#define BMI088_ACCEL_INT2_IO_MASK UINT8_C(0x08) + + /**\name Position definitions for INT2_IO_CONF register */ +#define BMI088_ACCEL_INT2_LVL_POS UINT8_C(1) +#define BMI088_ACCEL_INT2_OD_POS UINT8_C(2) +#define BMI088_ACCEL_INT2_IO_POS UINT8_C(3) + + /**\name Mask definitions for INT1_INT2_MAP_DATA register */ +#define BMI088_ACCEL_INT1_FIFO_FULL_MASK UINT8_C(0x01) +#define BMI088_ACCEL_INT1_FIFO_WM_MASK UINT8_C(0x02) +#define BMI088_ACCEL_INT1_DRDY_MASK UINT8_C(0x04) +#define BMI088_ACCEL_INT2_FIFO_FULL_MASK UINT8_C(0x10) +#define BMI088_ACCEL_INT2_FIFO_WM_MASK UINT8_C(0x20) +#define BMI088_ACCEL_INT2_DRDY_MASK UINT8_C(0x40) + + /**\name Position definitions for INT1_INT2_MAP_DATA register */ +#define BMI088_ACCEL_INT1_FIFO_FULL_POS UINT8_C(0) +#define BMI088_ACCEL_INT1_FIFO_WM_POS UINT8_C(1) +#define BMI088_ACCEL_INT1_DRDY_POS UINT8_C(2) +#define BMI088_ACCEL_INT2_FIFO_FULL_POS UINT8_C(4) +#define BMI088_ACCEL_INT2_FIFO_WM_POS UINT8_C(5) +#define BMI088_ACCEL_INT2_DRDY_POS UINT8_C(6) + + /**\name Maximum Accel Fifo filter value */ +#define BMI088_MAX_VALUE_FIFO_FILTER UINT8_C(1) + + /**\name Maximum Accel Fifo down value */ +#define BMI088_MAX_VALUE_FIFO_DOWN UINT8_C(7) + + /**\name Asic Initialization value */ +#define BMI088_ASIC_INITIALIZED UINT8_C(0x01) + + /*************************** BMI088 Gyroscope Macros *****************************/ + + /** Register map */ + /* Gyro registers */ + + /**\name Gyro Chip Id register */ +#define BMI088_GYRO_CHIP_ID_REG UINT8_C(0x00) + + /**\name Gyro X LSB data register */ +#define BMI088_GYRO_X_LSB_REG UINT8_C(0x02) + + /**\name Gyro X MSB data register */ +#define BMI088_GYRO_X_MSB_REG UINT8_C(0x03) + + /**\name Gyro Y LSB data register */ +#define BMI088_GYRO_Y_LSB_REG UINT8_C(0x04) + + /**\name Gyro Y MSB data register */ +#define BMI088_GYRO_Y_MSB_REG UINT8_C(0x05) + + /**\name Gyro Z LSB data register */ +#define BMI088_GYRO_Z_LSB_REG UINT8_C(0x06) + + /**\name Gyro Z MSB data register */ +#define BMI088_GYRO_Z_MSB_REG UINT8_C(0x07) + + /**\name Gyro Interrupt status register */ +#define BMI088_GYRO_INT_STAT_1_REG UINT8_C(0x0A) + + /**\name Gyro Fifo status register */ +#define BMI088_GYRO_FIFO_STAT_REG UINT8_C(0x0E) + + /**\name Gyro Range register */ +#define BMI088_GYRO_RANGE_REG UINT8_C(0x0F) + + /**\name Gyro Bandwidth register */ +#define BMI088_GYRO_BANDWIDTH_REG UINT8_C(0x10) + + /**\name Gyro Power register */ +#define BMI088_GYRO_LPM1_REG UINT8_C(0x11) + + /**\name Gyro Soft reset register */ +#define BMI088_GYRO_SOFTRESET_REG UINT8_C(0x14) + + /**\name Gyro Interrupt control register */ +#define BMI088_GYRO_INT_CTRL_REG UINT8_C(0x15) + + /**\name Gyro Interrupt Pin configuration register */ +#define BMI088_GYRO_INT3_INT4_IO_CONF_REG UINT8_C(0x16) + + /**\name Gyro Interrupt Map register */ +#define BMI088_GYRO_INT3_INT4_IO_MAP_REG UINT8_C(0x18) + + /**\name Gyro Interrupt Enable Register */ +#define BMI088_GYRO_INT_EN_REG UINT8_C(0x1E) + + /**\name Gyro Self test register */ +#define BMI088_GYRO_SELF_TEST_REG UINT8_C(0x3C) + + /**\name Gyro Fifo Config 0 register */ +#define BMI088_GYRO_FIFO_CONFIG_0_REG UINT8_C(0x3D) + + /**\name Gyro Fifo Config 1 register */ +#define BMI088_GYRO_FIFO_CONFIG_1_REG UINT8_C(0x3E) + + /**\name Gyro Fifo Data register */ +#define BMI088_GYRO_FIFO_DATA_REG UINT8_C(0x3F) + + /**\name Gyro unique chip identifier */ +#define BMI088_GYRO_CHIP_ID UINT8_C(0x0F) + + /**\name Gyro I2C slave address */ +#define BMI088_GYRO_I2C_ADDR_PRIMARY UINT8_C(0x68) +#define BMI088_GYRO_I2C_ADDR_SECONDARY UINT8_C(0x69) + + /**\name Gyro Range */ +#define BMI088_GYRO_RANGE_2000_DPS UINT8_C(0x00) +#define BMI088_GYRO_RANGE_1000_DPS UINT8_C(0x01) +#define BMI088_GYRO_RANGE_500_DPS UINT8_C(0x02) +#define BMI088_GYRO_RANGE_250_DPS UINT8_C(0x03) +#define BMI088_GYRO_RANGE_125_DPS UINT8_C(0x04) + + /**\name Gyro Output data rate and bandwidth */ +#define BMI088_GYRO_BW_532_ODR_2000_HZ UINT8_C(0x00) +#define BMI088_GYRO_BW_230_ODR_2000_HZ UINT8_C(0x01) +#define BMI088_GYRO_BW_116_ODR_1000_HZ UINT8_C(0x02) +#define BMI088_GYRO_BW_47_ODR_400_HZ UINT8_C(0x03) +#define BMI088_GYRO_BW_23_ODR_200_HZ UINT8_C(0x04) +#define BMI088_GYRO_BW_12_ODR_100_HZ UINT8_C(0x05) +#define BMI088_GYRO_BW_64_ODR_200_HZ UINT8_C(0x06) +#define BMI088_GYRO_BW_32_ODR_100_HZ UINT8_C(0x07) +#define BMI088_GYRO_ODR_RESET_VAL UINT8_C(0x80) + + /**\name Gyro Power mode */ +#define BMI088_GYRO_PM_NORMAL UINT8_C(0x00) +#define BMI088_GYRO_PM_DEEP_SUSPEND UINT8_C(0x20) +#define BMI088_GYRO_PM_SUSPEND UINT8_C(0x80) + + /**\name Gyro data ready interrupt enable value */ +#define BMI088_GYRO_DRDY_INT_ENABLE_VAL UINT8_C(0x80) + + /**\name Gyro data ready map values */ +#define BMI088_GYRO_MAP_DRDY_TO_INT3 UINT8_C(0x01) +#define BMI088_GYRO_MAP_DRDY_TO_INT4 UINT8_C(0x80) +#define BMI088_GYRO_MAP_DRDY_TO_BOTH_INT3_INT4 UINT8_C(0x81) + + /**\name Gyro Fifo Operating Mode selection values */ +#define BMI088_GYRO_BYPASS_OP_MODE UINT8_C(0x00) +#define BMI088_GYRO_FIFO_OP_MODE UINT8_C(0x01) +#define BMI088_GYRO_STREAM_OP_MODE UINT8_C(0x02) + + /**\name Gyro Fifo data select values */ +#define BMI088_GYRO_ALL_INT_DATA UINT8_C(0x00)//(X,Y,Z plus INT_status 0 AND 1 ) +#define BMI088_GYRO_X_DATA UINT8_C(0x01) +#define BMI088_GYRO_Y_DATA UINT8_C(0x02) +#define BMI088_GYRO_Z_DATA UINT8_C(0x03) + + /**\name Gyro Soft reset delay */ +#define BMI088_GYRO_SOFTRESET_DELAY UINT8_C(30) + + /**\name Gyro Fifo watermark mark maximum value */ +#define BMI088_GYRO_FIFO_WM_MAX UINT8_C(0x7F) + + /**\name Mask definitions for BMI088_GYRO_FIFO_STAT_REG register */ +#define BMI088_GYRO_FIFO_COUNTER_MASK UINT8_C(0x7F) +#define BMI088_GYRO_FIFO_OVERRUN_MASK UINT8_C(0x80) + + /**\name Position definitions for BMI088_GYRO_FIFO_STAT_REG register */ +#define BMI088_GYRO_FIFO_COUNTER_POS UINT8_C(0) +#define BMI088_GYRO_FIFO_OVERRUN_POS UINT8_C(7) + + /**\name Mask definitions for BMI088_GYRO_INT_CTRL_REG register */ +#define BMI088_GYRO_FIFO_EN_MASK UINT8_C(0x40) +#define BMI088_GYRO_DATA_EN_MASK UINT8_C(0x80) + + /**\name Position definitions for BMI088_GYRO_INT_CTRL_REG register */ +#define BMI088_GYRO_FIFO_EN_POS UINT8_C(6) +#define BMI088_GYRO_DATA_EN_POS UINT8_C(7) + + /**\name Mask definitions for BMI088_GYRO_INT3_INT4_IO_CONF_REG register */ +#define BMI088_GYRO_INT3_LVL_MASK UINT8_C(0x01) +#define BMI088_GYRO_INT3_OD_MASK UINT8_C(0x02) +#define BMI088_GYRO_INT4_LVL_MASK UINT8_C(0x04) +#define BMI088_GYRO_INT4_OD_MASK UINT8_C(0x08) + + /**\name Position definitions for BMI088_GYRO_INT3_INT4_IO_CONF_REG register */ +#define BMI088_GYRO_INT3_LVL_POS UINT8_C(0) +#define BMI088_GYRO_INT3_OD_POS UINT8_C(1) +#define BMI088_GYRO_INT4_LVL_POS UINT8_C(2) +#define BMI088_GYRO_INT4_OD_POS UINT8_C(3) + + /**\name Mask definitions for BMI088_GYRO_INT3_INT4_IO_MAP_REG register */ +#define BMI088_GYRO_INT1_FIFO_MASK UINT8_C(0x04) +#define BMI088_GYRO_INT2_FIFO_MASK UINT8_C(0x20) + + /**\name Position definitions for BMI088_GYRO_INT3_INT4_IO_MAP_REG register */ +#define BMI088_GYRO_INT1_FIFO_POS UINT8_C(2) +#define BMI088_GYRO_INT2_FIFO_POS UINT8_C(5) + + /**\name Mask definitions for BMI088_GYRO_INT_CTRL_REG register */ +#define BMI088_GYRO_INT_EN_MASK UINT8_C(0x80) + + /**\name Position definitions for BMI088_GYRO_INT_CTRL_REG register */ +#define BMI088_GYRO_INT_EN_POS UINT8_C(7) + + /**\name Mask definitions for GYRO_SELF_TEST register */ +#define BMI088_GYRO_SELF_TEST_EN_MASK UINT8_C(0x01) +#define BMI088_GYRO_SELF_TEST_RDY_MASK UINT8_C(0x02) +#define BMI088_GYRO_SELF_TEST_RESULT_MASK UINT8_C(0x04) +#define BMI088_GYRO_SELF_TEST_FUNCTION_MASK UINT8_C(0x08) + + /**\name Position definitions for GYRO_SELF_TEST register */ +#define BMI088_GYRO_SELF_TEST_EN_POS UINT8_C(0) +#define BMI088_GYRO_SELF_TEST_RDY_POS UINT8_C(1) +#define BMI088_GYRO_SELF_TEST_RESULT_POS UINT8_C(2) +#define BMI088_GYRO_SELF_TEST_FUNCTION_POS UINT8_C(3) + + /**\name Mask definitions for BMI088_GYRO_FIFO_CONFIG_0_REG register */ +#define BMI088_GYRO_FIFO_WM_MASK UINT8_C(0x7F) +#define BMI088_GYRO_FIFO_TAG_MASK UINT8_C(0x80) + + /**\name Position definitions for BMI088_GYRO_FIFO_CONFIG_0_REG register */ +#define BMI088_GYRO_FIFO_WM_POS UINT8_C(0) +#define BMI088_GYRO_FIFO_TAG_POS UINT8_C(7) + + /**\name Mask definitions for BMI088_GYRO_FIFO_CONFIG_1_REG register */ +#define BMI088_GYRO_FIFO_DATA_SELECT_MASK UINT8_C(0x03) +#define BMI088_GYRO_FIFO_MODE_MASK UINT8_C(0xC0) + + /**\name Position definitions for BMI088_GYRO_FIFO_CONFIG_1_REG register */ +#define BMI088_GYRO_FIFO_DATA_SELECT_POS UINT8_C(0) +#define BMI088_GYRO_FIFO_MODE_POS UINT8_C(6) + + /*************************** Common Macros for both Accel and Gyro *****************************/ + + /**\name Interface settings */ +#define BMI088_SPI_INTF UINT8_C(1) +#define BMI088_I2C_INTF UINT8_C(0) + + /**\name SPI read/write mask to configure address */ +#define BMI088_SPI_RD_MASK UINT8_C(0x80) +#define BMI088_SPI_WR_MASK UINT8_C(0x7F) + + /**\name Error code definitions */ +#define BMI088_OK UINT16_C(0) +#define BMI088_E_NULL_PTR UINT16_C(1) +#define BMI088_E_COM_FAIL UINT16_C(1 << 2) +#define BMI088_E_DEV_NOT_FOUND UINT16_C(1 << 3) +#define BMI088_E_OUT_OF_RANGE UINT16_C(1 << 4) +#define BMI088_E_INVALID_INPUT UINT16_C(1 << 5) +#define BMI088_E_SELF_TEST_FAIL UINT16_C(1 << 6) +#define BMI088_E_CONFIG_STREAM_ERROR UINT16_C(1 << 7) + + /***\name Soft reset Value */ +#define BMI088_SOFT_RESET_VAL UINT8_C(0xB6) + + /**\name Enable/disable values */ +#define BMI088_ENABLE UINT8_C(0x01) +#define BMI088_DISABLE UINT8_C(0x00) + + /**\name Constant values macros */ +#define BMI088_ONE UINT8_C(1) +#define BMI088_TWO UINT8_C(2) +#define BMI088_THREE UINT8_C(3) +#define BMI088_FOUR UINT8_C(4) +#define BMI088_FIVE UINT8_C(5) +#define BMI088_SIX UINT8_C(6) +#define BMI088_SEVEN UINT8_C(7) +#define BMI088_EIGHT UINT8_C(8) +#define BMI088_NINE UINT8_C(9) +#define BMI088_TEN UINT8_C(10) +#define BMI088_ELEVEN UINT8_C(11) +#define BMI088_TWELVE UINT8_C(12) +#define BMI088_SIXTEEN UINT8_C(16) +#define BMI088_FIFTY UINT8_C(50) +#define BMI088_HUNDRED UINT8_C(100) +#define BMI088_ONE_FIFTY UINT8_C(150) +#define BMI088_CONFIG_STREAM_SIZE UINT16_C(6144) + + /**\name Sensor time array parameter definitions */ +#define BMI088_SENSOR_TIME_MSB_BYTE UINT8_C(2) +#define BMI088_SENSOR_TIME_XLSB_BYTE UINT8_C(1) +#define BMI088_SENSOR_TIME_LSB_BYTE UINT8_C(0) + + /**\name FIFO header data definitions */ +#define FIFO_HEAD_A UINT8_C(0x84) +#define FIFO_HEAD_G UINT8_C(0x90) +#define FIFO_HEAD_G_A UINT8_C(0x94) +#define FIFO_HEAD_SENSOR_TIME UINT8_C(0x44) +#define FIFO_HEAD_INPUT_CONFIG UINT8_C(0x48) +#define FIFO_HEAD_SKIP_FRAME UINT8_C(0x40) +#define FIFO_HEAD_OVER_READ_MSB UINT8_C(0x80) +#define FIFO_HEAD_SAMPLE_DROP UINT8_C(0x50) + + /**\name FIFO headerless mode data enable definitions */ +#define BMI088_FIFO_A_ENABLE UINT8_C(0x40) + + /**\name FIFO configuration selection */ +#define BMI088_FIFO_STOP_ON_FULL UINT8_C(0x01) +#define BMI088_FIFO_TIME UINT8_C(0x02) +#define BMI088_FIFO_TAG_INTR2 UINT8_C(0x04) +#define BMI088_FIFO_TAG_INTR1 UINT8_C(0x08) +#define BMI088_FIFO_HEADER UINT8_C(0x10) +#define BMI088_FIFO_ACCEL UINT8_C(0x40) +#define BMI088_FIFO_ALL UINT8_C(0x7F) +#define BMI088_FIFO_CONFIG_0_MASK UINT8_C(0x03) +#define BMI088_FIFO_CONFIG_1_MASK UINT8_C(0xFC) + + /**\name FIFO frame count definition */ +#define FIFO_LSB_CONFIG_CHECK UINT8_C(0x00) +#define FIFO_MSB_CONFIG_CHECK UINT8_C(0x80) +#define BMI088_FIFO_TAG_INTR_MASK UINT8_C(0xFC) + + /**\name FIFO dropped frame definition */ +#define ACCEL_FIFO_DROP UINT8_C(0x01) + + /**\name FIFO sensor time length definitions*/ +#define BMI088_SENSOR_TIME_LENGTH UINT8_C(3) + + /**\name FIFO length definitions */ +#define BMI088_FIFO_A_LENGTH UINT8_C(6) +#define BMI088_FIFO_G_ALL_DATA_LENGTH UINT8_C(8) +#define BMI088_FIFO_G_X_LENGTH UINT8_C(2) +#define BMI088_FIFO_G_Y_LENGTH UINT8_C(2) +#define BMI088_FIFO_G_Z_LENGTH UINT8_C(2) + + /**\name Self test result indicators */ +#define BMI088_SELFTEST_PASS UINT8_C(0) +#define BMI088_SELFTEST_FAIL INT8_C(-1) + + /**\name Sensor bit resolution */ +#define BMI088_16_BIT_RESOLUTION UINT8_C(16) + + /**\name Absolute value */ +#ifndef ABS +#define ABS(a) ((a) > 0 ? (a) : -(a)) +#endif + + /**\name Utility Macros */ +#define BMI088_SET_LOW_BYTE UINT16_C(0x00FF) +#define BMI088_SET_HIGH_BYTE UINT16_C(0xFF00) +#define BMI088_SET_LOW_NIBBLE UINT8_C(0x0F) + + /**\name Macro definition for register bit slicing, read access */ +#define BMI088_GET_BITSLICE(regvar, bitname)\ + (regvar & bitname##_MASK) >> bitname##_POS + + /**\name Macro definition for register bit slicing, write access */ +#define BMI088_SET_BITSLICE(regvar, bitname, val)\ + (regvar & ~bitname##_MASK) | ((val<> 8) + + /*************************** Data structures *****************************/ + + /**\name Typedef definitions */ + /*! + * @brief Bus communication function pointer which should be mapped to + * the platform specific read and write functions of the user + * + * @note : dev_addr is used for I2C read/write operations only. + * For SPI read/write operations this is dummy variable. + */ + typedef int8_t (*bmi088_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t len); + + /**\name delay function pointer */ + typedef void (*bmi088_delay_fptr_t)(uint32_t period); + + /**\name Structure Definitions */ + + /*! + * @brief Sensor XYZ data structure + */ + struct bmi088_sensor_data + { + /*! X-axis sensor data */ + int16_t x; + /*! Y-axis sensor data */ + int16_t y; + /*! Z-axis sensor data */ + int16_t z; + }; + + /*! + * @brief Sensor configuration structure + */ + struct bmi088_cfg + { + /*! power mode */ + uint8_t power; + /*! range */ + uint8_t range; + /*! bandwidth */ + uint8_t bw; + /*! output data rate */ + uint8_t odr; + }; + + /*! + * @brief Error Status structure + */ + struct bmi088_err_reg + { + /*! Indicates fatal error */ + uint8_t fatal_err; + /*! Indicates command error */ + uint8_t cmd_err; + /*! Indicates error code */ + uint8_t err_code; + }; + + /*! + * @brief Enum to select accelerometer Interrupt pins + */ + enum bmi088_accel_int_channel + { + BMI088_INT_CHANNEL_1, /* interrupt Channel 1 for accel sensor*/ + BMI088_INT_CHANNEL_2 /* interrupt Channel 2 */ + }; + + /*! + * @brief Enum to select gyroscope Interrupt pins + */ + enum bmi088_gyro_int_channel + { + BMI088_INT_CHANNEL_3, /* interrupt Channel 3 for gyro sensor*/ + BMI088_INT_CHANNEL_4, /* interrupt Channel 4 */ + BMI088_INT_CHANNEL_BOTH /* Both interrupt Channel 3 and 4 */ + }; + + /*! + * @brief Enum to select accelerometer interrupts + */ + enum bmi088_accel_int_types + { + BMI088_ACCEL_DATA_RDY_INT, /* Accel data ready interrupt */ + }; + + /*! + * @brief Enum to select gyroscope interrupts + */ + enum bmi088_gyro_int_types + { + BMI088_GYRO_DATA_RDY_INT, /* Gyro data ready interrupt */ + }; + + /*! + * @brief Interrupt pin configuration structure + */ + struct bmi088_int_pin_cfg + { +#ifdef LITTLE_ENDIAN + /*! Enable interrupt pin -> 0 - disable, 1 - enable */ + uint8_t enable_int_pin :1; + /*! 0 - push-pull, 1 - open drain */ + uint8_t output_mode :1; + /*! 0 - active low, 1 - active high level */ + uint8_t lvl :1; +#else + /*! 0 - active low, 1 - active high level */ + uint8_t lvl : 1; + /*! 0 - push-pull, 1 - open drain */ + uint8_t output_mode : 1; + /*! Enable interrupt pin -> 0 - disable, 1 - enable */ + uint8_t enable_int_pin : 1; +#endif + }; + + /*! + * @brief Interrupt Configuration structure + */ + struct bmi088_int_cfg + { + /*! Accel Interrupt channel */ + enum bmi088_accel_int_channel accel_int_channel; + /*! Gyro Interrupt channel */ + enum bmi088_gyro_int_channel gyro_int_channel; + /*! Select Accel Interrupt */ + enum bmi088_accel_int_types accel_int_type; + /*! Select Gyro Interrupt */ + enum bmi088_gyro_int_types gyro_int_type; + /*! Structure to configure accel interrupt pins */ + struct bmi088_int_pin_cfg accel_int_pin_cfg; + /*! Structure to configure gyro interrupt pin 3 */ + struct bmi088_int_pin_cfg gyro_int_pin_3_cfg; + /*! Structure to configure gyro interrupt pin 4 */ + struct bmi088_int_pin_cfg gyro_int_pin_4_cfg; + }; + + /*! + * @brief This structure holds the information for usage of + * FIFO by the user. + */ + struct bmi088_fifo_frame + { + /*! Data buffer of user defined length is to be mapped here */ + uint8_t *data; + /*! Number of bytes of FIFO to be read as specified by the user */ + uint16_t length; + /*! Length of each frame stored in fifo */ + uint16_t frame_length; + /*! Enabling the FIFO header to stream in header mode */ + uint8_t fifo_header_enable; + /*! Sensor data enabled status */ + uint8_t fifo_data_enable; + /*! Will be equal to length when no more frames are there to parse */ + uint16_t byte_start_idx; + /*! Value of FIFO sensor time */ + uint32_t sensor_time; + /*! Value of Skipped frame counts */ + uint8_t skipped_frame_count; + /*! Value of dropped frame count */ + uint8_t dropped_frame_count; + }; + + /*! + * @brief + * This structure holds all relevant information about BMI088 + */ + struct bmi088_dev + { + /*! Accel chip Id */ + uint8_t accel_chip_id; + /*! Gyro chip Id */ + uint8_t gyro_chip_id; + /*! Accel device Id */ + uint8_t accel_id; + /*! Gyro device Id */ + uint8_t gyro_id; + /*! 0 - I2C , 1 - SPI Interface */ + uint8_t interface; + /*! Decide SPI or I2C read mechanism */ + uint8_t dummy_byte; + /*! Structure to configure accel sensor */ + struct bmi088_cfg accel_cfg; + /*! Structure to configure gyro sensor */ + struct bmi088_cfg gyro_cfg; + /*! Accel FIFO related configurations */ + struct bmi088_fifo_frame *accel_fifo; + /*! Gyro FIFO related configurations */ + struct bmi088_fifo_frame *gyro_fifo; + /*! Config stream data buffer address will be assigned*/ + const uint8_t *config_file_ptr; + /*! Max read/write length (maximum supported length is 32). + To be set by the user */ + uint8_t read_write_len; + /*! Read function pointer */ + bmi088_com_fptr_t read; + /*! Write function pointer */ + bmi088_com_fptr_t write; + /*! Delay function pointer */ + bmi088_delay_fptr_t delay_ms; + }; + +/*************************** C++ guard macro *****************************/ +#ifdef __cplusplus +} +#endif + +#endif /* BMI088_DEFS_H_ */ diff --git a/src/drivers/bosch/interface/bmi088_fifo.h b/src/drivers/bosch/interface/bmi088_fifo.h new file mode 100644 index 0000000000..f293cb24b3 --- /dev/null +++ b/src/drivers/bosch/interface/bmi088_fifo.h @@ -0,0 +1,549 @@ +/* + * + **************************************************************************** + * Copyright (C) 2015 - 2016 Bosch Sensortec GmbH + * + * File : bmi088_fifo.h + * + * Date: 30 Oct 2017 + * + * Revision: + * + * Usage: Sensor Driver for BMI088 family of sensors + * + **************************************************************************** + * + * Disclaimer + * + * Common: + * Bosch Sensortec products are developed for the consumer goods industry. + * They may only be used within the parameters of the respective valid + * product data sheet. Bosch Sensortec products are provided with the + * express understanding that there is no warranty of fitness for a + * particular purpose.They are not fit for use in life-sustaining, + * safety or security sensitive systems or any system or device + * that may lead to bodily harm or property damage if the system + * or device malfunctions. In addition,Bosch Sensortec products are + * not fit for use in products which interact with motor vehicle systems. + * The resale and or use of products are at the purchasers own risk and + * his own responsibility. The examination of fitness for the intended use + * is the sole responsibility of the Purchaser. + * + * The purchaser shall indemnify Bosch Sensortec from all third party + * claims, including any claims for incidental, or consequential damages, + * arising from any product use not covered by the parameters of + * the respective valid product data sheet or not approved by + * Bosch Sensortec and reimburse Bosch Sensortec for all costs in + * connection with such claims. + * + * The purchaser must monitor the market for the purchased products, + * particularly with regard to product safety and inform Bosch Sensortec + * without delay of all security relevant incidents. + * + * Engineering Samples are marked with an asterisk (*) or (e). + * Samples may vary from the valid technical specifications of the product + * series. They are therefore not intended or fit for resale to third + * parties or for use in end products. Their sole purpose is internal + * client testing. The testing of an engineering sample may in no way + * replace the testing of a product series. Bosch Sensortec assumes + * no liability for the use of engineering samples. + * By accepting the engineering samples, the Purchaser agrees to indemnify + * Bosch Sensortec from all claims arising from the use of engineering + * samples. + * + * Special: + * This software module (hereinafter called "Software") and any information + * on application-sheets (hereinafter called "Information") is provided + * free of charge for the sole purpose to support your application work. + * The Software and Information is subject to the following + * terms and conditions: + * + * The Software is specifically designed for the exclusive use for + * Bosch Sensortec products by personnel who have special experience + * and training. Do not use this Software if you do not have the + * proper experience or training. + * + * This Software package is provided `` as is `` and without any expressed + * or implied warranties,including without limitation, the implied warranties + * of merchantability and fitness for a particular purpose. + * + * Bosch Sensortec and their representatives and agents deny any liability + * for the functional impairment + * of this Software in terms of fitness, performance and safety. + * Bosch Sensortec and their representatives and agents shall not be liable + * for any direct or indirect damages or injury, except as + * otherwise stipulated in mandatory applicable law. + * + * The Information provided is believed to be accurate and reliable. + * Bosch Sensortec assumes no responsibility for the consequences of use + * of such Information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of Bosch. Specifications mentioned in the Information are + * subject to change without notice. + **************************************************************************/ +/*! \file bmi088_fifo.h + \brief Sensor Driver for BMI088 family of sensors */ +#ifndef BMI088_FIFO_H_ +#define BMI088_FIFO_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif +#ifdef USE_FIFO + /*********************************************************************/ + /* header files */ +#include "bmi088.h" + + /*********************************************************************/ + /* (extern) variable declarations */ + + /*********************************************************************/ + /* function prototype declarations */ + + /*! + * @brief This API reads the FIFO data of Accel sensor. + * + * @param[in,out] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_get_accel_fifo_data(struct bmi088_dev *dev); + + /*! + * @brief This API parses and extracts the accelerometer frames from + * FIFO data read by the "bmi088_get_accel_fifo_data" API and stores + * it in the "accel_data" structure instance. + * + * @note The bmi088_extract_accel API should be called only after reading + * the FIFO data by calling the bmi088_get_accel_fifo_data() API + * + * @param[in,out] accel_data : Structure instance of bmi088_sensor_data + * where the accelerometer data in FIFO is stored. + * @param[in,out] accel_length : Number of accelerometer frames + * (x,y,z axes data) + * @param[in,out] dev : Structure instance of bmi088_dev. + * + * @note accel_length has the number of accelerometer frames + * (1 accel frame = 6 bytes) which the user needs to extract and store, is + * provided as input parameter by the user and the Number of valid + * accelerometer frames extracted and stored is updated in + * "accel_length" at the end of execution of this API. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_extract_accel(struct bmi088_sensor_data *accel_data, uint16_t *accel_length, const struct bmi088_dev *dev); + + /*! + * @brief This API reads the FIFO water mark level which is set + * in the accel sensor. + * + * @note The FIFO watermark is issued when the accel FIFO fill level + * is equal or above the watermark level. + * + * @param[out] fifo_wm : Pointer variable to store FIFO water mark level + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_get_accel_fifo_wm(uint16_t *fifo_wm, struct bmi088_dev *dev); + + /*! + * @brief This API sets the FIFO watermark level in the accel sensor. + * + * @note The FIFO watermark is issued when the accel FIFO fill level is + * equal or above the watermark level. + * + * @param[in] fifo_wm : Variable used to set the FIFO water mark level + * @param[out] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_set_accel_fifo_wm(uint16_t fifo_wm, struct bmi088_dev *dev); + + /*! + * @brief This API checks whether the Accel FIFO data is set for filtered + * or unfiltered mode. + * + * @param[out] accel_fifo_filter : Variable used to check whether the Accel + * data is filtered or unfiltered. + * Value | accel_fifo_filter + * ---------|------------------------- + * 0x00 | Unfiltered data + * 0x01 | Filtered data + * + * @param[in] dev : structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_get_accel_fifo_filt_data(uint8_t *accel_fifo_filter, struct bmi088_dev *dev); + + /*! + * @brief This API sets the condition of Accel FIFO data either to + * filtered or unfiltered mode. + * + * @param[in] accel_fifo_filter : Variable used to set the filtered or + * unfiltered condition of Accel FIFO data. + * value | accel_fifo_filter_data + * -----------|------------------------- + * 0x00 | Unfiltered data + * 0x01 | Filtered data + * + * @param[out] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_set_accel_fifo_filt_data(uint8_t accel_fifo_filter, struct bmi088_dev *dev); + + /*! + * @brief This API reads the down sampling rates which is configured + * for Accel FIFO data. + * + * @param[out] fifo_down : Variable used to specify the Accel FIFO + * down-sampling rates + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_get_fifo_down_accel(uint8_t *fifo_down, struct bmi088_dev *dev); + + /*! + * @brief This API sets the down-sampling rates for Accel FIFO. + * + * @param[in] fifo_down : Variable used to specify the Accel FIFO + * down-sampling rates. + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_set_fifo_down_accel(uint8_t fifo_down, struct bmi088_dev *dev); + + /*! + * @brief This API reads the length of Accel FIFO data in the units of bytes. + * + * @note This byte counter is updated each time a complete frame is read + * or written + * + * @param[in] fifo_length : Pointer variable used to store the value of + * fifo byte counter + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_get_accel_fifo_length(uint16_t *fifo_length, struct bmi088_dev *dev); + + /*! + * @brief This API sets the FIFO full interrupt of the accel sensor. + * + * @param[in] int_config : Structure instance of bmi088_int_cfg. + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_set_accel_fifo_full_int(struct bmi088_int_cfg *int_config, struct bmi088_dev *dev); + + /*! + * @brief This API sets the FIFO watermark interrupt of the accel sensor. + * + * @param[in] int_config : Structure instance of bmi088_int_cfg. + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_set_accel_fifo_wm_int(struct bmi088_int_cfg *int_config, struct bmi088_dev *dev); + + /*! + * @brief This API reads the FIFO data of Gyro sensor + * + * @param[in,out] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_get_gyro_fifo_data(struct bmi088_dev *dev); + + /*! + * @brief This API parses and extracts the gyroscope frames from + * FIFO data read by the "bmi088_get_gyro_fifo_data" API and stores + * it in the "gyro_data" structure instance parameter of this API + * + * @note The bmi088_extract_gyro API should be called only after reading + * the FIFO data by calling the bmi088_get_gyro_fifo_data() API + * + * @param[in,out] gyro_data : Structure instance of bmi088_sensor_data + * where the gyroscope data in FIFO is stored. + * @param[in,out] gyro_length : Number of gyroscope frames (x,y,z,r data) + * @param[in,out] dev : Structure instance of bmi088_dev. + * + * @note gyro_length has the number of gyroscope frames(x,y,z,r data) + * which the user needs to extract and store. It is provided as input + * parameter by the user and the number of valid gyroscope frames + * extracted and stored is updated in "gyro_length" at the end of + * execution of this API. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_extract_gyro(struct bmi088_sensor_data *gyro_data, uint16_t *gyro_length, const struct bmi088_dev *dev); + + /*! + * @brief This API reads the FIFO water mark level which is set + * in the gyro sensor. + * + * @note The FIFO watermark is issued when the FIFO fill level is + * equal or above the watermark level. + * + * @param[out] fifo_wm : Pointer variable to store FIFO water mark level + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_get_gyro_fifo_wm(uint8_t *fifo_wm, struct bmi088_dev *dev); + + /*! + * @brief This API sets the FIFO watermark level in the gyro sensor. + * + * @note The FIFO watermark is issued when the FIFO fill level is + * equal or above the watermark level. + * + * @param[in] fifo_wm : Variable used to set the FIFO water mark level + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_set_gyro_fifo_wm(uint8_t fifo_wm, struct bmi088_dev *dev); + + /*! + * @brief This API reads the FIFO operating mode which is set + * in the gyro sensor. + * + * @param[out] fifo_mode : Pointer variable used to get the FIFO + * operating mode + * value | fifo_mode + * --------------------------------|------------------------- + * BMI088_GYRO_BYPASS_OP_MODE | Bypass Mode + * BMI088_GYRO_FIFO_OP_MODE | Fifo Mode + * BMI088_GYRO_STREAM_OP_MODE | Stream Mode + * + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_get_gyro_fifo_mode(uint8_t *fifo_mode, struct bmi088_dev *dev); + + /*! + * @brief This API sets the FIFO operating mode in the gyro sensor. + * + * @param[in] fifo_mode : Variable used to set the FIFO operating mode + * value | Fifo Mode + * --------------------------------|------------------------- + * BMI088_GYRO_BYPASS_OP_MODE | Bypass Mode + * BMI088_GYRO_FIFO_OP_MODE | Fifo Mode + * BMI088_GYRO_STREAM_OP_MODE | Stream Mode + * + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_set_gyro_fifo_mode(uint8_t fifo_mode, struct bmi088_dev *dev); + + /*! + * @brief This API reads the data of axes to be stored in the FIFO in the gyro sensor. + * + * @param[out] fifo_data_select : Pointer variable used to get the selected data + * axes for FIFO data storage. + * value | fifo_data_select + * --------------------------------|------------------------- + * BMI088_GYRO_ALL_INT_DATA | X,Y,Z plus INT_status 0 and 1 + * BMI088_GYRO_X_DATA | X only + * BMI088_GYRO_Y_DATA | Y only + * BMI088_GYRO_Z_DATA | Z only + * + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_get_gyro_fifo_data_sel(uint8_t *fifo_data_select, struct bmi088_dev *dev); + + /*! + * @brief This API sets the data of axes to be stored in the FIFO in the gyro sensor. + * + * @param[in] fifo_data_select : Variable used to select data of axis to be stored + * in fifo + * value | Data of axis stored in FIFO + * --------------------------------|------------------------- + * BMI088_GYRO_ALL_INT_DATA | X,Y,Z plus INT_status 0 and 1 + * BMI088_GYRO_X_DATA | X only + * BMI088_GYRO_Y_DATA | Y only + * BMI088_GYRO_Z_DATA | Z only + * + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_set_gyro_fifo_data_sel(uint8_t fifo_data_select, struct bmi088_dev *dev); + + /*! + * @brief This API gets the length of Gyro FIFO data in the units of bytes. + * + * @note This byte counter is updated each time a complete frame is read + * or written + * + * @param[out] fifo_length : Pointer variable used to store the value of + * fifo byte counter + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_get_gyro_fifo_length(uint8_t *fifo_length, struct bmi088_dev *dev); + + /*! + * @brief This API gets the gyro FIFO overrun status. + * + * @param[out] fifo_overrun_status : Pointer variable used to store the status + * of FIFO overrun. + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_get_gyro_fifo_overrun(uint8_t *fifo_overrun_status, struct bmi088_dev *dev); + + /*! + * @brief This API gets the fifo tag status which is set in + * gyro sensor. + * + * @param[out] fifo_tag_status : Pointer variable used to store the value of + * fifo tag status. + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_get_gyro_fifo_tag(uint8_t *fifo_tag_status, struct bmi088_dev *dev); + + /*! + * @brief This API enables or disables fifo tag in gyro sensor. + * + * @param[in] fifo_tag : Variable used to enable or disable fifo tag + * value | fifo_tag + * --------------------------|----------------------------------- + * BMI088_DISABLE | Do not collect Interrupts in FIFO + * BMI088_ENABLE | Collects Interrupts in FIFO + * + * @param[in] dev : Structure instance of bmi088_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_set_gyro_fifo_tag(uint8_t fifo_tag, struct bmi088_dev *dev); + + /*! + * @brief This API enables or disables the FIFO full interrupt of the gyro sensor. + * + * @param[in] int_config : Structure instance of bmi088_int_cfg. + * @param[in] dev : Structure instance of bmi088_dev. + * @param[in] fifo_full_enable : Variable used to enable or disable fifo + * full interrupt + * value | fifo_full_enable + * --------------------------|----------------------------------- + * BMI088_DISABLE | Disables fifo full interrupt + * BMI088_ENABLE | Enables fifo full interrupt + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_set_gyro_fifo_full_int(struct bmi088_int_cfg *int_config, struct bmi088_dev *dev, uint8_t fifo_full_enable); + + /*! + * @brief This API enables or disables the FIFO watermark interrupt of the gyro sensor. + * + * @param[in] int_config : Structure instance of bmi088_int_cfg. + * @param[in] dev : Structure instance of bmi088_dev. + * @param[in] fifo_wm_enable : Variable used to enable or disable fifo + * watermark interrupt + * value | fifo_full_enable + * --------------------------|----------------------------------- + * BMI088_DISABLE | Disables fifo watermark interrupt + * BMI088_ENABLE | Enables fifo watermark interrupt + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + * + */ + uint16_t bmi088_set_gyro_fifo_wm_int(struct bmi088_int_cfg *int_config, struct bmi088_dev *dev, uint8_t fifo_wm_enable); + +#ifdef __cplusplus +} +#endif +#endif +#endif +/* End of BMI088_FIFO_H_ */ diff --git a/src/drivers/bosch/interface/bmp3.h b/src/drivers/bosch/interface/bmp3.h new file mode 100644 index 0000000000..8d8ed1c7b0 --- /dev/null +++ b/src/drivers/bosch/interface/bmp3.h @@ -0,0 +1,322 @@ +/** + * Copyright (C) 2016 - 2017 Bosch Sensortec GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 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. + * + * Neither the name of the copyright holder nor the names of the + * 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 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 + * + * The information provided is believed to be accurate and reliable. + * The copyright holder assumes no responsibility + * for the consequences of use + * of such information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of the copyright holder. + * + * @file bmp3.h + * @date 04 Dec 2017 + * @version 1.0.0 + * @brief + * + */ + +/*! @file bmp3.h + @brief Sensor driver for BMP3 sensor */ +/*! + * @defgroup BMP3 SENSOR API + * @{*/ +#ifndef BMP3_H_ +#define BMP3_H_ + +/* Header includes */ +#include "bmp3_defs.h" + + +/*! + * @brief This API is the entry point. + * It performs the selection of I2C/SPI read mechanism according to the + * selected interface and reads the chip-id and calibration data of the sensor. + * + * @param[in,out] dev : Structure instance of bmp3_dev + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +int8_t bmp3_init(struct bmp3_dev *dev); + +/*! + * @brief This API performs the soft reset of the sensor. + * + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. + */ +int8_t bmp3_soft_reset(const struct bmp3_dev *dev); + +/*! + * @brief This API sets the power control(pressure enable and + * temperature enable), over sampling, odr and filter + * settings in the sensor. + * + * @param[in] dev : Structure instance of bmp3_dev. + * @param[in] desired_settings : Variable used to select the settings which + * are to be set in the sensor. + * + * @note : Below are the macros to be used by the user for selecting the + * desired settings. User can do OR operation of these macros for configuring + * multiple settings. + * + * Macros | Functionality + * -----------------------|---------------------------------------------- + * BMP3_PRESS_EN_SEL | Enable/Disable pressure. + * BMP3_TEMP_EN_SEL | Enable/Disable temperature. + * BMP3_PRESS_OS_SEL | Set pressure oversampling. + * BMP3_TEMP_OS_SEL | Set temperature oversampling. + * BMP3_IIR_FILTER_SEL | Set IIR filter. + * BMP3_ODR_SEL | Set ODR. + * BMP3_OUTPUT_MODE_SEL | Set either open drain or push pull + * BMP3_LEVEL_SEL | Set interrupt pad to be active high or low + * BMP3_LATCH_SEL | Set interrupt pad to be latched or nonlatched. + * BMP3_DRDY_EN_SEL | Map/Unmap the drdy interrupt to interrupt pad. + * BMP3_I2C_WDT_EN_SEL | Enable/Disable I2C internal watch dog. + * BMP3_I2C_WDT_SEL_SEL | Set I2C watch dog timeout delay. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. + */ +int8_t bmp3_set_sensor_settings(uint32_t desired_settings, struct bmp3_dev *dev); + +/*! + * @brief This API gets the power control(power mode, pressure enable and + * temperature enable), over sampling, odr, filter, interrupt control and + * advance settings from the sensor. + * + * @param[in,out] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. + */ +int8_t bmp3_get_sensor_settings(struct bmp3_dev *dev); + +/*! + * @brief This API sets the power mode of the sensor. + * + * @param[in] dev : Structure instance of bmp3_dev. + * + * dev->settings.op_mode | Macros + * ----------------------|------------------- + * 0 | BMP3_SLEEP_MODE + * 1 | BMP3_FORCED_MODE + * 3 | BMP3_NORMAL_MODE + * + * + * @note : Before setting normal mode, valid odr and osr settings should be set + * in the sensor by using 'bmp3_set_sensor_settings' function. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +int8_t bmp3_set_op_mode(struct bmp3_dev *dev); + +/*! + * @brief This API gets the power mode of the sensor. + * + * @param[in] dev : Structure instance of bmp3_dev. + * @param[out] op_mode : Pointer variable to store the op-mode. + * + * op_mode | Macros + * ----------------------|------------------- + * 0 | BMP3_SLEEP_MODE + * 1 | BMP3_FORCED_MODE + * 3 | BMP3_NORMAL_MODE + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +int8_t bmp3_get_op_mode(uint8_t *op_mode, const struct bmp3_dev *dev); + +/*! + * @brief This API reads the pressure, temperature or both data from the + * sensor, compensates the data and store it in the bmp3_data structure + * instance passed by the user. + * + * @param[in] sensor_comp : Variable which selects which data to be read from + * the sensor. + * + * sensor_comp | Macros + * ------------|------------------- + * 1 | BMP3_PRESS + * 2 | BMP3_TEMP + * 3 | BMP3_ALL + * + * @param[out] data : Structure instance of bmp3_data. + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +int8_t bmp3_get_sensor_data(uint8_t sensor_comp, struct bmp3_data *data, struct bmp3_dev *dev); + +/*! + * @brief This API writes the given data to the register address + * of the sensor. + * + * @param[in] reg_addr : Register address from where the data to be written. + * @param[in] reg_data : Pointer to data buffer which is to be written + * in the sensor. + * @param[in] len : No of bytes of data to write.. + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +int8_t bmp3_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, const struct bmp3_dev *dev); + +/*! + * @brief This API reads the data from the given register address of the sensor. + * + * @param[in] reg_addr : Register address from where the data to be read + * @param[out] reg_data : Pointer to data buffer to store the read data. + * @param[in] length : No of bytes of data to be read. + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +int8_t bmp3_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t length, const struct bmp3_dev *dev); + +/*! + * @brief This API sets the fifo_config_1(fifo_mode, + * fifo_stop_on_full, fifo_time_en, fifo_press_en, fifo_temp_en), + * fifo_config_2(fifo_subsampling, data_select) and int_ctrl(fwtm_en, ffull_en) + * settings in the sensor. + * + * @param[in] dev : Structure instance of bmp3_dev. + * @param[in] desired_settings : Variable used to select the FIFO settings which + * are to be set in the sensor. + * + * @note : Below are the macros to be used by the user for selecting the + * desired settings. User can do OR operation of these macros for configuring + * multiple settings. + * + * Macros | Functionality + * --------------------------------|---------------------------- + * BMP3_FIFO_MODE_SEL | Enable/Disable FIFO + * BMP3_FIFO_STOP_ON_FULL_EN_SEL | Set FIFO stop on full interrupt + * BMP3_FIFO_TIME_EN_SEL | Enable/Disable FIFO time + * BMP3_FIFO_PRESS_EN_SEL | Enable/Disable pressure + * BMP3_FIFO_TEMP_EN_SEL | Enable/Disable temperature + * BMP3_FIFO_DOWN_SAMPLING_SEL | Set FIFO downsampling + * BMP3_FIFO_FILTER_EN_SEL | Enable/Disable FIFO filter + * BMP3_FIFO_FWTM_EN_SEL | Enable/Disable FIFO watermark interrupt + * BMP3_FIFO_FFULL_EN_SEL | Enable/Disable FIFO full interrupt + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. + */ +int8_t bmp3_set_fifo_settings(uint16_t desired_settings, const struct bmp3_dev *dev); + +/*! + * @brief This API gets the fifo_config_1(fifo_mode, + * fifo_stop_on_full, fifo_time_en, fifo_press_en, fifo_temp_en), + * fifo_config_2(fifo_subsampling, data_select) and int_ctrl(fwtm_en, ffull_en) + * settings from the sensor. + * + * @param[in,out] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. + */ +int8_t bmp3_get_fifo_settings(const struct bmp3_dev *dev); + +/*! + * @brief This API gets the fifo data from the sensor. + * + * @param[in,out] dev : Structure instance of bmp3 device, where the fifo + * data will be stored in fifo buffer. + * + * @return Result of API execution status. + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. + */ +int8_t bmp3_get_fifo_data(const struct bmp3_dev *dev); + +/*! + * @brief This API gets the fifo length from the sensor. + * + * @param[out] fifo_length : Variable used to store the fifo length. + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status. + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. + */ +int8_t bmp3_get_fifo_length(uint16_t *fifo_length, const struct bmp3_dev *dev); + +/*! + * @brief This API extracts the temperature and/or pressure data from the FIFO + * data which is already read from the fifo. + * + * @param[out] data : Array of bmp3_data structures where the temperature + * and pressure frames will be stored. + * @param[in,out] dev : Structure instance of bmp3_dev which contains the + * fifo buffer to parse the temperature and pressure frames. + * + * @return Result of API execution status. + * @retval zero -> Success / -ve value -> Error. + */ +int8_t bmp3_extract_fifo_data(struct bmp3_data *data, struct bmp3_dev *dev); + +/*! + * @brief This API gets the command ready, data ready for pressure and + * temperature and interrupt (fifo watermark, fifo full, data ready) and + * error status from the sensor. + * + * @param[in,out] dev : Structure instance of bmp3_dev + * + * @return Result of API execution status. + * @retval zero -> Success / -ve value -> Error. + */ +int8_t bmp3_get_status(struct bmp3_dev *dev); + +/*! + * @brief This API sets the fifo watermark length according to the frames count + * set by the user in the device structure. Refer below for usage. + * + * @note: dev->fifo->data.req_frames = 50; + * + * @param[in] dev : Structure instance of bmp3_dev + * + * @return Result of API execution status. + * @retval zero -> Success / -ve value -> Error. + */ +int8_t bmp3_set_fifo_watermark(const struct bmp3_dev *dev); + +#endif /* BMP3_H_ */ +/** @}*/ + diff --git a/src/drivers/bosch/interface/bmp3_defs.h b/src/drivers/bosch/interface/bmp3_defs.h new file mode 100644 index 0000000000..3bcdaeacce --- /dev/null +++ b/src/drivers/bosch/interface/bmp3_defs.h @@ -0,0 +1,731 @@ +/** + * Copyright (C) 2016 - 2017 Bosch Sensortec GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 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. + * + * Neither the name of the copyright holder nor the names of the + * 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 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 + * + * The information provided is believed to be accurate and reliable. + * The copyright holder assumes no responsibility + * for the consequences of use + * of such information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of the copyright holder. + * + * @file bmp3_defs.h + * @date 04 Dec 2017 + * @version 1.0.0 + * @brief + * + */ + +/*! @file bmp3_defs.h + @brief Sensor driver for BMP3 sensor */ +/*! + * @defgroup BMP3 SENSOR API + * @brief + * @{*/ +#ifndef BMP3_DEFS_H_ +#define BMP3_DEFS_H_ + +/********************************************************/ +/* header includes */ +#ifdef __KERNEL__ +#include +#include +#else +#include +#include +#endif + +/*************************** Common macros *****************************/ + +#if !defined(UINT8_C) && !defined(INT8_C) +#define INT8_C(x) S8_C(x) +#define UINT8_C(x) U8_C(x) +#endif + +#if !defined(UINT16_C) && !defined(INT16_C) +#define INT16_C(x) S16_C(x) +#define UINT16_C(x) U16_C(x) +#endif + +#if !defined(INT32_C) && !defined(UINT32_C) +#define INT32_C(x) S32_C(x) +#define UINT32_C(x) U32_C(x) +#endif + +#if !defined(INT64_C) && !defined(UINT64_C) +#define INT64_C(x) S64_C(x) +#define UINT64_C(x) U64_C(x) +#endif + +/**@}*/ + +/**\name C standard macros */ +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *) 0) +#endif +#endif + +#define TRUE UINT8_C(1) +#define FALSE UINT8_C(0) + +/********************************************************/ +/**\name Compiler switch macros */ +/**\name Comment the below line to use fixed-point compensation */ +#define FLOATING_POINT_COMPENSATION + +/********************************************************/ +/**\name Macro definitions */ + +/**\name I2C addresses */ +#define BMP3_I2C_ADDR_PRIM UINT8_C(0x76) +#define BMP3_I2C_ADDR_SEC UINT8_C(0x77) + +/**\name BMP3 chip identifier */ +#define BMP3_CHIP_ID UINT8_C(0x50) +/**\name BMP3 pressure settling time (micro secs)*/ +#define BMP3_PRESS_SETTLE_TIME UINT16_C(392) +/**\name BMP3 temperature settling time (micro secs) */ +#define BMP3_TEMP_SETTLE_TIME UINT16_C(313) +/**\name BMP3 adc conversion time (micro secs) */ +#define BMP3_ADC_CONV_TIME UINT16_C(2000) + +/**\name Register Address */ +#define BMP3_CHIP_ID_ADDR UINT8_C(0x00) +#define BMP3_ERR_REG_ADDR UINT8_C(0x02) +#define BMP3_SENS_STATUS_REG_ADDR UINT8_C(0x03) +#define BMP3_DATA_ADDR UINT8_C(0x04) +#define BMP3_EVENT_ADDR UINT8_C(0x10) +#define BMP3_INT_STATUS_REG_ADDR UINT8_C(0x11) +#define BMP3_FIFO_LENGTH_ADDR UINT8_C(0x12) +#define BMP3_FIFO_DATA_ADDR UINT8_C(0x14) +#define BMP3_FIFO_WM_ADDR UINT8_C(0x15) +#define BMP3_FIFO_CONFIG_1_ADDR UINT8_C(0x17) +#define BMP3_FIFO_CONFIG_2_ADDR UINT8_C(0x18) +#define BMP3_INT_CTRL_ADDR UINT8_C(0x19) +#define BMP3_IF_CONF_ADDR UINT8_C(0x1A) +#define BMP3_PWR_CTRL_ADDR UINT8_C(0x1B) +#define BMP3_OSR_ADDR UINT8_C(0X1C) +#define BMP3_CALIB_DATA_ADDR UINT8_C(0x31) +#define BMP3_CMD_ADDR UINT8_C(0x7E) + +/**\name Error status macros */ +#define BMP3_FATAL_ERR UINT8_C(0x01) +#define BMP3_CMD_ERR UINT8_C(0x02) +#define BMP3_CONF_ERR UINT8_C(0x04) + +/**\name Status macros */ +#define BMP3_CMD_RDY UINT8_C(0x10) +#define BMP3_DRDY_PRESS UINT8_C(0x20) +#define BMP3_DRDY_TEMP UINT8_C(0x40) + +/**\name Power mode macros */ +#define BMP3_SLEEP_MODE UINT8_C(0x00) +#define BMP3_FORCED_MODE UINT8_C(0x01) +#define BMP3_NORMAL_MODE UINT8_C(0x03) + +/**\name FIFO related macros */ +/**\name FIFO enable */ +#define BMP3_ENABLE UINT8_C(0x01) +#define BMP3_DISABLE UINT8_C(0x00) + +/**\name Interrupt pin configuration macros */ +/**\name Open drain */ +#define BMP3_INT_PIN_OPEN_DRAIN UINT8_C(0x01) +#define BMP3_INT_PIN_PUSH_PULL UINT8_C(0x00) + +/**\name Level */ +#define BMP3_INT_PIN_ACTIVE_HIGH UINT8_C(0x01) +#define BMP3_INT_PIN_ACTIVE_LOW UINT8_C(0x00) + +/**\name Latch */ +#define BMP3_INT_PIN_LATCH UINT8_C(0x01) +#define BMP3_INT_PIN_NON_LATCH UINT8_C(0x00) + +/**\name Advance settings */ +/**\name I2c watch dog timer period selection */ +#define BMP3_I2C_WDT_SHORT_1_25_MS UINT8_C(0x00) +#define BMP3_I2C_WDT_LONG_40_MS UINT8_C(0x01) + +/**\name FIFO Sub-sampling macros */ +#define BMP3_FIFO_NO_SUBSAMPLING UINT8_C(0x00) +#define BMP3_FIFO_SUBSAMPLING_2X UINT8_C(0x01) +#define BMP3_FIFO_SUBSAMPLING_4X UINT8_C(0x02) +#define BMP3_FIFO_SUBSAMPLING_8X UINT8_C(0x03) +#define BMP3_FIFO_SUBSAMPLING_16X UINT8_C(0x04) +#define BMP3_FIFO_SUBSAMPLING_32X UINT8_C(0x05) +#define BMP3_FIFO_SUBSAMPLING_64X UINT8_C(0x06) +#define BMP3_FIFO_SUBSAMPLING_128X UINT8_C(0x07) + +/**\name Over sampling macros */ +#define BMP3_NO_OVERSAMPLING UINT8_C(0x00) +#define BMP3_OVERSAMPLING_2X UINT8_C(0x01) +#define BMP3_OVERSAMPLING_4X UINT8_C(0x02) +#define BMP3_OVERSAMPLING_8X UINT8_C(0x03) +#define BMP3_OVERSAMPLING_16X UINT8_C(0x04) +#define BMP3_OVERSAMPLING_32X UINT8_C(0x05) + +/**\name Filter setting macros */ +#define BMP3_IIR_FILTER_DISABLE UINT8_C(0x00) +#define BMP3_IIR_FILTER_COEFF_1 UINT8_C(0x01) +#define BMP3_IIR_FILTER_COEFF_3 UINT8_C(0x02) +#define BMP3_IIR_FILTER_COEFF_7 UINT8_C(0x03) +#define BMP3_IIR_FILTER_COEFF_15 UINT8_C(0x04) +#define BMP3_IIR_FILTER_COEFF_31 UINT8_C(0x05) +#define BMP3_IIR_FILTER_COEFF_63 UINT8_C(0x06) +#define BMP3_IIR_FILTER_COEFF_127 UINT8_C(0x07) + +/**\name Odr setting macros */ +#define BMP3_ODR_200_HZ UINT8_C(0x00) +#define BMP3_ODR_100_HZ UINT8_C(0x01) +#define BMP3_ODR_50_HZ UINT8_C(0x02) +#define BMP3_ODR_25_HZ UINT8_C(0x03) +#define BMP3_ODR_12_5_HZ UINT8_C(0x04) +#define BMP3_ODR_6_25_HZ UINT8_C(0x05) +#define BMP3_ODR_3_1_HZ UINT8_C(0x06) +#define BMP3_ODR_1_5_HZ UINT8_C(0x07) +#define BMP3_ODR_0_78_HZ UINT8_C(0x08) +#define BMP3_ODR_0_39_HZ UINT8_C(0x09) +#define BMP3_ODR_0_2_HZ UINT8_C(0x0A) +#define BMP3_ODR_0_1_HZ UINT8_C(0x0B) +#define BMP3_ODR_0_05_HZ UINT8_C(0x0C) +#define BMP3_ODR_0_02_HZ UINT8_C(0x0D) +#define BMP3_ODR_0_01_HZ UINT8_C(0x0E) +#define BMP3_ODR_0_006_HZ UINT8_C(0x0F) +#define BMP3_ODR_0_003_HZ UINT8_C(0x10) +#define BMP3_ODR_0_001_HZ UINT8_C(0x11) + +/**\name API success code */ +#define BMP3_OK INT8_C(0) +/**\name API error codes */ +#define BMP3_E_NULL_PTR INT8_C(-1) +#define BMP3_E_DEV_NOT_FOUND INT8_C(-2) +#define BMP3_E_INVALID_ODR_OSR_SETTINGS INT8_C(-3) +#define BMP3_E_CMD_EXEC_FAILED INT8_C(-4) +#define BMP3_E_CONFIGURATION_ERR INT8_C(-5) +#define BMP3_E_INVALID_LEN INT8_C(-6) +#define BMP3_E_COMM_FAIL INT8_C(-7) +#define BMP3_E_FIFO_WATERMARK_NOT_REACHED INT8_C(-8) + +/**\name API warning codes */ +#define BMP3_W_SENSOR_NOT_ENABLED UINT8_C(1) +#define BMP3_W_INVALID_FIFO_REQ_FRAME_CNT UINT8_C(2) + +/**\name Macros to select the which sensor settings are to be set by the user. + These values are internal for API implementation. Don't relate this to + data sheet. */ +#define BMP3_PRESS_EN_SEL UINT16_C(1 << 1) +#define BMP3_TEMP_EN_SEL UINT16_C(1 << 2) +#define BMP3_DRDY_EN_SEL UINT16_C(1 << 3) +#define BMP3_PRESS_OS_SEL UINT16_C(1 << 4) +#define BMP3_TEMP_OS_SEL UINT16_C(1 << 5) +#define BMP3_IIR_FILTER_SEL UINT16_C(1 << 6) +#define BMP3_ODR_SEL UINT16_C(1 << 7) +#define BMP3_OUTPUT_MODE_SEL UINT16_C(1 << 8) +#define BMP3_LEVEL_SEL UINT16_C(1 << 9) +#define BMP3_LATCH_SEL UINT16_C(1 << 10) +#define BMP3_I2C_WDT_EN_SEL UINT16_C(1 << 11) +#define BMP3_I2C_WDT_SEL_SEL UINT16_C(1 << 12) +#define BMP3_ALL_SETTINGS UINT16_C(0x7FF) + +/**\name Macros to select the which FIFO settings are to be set by the user + These values are internal for API implementation. Don't relate this to + data sheet.*/ +#define BMP3_FIFO_MODE_SEL UINT16_C(1 << 1) +#define BMP3_FIFO_STOP_ON_FULL_EN_SEL UINT16_C(1 << 2) +#define BMP3_FIFO_TIME_EN_SEL UINT16_C(1 << 3) +#define BMP3_FIFO_PRESS_EN_SEL UINT16_C(1 << 4) +#define BMP3_FIFO_TEMP_EN_SEL UINT16_C(1 << 5) +#define BMP3_FIFO_DOWN_SAMPLING_SEL UINT16_C(1 << 6) +#define BMP3_FIFO_FILTER_EN_SEL UINT16_C(1 << 7) +#define BMP3_FIFO_FWTM_EN_SEL UINT16_C(1 << 8) +#define BMP3_FIFO_FULL_EN_SEL UINT16_C(1 << 9) +#define BMP3_FIFO_ALL_SETTINGS UINT16_C(0x3FF) + +/**\name Sensor component selection macros + These values are internal for API implementation. Don't relate this to + data sheet.*/ +#define BMP3_PRESS UINT8_C(1) +#define BMP3_TEMP UINT8_C(1 << 1) +#define BMP3_ALL UINT8_C(0x03) + +/**\name Macros for bit masking */ +#define BMP3_ERR_FATAL_MSK UINT8_C(0x01) + +#define BMP3_ERR_CMD_MSK UINT8_C(0x02) +#define BMP3_ERR_CMD_POS UINT8_C(0x01) + +#define BMP3_ERR_CONF_MSK UINT8_C(0x04) +#define BMP3_ERR_CONF_POS UINT8_C(0x02) + +#define BMP3_STATUS_CMD_RDY_MSK UINT8_C(0x10) +#define BMP3_STATUS_CMD_RDY_POS UINT8_C(0x04) + +#define BMP3_STATUS_DRDY_PRESS_MSK UINT8_C(0x20) +#define BMP3_STATUS_DRDY_PRESS_POS UINT8_C(0x05) + +#define BMP3_STATUS_DRDY_TEMP_MSK UINT8_C(0x40) +#define BMP3_STATUS_DRDY_TEMP_POS UINT8_C(0x06) + +#define BMP3_OP_MODE_MSK UINT8_C(0x30) +#define BMP3_OP_MODE_POS UINT8_C(0x04) + +#define BMP3_PRESS_EN_MSK UINT8_C(0x01) + +#define BMP3_TEMP_EN_MSK UINT8_C(0x02) +#define BMP3_TEMP_EN_POS UINT8_C(0x01) + +#define BMP3_IIR_FILTER_MSK UINT8_C(0x0E) +#define BMP3_IIR_FILTER_POS UINT8_C(0x01) + +#define BMP3_ODR_MSK UINT8_C(0x1F) + +#define BMP3_PRESS_OS_MSK UINT8_C(0x07) + +#define BMP3_TEMP_OS_MSK UINT8_C(0x38) +#define BMP3_TEMP_OS_POS UINT8_C(0x03) + +#define BMP3_FIFO_MODE_MSK UINT8_C(0x01) + +#define BMP3_FIFO_STOP_ON_FULL_MSK UINT8_C(0x02) +#define BMP3_FIFO_STOP_ON_FULL_POS UINT8_C(0x01) + +#define BMP3_FIFO_TIME_EN_MSK UINT8_C(0x04) +#define BMP3_FIFO_TIME_EN_POS UINT8_C(0x02) + +#define BMP3_FIFO_PRESS_EN_MSK UINT8_C(0x08) +#define BMP3_FIFO_PRESS_EN_POS UINT8_C(0x03) + +#define BMP3_FIFO_TEMP_EN_MSK UINT8_C(0x10) +#define BMP3_FIFO_TEMP_EN_POS UINT8_C(0x04) + +#define BMP3_FIFO_FILTER_EN_MSK UINT8_C(0x18) +#define BMP3_FIFO_FILTER_EN_POS UINT8_C(0x03) + +#define BMP3_FIFO_DOWN_SAMPLING_MSK UINT8_C(0x07) + +#define BMP3_FIFO_FWTM_EN_MSK UINT8_C(0x08) +#define BMP3_FIFO_FWTM_EN_POS UINT8_C(0x03) + +#define BMP3_FIFO_FULL_EN_MSK UINT8_C(0x10) +#define BMP3_FIFO_FULL_EN_POS UINT8_C(0x04) + +#define BMP3_INT_OUTPUT_MODE_MSK UINT8_C(0x01) + +#define BMP3_INT_LEVEL_MSK UINT8_C(0x02) +#define BMP3_INT_LEVEL_POS UINT8_C(0x01) + +#define BMP3_INT_LATCH_MSK UINT8_C(0x04) +#define BMP3_INT_LATCH_POS UINT8_C(0x02) + +#define BMP3_INT_DRDY_EN_MSK UINT8_C(0x40) +#define BMP3_INT_DRDY_EN_POS UINT8_C(0x06) + +#define BMP3_I2C_WDT_EN_MSK UINT8_C(0x02) +#define BMP3_I2C_WDT_EN_POS UINT8_C(0x01) + +#define BMP3_I2C_WDT_SEL_MSK UINT8_C(0x04) +#define BMP3_I2C_WDT_SEL_POS UINT8_C(0x02) + +#define BMP3_INT_STATUS_FWTM_MSK UINT8_C(0x01) + +#define BMP3_INT_STATUS_FFULL_MSK UINT8_C(0x02) +#define BMP3_INT_STATUS_FFULL_POS UINT8_C(0x01) + +#define BMP3_INT_STATUS_DRDY_MSK UINT8_C(0x08) +#define BMP3_INT_STATUS_DRDY_POS UINT8_C(0x03) + + +/**\name UTILITY MACROS */ +#define BMP3_SET_LOW_BYTE UINT16_C(0x00FF) +#define BMP3_SET_HIGH_BYTE UINT16_C(0xFF00) + +/**\name Macro to combine two 8 bit data's to form a 16 bit data */ +#define BMP3_CONCAT_BYTES(msb, lsb) (((uint16_t)msb << 8) | (uint16_t)lsb) + + +#define BMP3_SET_BITS(reg_data, bitname, data) \ + ((reg_data & ~(bitname##_MSK)) | \ + ((data << bitname##_POS) & bitname##_MSK)) +/* Macro variant to handle the bitname position if it is zero */ +#define BMP3_SET_BITS_POS_0(reg_data, bitname, data) \ + ((reg_data & ~(bitname##_MSK)) | \ + (data & bitname##_MSK)) + +#define BMP3_GET_BITS(reg_data, bitname) ((reg_data & (bitname##_MSK)) >> \ + (bitname##_POS)) +/* Macro variant to handle the bitname position if it is zero */ +#define BMP3_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK)) + +#define BMP3_GET_LSB(var) (uint8_t)(var & BMP3_SET_LOW_BYTE) +#define BMP3_GET_MSB(var) (uint8_t)((var & BMP3_SET_HIGH_BYTE) >> 8) + +/**\name Macros related to size */ +#define BMP3_CALIB_DATA_LEN UINT8_C(21) +#define BMP3_P_AND_T_HEADER_DATA_LEN UINT8_C(7) +#define BMP3_P_OR_T_HEADER_DATA_LEN UINT8_C(4) +#define BMP3_P_T_DATA_LEN UINT8_C(6) +#define BMP3_GEN_SETT_LEN UINT8_C(7) +#define BMP3_P_DATA_LEN UINT8_C(3) +#define BMP3_T_DATA_LEN UINT8_C(3) +#define BMP3_SENSOR_TIME_LEN UINT8_C(3) +#define BMP3_FIFO_MAX_FRAMES UINT8_C(73) + +/********************************************************/ + +/*! + * @brief Interface selection Enums + */ +enum bmp3_intf { + /*! SPI interface */ + BMP3_SPI_INTF, + /*! I2C interface */ + BMP3_I2C_INTF +}; + +/********************************************************/ +/*! + * @brief Type definitions + */ +typedef int8_t (*bmp3_com_fptr_t)(uint8_t dev_id, uint8_t reg_addr, + uint8_t *data, uint16_t len); + +typedef void (*bmp3_delay_fptr_t)(uint32_t period); + +/********************************************************/ +/*! + * @brief Register Trim Variables + */ +struct bmp3_reg_calib_data { + /** + * @ Trim Variables + */ +/**@{*/ + uint16_t par_t1; + uint16_t par_t2; + int8_t par_t3; + int16_t par_p1; + int16_t par_p2; + int8_t par_p3; + int8_t par_p4; + uint16_t par_p5; + uint16_t par_p6; + int8_t par_p7; + int8_t par_p8; + int16_t par_p9; + int8_t par_p10; + int8_t par_p11; + int64_t t_lin; +/**@}*/ +}; + +/*! + * @brief bmp3 advance settings + */ +struct bmp3_adv_settings { + /*! i2c watch dog enable */ + uint8_t i2c_wdt_en; + /*! i2c watch dog select */ + uint8_t i2c_wdt_sel; +}; + +/*! + * @brief bmp3 odr and filter settings + */ +struct bmp3_odr_filter_settings { + /*! Pressure oversampling */ + uint8_t press_os; + /*! Temperature oversampling */ + uint8_t temp_os; + /*! IIR filter */ + uint8_t iir_filter; + /*! Output data rate */ + uint8_t odr; +}; + +/*! + * @brief bmp3 sensor status flags + */ +struct bmp3_sens_status { + /*! Command ready status */ + uint8_t cmd_rdy; + /*! Data ready for pressure */ + uint8_t drdy_press; + /*! Data ready for temperature */ + uint8_t drdy_temp; +}; + +/*! + * @brief bmp3 interrupt status flags + */ +struct bmp3_int_status { + /*! fifo watermark interrupt */ + uint8_t fifo_wm; + /*! fifo full interrupt */ + uint8_t fifo_full; + /*! data ready interrupt */ + uint8_t drdy; +}; + +/*! + * @brief bmp3 error status flags + */ +struct bmp3_err_status { + /*! fatal error */ + uint8_t fatal; + /*! command error */ + uint8_t cmd; + /*! configuration error */ + uint8_t conf; +}; + +/*! + * @brief bmp3 status flags + */ +struct bmp3_status { + /*! Interrupt status */ + struct bmp3_int_status intr; + /*! Sensor status */ + struct bmp3_sens_status sensor; + /*! Error status */ + struct bmp3_err_status err; + /*! power on reset status */ + uint8_t pwr_on_rst; +}; + + +/*! + * @brief bmp3 interrupt pin settings + */ +struct bmp3_int_ctrl_settings { + /*! Output mode */ + uint8_t output_mode; + /*! Active high/low */ + uint8_t level; + /*! Latched or Non-latched */ + uint8_t latch; + /*! Data ready interrupt */ + uint8_t drdy_en; +}; + +/*! + * @brief bmp3 device settings + */ +struct bmp3_settings { + /*! Power mode which user wants to set */ + uint8_t op_mode; + /*! Enable/Disable pressure sensor */ + uint8_t press_en; + /*! Enable/Disable temperature sensor */ + uint8_t temp_en; + /*! ODR and filter configuration */ + struct bmp3_odr_filter_settings odr_filter; + /*! Interrupt configuration */ + struct bmp3_int_ctrl_settings int_settings; + /*! Advance settings */ + struct bmp3_adv_settings adv_settings; +}; + +/*! + * @brief bmp3 fifo frame + */ +struct bmp3_fifo_data { + /*! Data buffer of user defined length is to be mapped here + 512 + 4 */ + uint8_t buffer[516]; + /*! Number of bytes of data read from the fifo */ + uint16_t byte_count; + /*! Number of frames to be read as specified by the user */ + uint8_t req_frames; + /*! Will be equal to length when no more frames are there to parse */ + uint16_t start_idx; + /*! Will contain the no of parsed data frames from fifo */ + uint8_t parsed_frames; + /*! Configuration error */ + uint8_t config_err; + /*! Sensor time */ + uint32_t sensor_time; + /*! FIFO input configuration change */ + uint8_t config_change; + /*! All available frames are parsed */ + uint8_t frame_not_available; +}; + +/*! + * @brief bmp3 fifo configuration + */ +struct bmp3_fifo_settings { + /*! enable/disable */ + uint8_t mode; + /*! stop on full enable/disable */ + uint8_t stop_on_full_en; + /*! time enable/disable */ + uint8_t time_en; + /*! pressure enable/disable */ + uint8_t press_en; + /*! temperature enable/disable */ + uint8_t temp_en; + /*! down sampling rate */ + uint8_t down_sampling; + /*! filter enable/disable */ + uint8_t filter_en; + /*! FIFO watermark enable/disable */ + uint8_t fwtm_en; + /*! FIFO full enable/disable */ + uint8_t ffull_en; +}; + +/*! + * @brief bmp3 bmp3 FIFO + */ +struct bmp3_fifo { + /*! FIFO frame structure */ + struct bmp3_fifo_data data; + /*! FIFO config structure */ + struct bmp3_fifo_settings settings; +}; + +#ifdef FLOATING_POINT_COMPENSATION +/*! + * @brief Quantized Trim Variables + */ +struct bmp3_quantized_calib_data { + /** + * @ Quantized Trim Variables + */ +/**@{*/ + float par_t1; + float par_t2; + float par_t3; + float par_p1; + float par_p2; + float par_p3; + float par_p4; + float par_p5; + float par_p6; + float par_p7; + float par_p8; + float par_p9; + float par_p10; + float par_p11; + float t_lin; +/**@}*/ +}; + +/*! + * @brief Calibration data + */ +struct bmp3_calib_data { + /*! Quantized data */ + struct bmp3_quantized_calib_data quantized_calib_data; + /*! Register data */ + struct bmp3_reg_calib_data reg_calib_data; +}; + +/*! + * @brief bmp3 sensor structure which comprises of temperature and pressure + * data. + */ +struct bmp3_data { + /*! Compensated temperature */ + float temperature; + /*! Compensated pressure */ + float pressure; +}; + +#else +/*! + * @brief bmp3 sensor structure which comprises of temperature and pressure + * data. + */ +struct bmp3_data { + /*! Compensated temperature */ + int64_t temperature; + /*! Compensated pressure */ + uint64_t pressure; +}; + +/*! + * @brief Calibration data + */ +struct bmp3_calib_data { + /*! Register data */ + struct bmp3_reg_calib_data reg_calib_data; +}; + +#endif /* BMP3_USE_FLOATING_POINT */ + +/*! + * @brief bmp3 sensor structure which comprises of uncompensated temperature + * and pressure data. + */ +struct bmp3_uncomp_data { + /*! un-compensated pressure */ + uint32_t pressure; + /*! un-compensated temperature */ + uint32_t temperature; +}; + +/*! + * @brief bmp3 device structure + */ +struct bmp3_dev { + /*! Chip Id */ + uint8_t chip_id; + /*! Device Id */ + uint8_t dev_id; + /*! SPI/I2C interface */ + enum bmp3_intf intf; + /*! Decide SPI or I2C read mechanism */ + uint8_t dummy_byte; + /*! Read function pointer */ + bmp3_com_fptr_t read; + /*! Write function pointer */ + bmp3_com_fptr_t write; + /*! Delay function pointer */ + bmp3_delay_fptr_t delay_ms; + /*! Trim data */ + struct bmp3_calib_data calib_data; + /*! Sensor Settings */ + struct bmp3_settings settings; + /*! Sensor and interrupt status flags */ + struct bmp3_status status; + /*! FIFO data and settings structure */ + struct bmp3_fifo *fifo; +}; + +#endif /* BMP3_DEFS_H_ */ +/** @}*/ +/** @}*/ diff --git a/src/drivers/bosch/src/bmi088_accel.c b/src/drivers/bosch/src/bmi088_accel.c new file mode 100644 index 0000000000..1d545c956e --- /dev/null +++ b/src/drivers/bosch/src/bmi088_accel.c @@ -0,0 +1,1117 @@ +/* + **************************************************************************** + * Copyright (C) 2015 - 2016 Bosch Sensortec GmbH + * + * File :bmi088_accel.c + * + * Date: 30 Oct 2017 + * + * Revision: + * + * Usage: Sensor Driver for BMI088 family of sensors + * + **************************************************************************** + * Disclaimer + * + * Common: + * Bosch Sensortec products are developed for the consumer goods industry. + * They may only be used within the parameters of the respective valid + * product data sheet. Bosch Sensortec products are provided with the + * express understanding that there is no warranty of fitness for a + * particular purpose.They are not fit for use in life-sustaining, + * safety or security sensitive systems or any system or device + * that may lead to bodily harm or property damage if the system + * or device malfunctions. In addition,Bosch Sensortec products are + * not fit for use in products which interact with motor vehicle systems. + * The resale and or use of products are at the purchasers own risk and + * his own responsibility. The examination of fitness for the intended use + * is the sole responsibility of the Purchaser. + * + * The purchaser shall indemnify Bosch Sensortec from all third party + * claims, including any claims for incidental, or consequential damages, + * arising from any product use not covered by the parameters of + * the respective valid product data sheet or not approved by + * Bosch Sensortec and reimburse Bosch Sensortec for all costs in + * connection with such claims. + * + * The purchaser must monitor the market for the purchased products, + * particularly with regard to product safety and inform Bosch Sensortec + * without delay of all security relevant incidents. + * + * Engineering Samples are marked with an asterisk (*) or (e). + * Samples may vary from the valid technical specifications of the product + * series. They are therefore not intended or fit for resale to third + * parties or for use in end products. Their sole purpose is internal + * client testing. The testing of an engineering sample may in no way + * replace the testing of a product series. Bosch Sensortec assumes + * no liability for the use of engineering samples. + * By accepting the engineering samples, the Purchaser agrees to indemnify + * Bosch Sensortec from all claims arising from the use of engineering + * samples. + * + * Special: + * This software module (hereinafter called "Software") and any information + * on application-sheets (hereinafter called "Information") is provided + * free of charge for the sole purpose to support your application work. + * The Software and Information is subject to the following + * terms and conditions: + * + * The Software is specifically designed for the exclusive use for + * Bosch Sensortec products by personnel who have special experience + * and training. Do not use this Software if you do not have the + * proper experience or training. + * + * This Software package is provided `` as is `` and without any expressed + * or implied warranties,including without limitation, the implied warranties + * of merchantability and fitness for a particular purpose. + * + * Bosch Sensortec and their representatives and agents deny any liability + * for the functional impairment + * of this Software in terms of fitness, performance and safety. + * Bosch Sensortec and their representatives and agents shall not be liable + * for any direct or indirect damages or injury, except as + * otherwise stipulated in mandatory applicable law. + * + * The Information provided is believed to be accurate and reliable. + * Bosch Sensortec assumes no responsibility for the consequences of use + * of such Information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of Bosch. Specifications mentioned in the Information are + * subject to change without notice. + **************************************************************************/ +/*! \file bmi088_accel.c + \brief Sensor Driver for BMI088 family of sensors */ +/***************************************************************************/ +/**\name Header files + ****************************************************************************/ +#include "bmi088.h" + +/***************************************************************************/ +/**\name Local structures + ****************************************************************************/ + +/***************************************************************************/ +/*! Static Function Declarations + ****************************************************************************/ + +/*! + * @brief This API is used to validate the device structure pointer for + * null conditions. + * + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ +static uint16_t null_ptr_check(struct bmi088_dev *dev); + +/*! + * @brief This API configures the pins which fire the + * interrupt signal when any interrupt occurs. + * + * @param[in] int_config : Structure instance of bmi088_int_cfg. + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ +static uint16_t set_int_pin_config(const struct bmi088_int_cfg *int_config, struct bmi088_dev *dev); + +/*! + * @brief This API sets the data ready interrupt for accel sensor + * + * @param[in] int_config : Structure instance of bmi088_int_cfg. + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ +static uint16_t set_accel_data_ready_int(const struct bmi088_int_cfg *int_config, struct bmi088_dev *dev); + +/*! + * @brief This API writes the config stream data in memory using burst mode + * + * @param[in] stream_data : Pointer to store data of 32 bytes + * @param[in] index : Represents value in multiple of 32 bytes + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +static uint16_t stream_transfer_write(const uint8_t *stream_data, uint16_t index, struct bmi088_dev *dev); + +/*! + * @brief This function enables and configures the Accel which is needed + * for Self test operation. + * + * @param[in] dev : Structure instance of bmi088_dev + * + * @return results of self test + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ +static uint16_t set_accel_selftest_config(struct bmi088_dev *dev); + +/*! + * @brief This function validates the Accel Self test data and decides the + * result of Self test operation. + * + * @param[in] accel_data_diff : Pointer to structure variable which holds + * the Accel data difference of Self test operation + * + * @return results of self test operation + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ +static uint16_t validate_selftest(const struct bmi088_sensor_data *accel_data_diff); + +/*! + * @brief This API converts lsb value of axes to mg for self-test + * + * @param[in] accel_data_diff : Pointer variable used to pass accel difference + * values in g + * @param[out] accel_data_diff_mg : Pointer variable used to store accel + * difference values in mg + * + * @return None + */ +static void convert_lsb_g(const struct bmi088_sensor_data *accel_data_diff, + struct bmi088_sensor_data *accel_data_diff_mg); + +/*! + * @brief This API is used to calculate the power of given + * base value. + * + * @param[in] base : value of base + * @param[in] resolution : resolution of the sensor + * + * @return : returns the value of base^resolution + */ +static int32_t power(int16_t base, uint8_t resolution); + +/***************************************************************************/ +/**\name Extern Declarations + ****************************************************************************/ + +/***************************************************************************/ +/**\name Globals + ****************************************************************************/ + +/* Copy of accel_cfg structure of device structure.It + * prevents overwriting same accel configuration data */ +static struct bmi088_cfg accel_cfg_copy; + +/***************************************************************************/ +/**\name Function definitions + ****************************************************************************/ +/*! + * @brief This API is the entry point for accel sensor. + * It performs the selection of I2C/SPI read mechanism according to the + * selected interface and reads the chip-id of accel sensor. + */ +uint16_t bmi088_accel_init(struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t data = 0, reg_addr; + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + if (dev->interface == BMI088_SPI_INTF) + { + /* Set dummy byte in case of SPI interface*/ + dev->dummy_byte = 1; + } + else + { + /* Make dummy byte 0 in case of I2C interface*/ + dev->dummy_byte = 0; + } + + reg_addr = BMI088_ACCEL_CHIP_ID_REG; + rslt |= bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Assign Chip Id */ + dev->accel_chip_id = data; + + /* Initializing accel sensor parameters with default values */ + dev->accel_cfg.bw = BMI088_ACCEL_ODR_100_HZ; + dev->accel_cfg.power = BMI088_ACCEL_PM_SUSPEND; + dev->accel_cfg.range = BMI088_ACCEL_RANGE_6G; + + /* Copying accel_cfg parameters of device structure to + * accel_cfg_copy structure to maintain a copy */ + accel_cfg_copy.bw = dev->accel_cfg.bw; + accel_cfg_copy.power = dev->accel_cfg.power; + accel_cfg_copy.range = dev->accel_cfg.range; + + } + else + { + rslt = BMI088_E_COM_FAIL; + } + + } + + return rslt; +} + +/*! + * @brief This API is used to write the binary configuration in the sensor. + */ +uint16_t bmi088_write_config_file(struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + /* Disable advance power save*/ + uint8_t adv_power_save = 0, reg_addr; + /* Config loading disable*/ + uint8_t config_load = BMI088_DISABLE; + uint16_t index = 0; + uint8_t config_stream_status = 0; + + reg_addr = BMI088_ACCEL_PWR_CONF_REG; + /* Disable advanced power save*/ + rslt |= bmi088_set_accel_regs(reg_addr, &adv_power_save, BMI088_ONE, dev); + + /* Wait for sensor time synchronization. Refer the data-sheet for + more information*/ + dev->delay_ms(BMI088_ONE); + + if (rslt == BMI088_OK) + { + reg_addr = BMI088_ACCEL_INIT_CTRL_REG; + /* Disable config loading*/ + rslt |= bmi088_set_accel_regs(reg_addr, &config_load, BMI088_ONE, dev); + + /* Write the config stream */ + for (index = 0; index < BMI088_CONFIG_STREAM_SIZE; index += dev->read_write_len) + { + rslt |= stream_transfer_write((dev->config_file_ptr + index), index, dev); + } + + /* Enable config loading and FIFO mode */ + config_load = BMI088_ENABLE; + + rslt |= bmi088_set_accel_regs(reg_addr, &config_load, BMI088_ONE, dev); + + /* Wait till ASIC is initialized. Refer the data-sheet for + more information*/ + dev->delay_ms(BMI088_ONE_FIFTY); + + reg_addr = BMI088_ACCEL_INTERNAL_STAT_REG; + /* Read the status of config stream operation */ + rslt |= bmi088_get_accel_regs(reg_addr, &config_stream_status, BMI088_ONE, dev); + + if (config_stream_status != BMI088_ASIC_INITIALIZED) + { + rslt |= BMI088_E_CONFIG_STREAM_ERROR; + } + } + + return rslt; + +} + +/*! + * @brief This API reads the data from the given register address of accel sensor. + */ +uint16_t bmi088_get_accel_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, + struct bmi088_dev *dev) +{ + /* variable used to return the status of communication result*/ + uint16_t rslt = BMI088_OK; + uint16_t temp_len = len + dev->dummy_byte; + uint16_t i; + uint8_t temp_buff[temp_len]; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + /* Configuring reg_addr for SPI Interface */ + if (dev->interface == BMI088_SPI_INTF) + { + reg_addr = reg_addr | BMI088_SPI_RD_MASK; + } + /* Read the data from the register */ + rslt |= dev->read(dev->accel_id, reg_addr, temp_buff, temp_len); + + for (i = 0; i < len; i++) + { + data[i] = temp_buff[i + dev->dummy_byte]; + } + } + + return rslt; + +} + +/*! + * @brief This API writes the given data to the register address + * of accel sensor. + */ +uint16_t bmi088_set_accel_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, + struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if ((rslt == BMI088_OK) && (data != NULL) && (len != 0)) + { + /* Configuring reg_addr for SPI Interface */ + if (dev->interface == BMI088_SPI_INTF) + { + reg_addr = (reg_addr & BMI088_SPI_WR_MASK); + } + + /* write to an accel register */ + rslt = dev->write(dev->accel_id, reg_addr, data, len); + + if (rslt != BMI088_OK) + { + rslt = BMI088_E_COM_FAIL; + } + } + + return rslt; +} + +/*! + * @brief This API reads the error status from the accel sensor. + */ +uint16_t bmi088_get_accel_error_status(struct bmi088_err_reg *err_reg, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_ACCEL_ERR_REG; + /* Read the error codes */ + rslt = bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Fatal error */ + err_reg->fatal_err = BMI088_GET_BITSLICE(data, BMI088_FATAL_ERR); + /* Cmd error */ + err_reg->cmd_err = BMI088_GET_BITSLICE(data, BMI088_CMD_ERR); + /* User error */ + err_reg->err_code = BMI088_GET_BITSLICE(data, BMI088_ERR_CODE); + } + } + + return rslt; +} + +/*! + * @brief This API reads the status of the accel sensor. + */ +uint16_t bmi088_get_accel_status(uint8_t *status, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_ACCEL_STATUS_REG; + /* Read the status */ + rslt = bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + *status = data; + } + } + + return rslt; + +} + +/*! + * @brief This API resets the accel sensor. + */ +uint16_t bmi088_accel_soft_reset(struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, data; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_ACCEL_SOFTRESET_REG; + data = BMI088_SOFT_RESET_VAL; + /* Reset accel device */ + rslt = bmi088_set_accel_regs(reg_addr, &data, BMI088_ONE, dev); + if (rslt == BMI088_OK) + { + /* Delay 1 ms after reset value is written to its register */ + dev->delay_ms(BMI088_ACCEL_SOFTRESET_DELAY); + } + } + + return rslt; +} + +/*! + * @brief This API sets the output data rate, range and bandwidth + * of accel sensor. + */ +uint16_t bmi088_set_accel_meas_conf(struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, data; + uint8_t bw, range, odr; + bool is_odr_invalid = false, is_bw_invalid = false, is_range_invalid = false; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + odr = dev->accel_cfg.odr; + bw = dev->accel_cfg.bw; + range = dev->accel_cfg.range; + + /* Check if odr and bandwidth are not previously configured odr and bandwidth */ + if ((odr != accel_cfg_copy.odr) || (bw != accel_cfg_copy.bw)) + { + /* Check for valid odr */ + if ((odr < BMI088_ACCEL_ODR_12_5_HZ) || (odr > BMI088_ACCEL_ODR_1600_HZ)) + { + is_odr_invalid = true; + /* Since odr and bandwidth are written to the same + * register, use previous odr in case of invalid ODR. + * This will be helpful if valid bandwidth arrives */ + odr = accel_cfg_copy.odr; + } + + /* Check for valid bandwidth */ + if (bw > BMI088_ACCEL_BW_NORMAL) + { + is_bw_invalid = true; + /* Since bandwidth and odr are written to the same + * register, use previous bandwidth in case of + * invalid bandwidth.This will be helpful if valid + * odr arrives */ + bw = accel_cfg_copy.bw; + } + + /* If either odr or bw is valid, write it to accel config. registers */ + if ((!is_odr_invalid) || (!is_bw_invalid)) + { + reg_addr = BMI088_ACCEL_CONF_REG; + /* Read accel config. register */ + rslt = bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + if (rslt == BMI088_OK) + { + /* Update data with new odr and bw values */ + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_ODR, odr); + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_BW, bw); + /* write to accel config. register */ + rslt = bmi088_set_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + /* If rslt is ok, copy the current odr + * and bw to accel_cfg_copy structure to + * maintain a copy */ + if (rslt == BMI088_OK) + { + accel_cfg_copy.odr = odr; + accel_cfg_copy.bw = bw; + } + } + } + } + + /* Check if range is not previously configured range */ + if (range != accel_cfg_copy.range) + { + /* Check if range is valid */ + if (range <= BMI088_ACCEL_RANGE_24G) + { + reg_addr = BMI088_ACCEL_RANGE_REG; + /* Read range register */ + rslt = bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + if (rslt == BMI088_OK) + { + /* Update data with current range values */ + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_RANGE, range); + /* write to range register */ + rslt = bmi088_set_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + /* If rslt is ok, copy the current range + * to accel_cfg_copy structure to + * maintain a copy */ + if (rslt == BMI088_OK) + { + accel_cfg_copy.range = range; + } + } + } + else + { + /* Range is invalid */ + is_range_invalid = true; + } + } + } + + /* If invalid odr or bw or range arrive, make rslt invalid input */ + if (is_odr_invalid || is_bw_invalid || is_range_invalid) + { + rslt = BMI088_E_INVALID_INPUT; + } + + return rslt; +} + +/*! + * @brief This API sets the power mode of the accel sensor. + */ +uint16_t bmi088_set_accel_power_mode(struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, power; + uint8_t data[2]; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + power = dev->accel_cfg.power; + /* Check if current power is not previously configured power */ + if (power != accel_cfg_copy.power) + { + /* Configure data array to write to accel power configuration register */ + if (power == BMI088_ACCEL_PM_ACTIVE) + { + data[0] = BMI088_ACCEL_PM_ACTIVE; + data[1] = BMI088_ACCEL_POWER_ENABLE; + } + else if (power == BMI088_ACCEL_PM_SUSPEND) + { + data[0] = BMI088_ACCEL_PM_SUSPEND; + data[1] = BMI088_ACCEL_POWER_DISABLE; + } + else + { + /* Invalid power input */ + rslt = BMI088_E_INVALID_INPUT; + } + + if (rslt == BMI088_OK) + { + reg_addr = BMI088_ACCEL_PWR_CONF_REG; + /* write to accel power configuration register */ + rslt = bmi088_set_accel_regs(reg_addr, data, BMI088_TWO, dev); + + /* If rslt is ok, copy the current power + * to accel_cfg_copy structure to maintain + * a copy */ + if (rslt == BMI088_OK) + { + accel_cfg_copy.power = power; + } + } + + } + } + + return rslt; +} + +/*! + * @brief This API reads the accel data from the sensor, + * store it in the bmi088_sensor_data structure instance + * passed by the user. + */ +uint16_t bmi088_get_accel_data(struct bmi088_sensor_data *accel, + struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t index = 0, reg_addr, data[6]; + uint32_t lsb, msb, msblsb; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if ((rslt == BMI088_OK) && (accel != NULL)) + { + /* Read accel sensor data */ + reg_addr = BMI088_ACCEL_X_LSB_REG; + rslt = bmi088_get_accel_regs(reg_addr, data, BMI088_SIX, dev); + + if (rslt == BMI088_OK) + { + lsb = (uint32_t)data[index++]; + msb = (uint32_t)data[index++]; + msblsb = (msb << BMI088_EIGHT) | lsb; + accel->x = ((int16_t)msblsb); /* Data in X axis */ + + lsb = (uint32_t)data[index++]; + msb = (uint32_t)data[index++]; + msblsb = (msb << BMI088_EIGHT) | lsb; + accel->y = ((int16_t)msblsb); /* Data in Y axis */ + + lsb = (uint32_t)data[index++]; + msb = (uint32_t)data[index++]; + msblsb = (msb << BMI088_EIGHT) | lsb; + accel->z = ((int16_t)msblsb); /* Data in Z axis */ + } + } + + return rslt; +} + +/*! + * @brief This API configures the necessary accel interrupt + * based on the user settings in the bmi088_int_cfg + * structure instance. + */ +uint16_t bmi088_set_accel_int_config(const struct bmi088_int_cfg *int_config, struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + + switch (int_config->accel_int_type) + { + case BMI088_ACCEL_DATA_RDY_INT: + { + /* Data ready interrupt */ + rslt = set_accel_data_ready_int(int_config, dev); + } + break; + default: + break; + } + + return rslt; +} + +/*! + * @brief This API switches accel sensor on or off. + */ +uint16_t bmi088_accel_switch_control(struct bmi088_dev *dev, uint8_t switch_input) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, data = switch_input; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + /* Check if switch input is valid */ + if ((data == BMI088_ACCEL_POWER_DISABLE) || (data == BMI088_ACCEL_POWER_ENABLE)) + { + reg_addr = BMI088_ACCEL_PWR_CTRL_REG; + /* write to accel power control register */ + rslt = bmi088_set_accel_regs(reg_addr, &data, BMI088_ONE, dev); + } + else + { + rslt = BMI088_E_INVALID_INPUT; + } + } + + return rslt; +} + +/*! + * @brief This API reads the temperature of the sensor in � Celcius. + */ +uint16_t bmi088_get_sensor_temperature(struct bmi088_dev *dev, float *sensor_temp) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, data[2] = { 0 }; + uint16_t msb, lsb; + int16_t msblsb; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_TEMP_MSB_REG; + /* Read sensor temperature */ + rslt = bmi088_get_accel_regs(reg_addr, data, BMI088_TWO, dev); + + if (rslt == BMI088_OK) + { + msb = (data[0] << BMI088_THREE); /* MSB data */ + lsb = (data[1] >> BMI088_FIVE); /* LSB data */ + msblsb = (int16_t)(msb + lsb); + + if (msblsb > 1023) + { + msblsb = msblsb - 2048; + } + /* sensor temperature */ + *sensor_temp = (msblsb * 0.125) + 23; + } + } + + return rslt; + +} + +/*! + * @brief This API reads the sensor time of the sensor. + */ +uint16_t bmi088_get_sensor_time(struct bmi088_dev *dev, uint32_t *sensor_time) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, data[3] = { 0 }; + uint32_t byte2, byte1, byte0; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_ACCEL_SENSORTIME_0_REG; + /* Read 3-byte sensor time */ + rslt = bmi088_get_accel_regs(reg_addr, data, BMI088_THREE, dev); + if (rslt == BMI088_OK) + { + byte0 = data[0]; /* Lower byte */ + byte1 = (data[1] << BMI088_EIGHT); /* Middle byte */ + byte2 = (data[2] << BMI088_SIXTEEN); /* Higher byte */ + + /* Sensor time */ + *sensor_time = (byte2 | byte1 | byte0); + } + } + + return rslt; +} + +/*! + * @brief This API checks whether the self test functionality of the sensor + * is working or not. + */ +uint16_t bmi088_perform_accel_selftest(int8_t *result, struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + struct bmi088_sensor_data positive = { 0 }; + struct bmi088_sensor_data negative = { 0 }; + /*! Structure for difference of accel values in g*/ + struct bmi088_sensor_data accel_data_diff = { 0 }; + /*! Structure for difference of accel values in mg*/ + struct bmi088_sensor_data accel_data_diff_mg = { 0 }; + + *result = BMI088_SELFTEST_FAIL; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + rslt |= set_accel_selftest_config(dev); + dev->delay_ms(20); + rslt |= bmi088_set_accel_selftest(BMI088_ACCEL_POSITIVE_SELF_TEST, dev); + + if (rslt == BMI088_OK) + { + dev->delay_ms(BMI088_HUNDRED); + rslt |= bmi088_get_accel_data(&positive, dev); + rslt |= bmi088_set_accel_selftest(BMI088_ACCEL_NEGATIVE_SELF_TEST, dev); + + if (rslt == BMI088_OK) + { + dev->delay_ms(100); + rslt |= bmi088_get_accel_data(&negative, dev); + rslt |= bmi088_set_accel_selftest(BMI088_ACCEL_SWITCH_OFF_SELF_TEST, dev); + + accel_data_diff.x = ABS(positive.x) + ABS(negative.x); + accel_data_diff.y = ABS(positive.y) + ABS(negative.y); + accel_data_diff.z = ABS(positive.z) + ABS(negative.z); + + /*! Converting LSB of the differences of + accel values to mg */ + convert_lsb_g(&accel_data_diff, &accel_data_diff_mg); + /*! Validating self test for + accel values in mg */ + rslt |= validate_selftest(&accel_data_diff_mg); + + if (rslt == BMI088_OK) + { + *result = BMI088_SELFTEST_PASS; + dev->delay_ms(BMI088_HUNDRED); + } + + /* Triggers a soft reset */ + rslt |= bmi088_accel_soft_reset(dev); + } + } + } + + return rslt; +} + +/*! + * @brief This API enables or disables the Accel Self test feature in the + * sensor. + */ +uint16_t bmi088_set_accel_selftest(uint8_t selftest, struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, data = 0; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_ACCEL_SELF_TEST_REG; + data = selftest; + /* Write to accel selftest register */ + rslt = bmi088_set_accel_regs(reg_addr, &data, BMI088_ONE, dev); + } + + return rslt; +} + +/*****************************************************************************/ +/* Static function definition */ +/*! + * @brief This API is used to validate the device structure pointer for + * null conditions. + */ +static uint16_t null_ptr_check(struct bmi088_dev *dev) +{ + uint16_t rslt; + + if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL)) + { + /* Device structure pointer is not valid */ + rslt = BMI088_E_NULL_PTR; + } + else + { + /* Device structure is fine */ + rslt = BMI088_OK; + } + + return rslt; +} + +/*! + * @brief This API configures the pins which fire the + * interrupt signal when any interrupt occurs. + */ +static uint16_t set_int_pin_config(const struct bmi088_int_cfg *int_config, struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, data; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if ((rslt == BMI088_OK) && (int_config != NULL)) + { + /* update reg_addr based on channel inputs */ + if (int_config->accel_int_channel == BMI088_INT_CHANNEL_1) + { + reg_addr = BMI088_ACCEL_INT1_IO_CONF_REG; + } + + if (int_config->accel_int_channel == BMI088_INT_CHANNEL_2) + { + reg_addr = BMI088_ACCEL_INT2_IO_CONF_REG; + } + + /* Read interrupt pin configuration register */ + rslt = bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Update data with user configured bmi088_int_cfg structure */ + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT2_LVL, int_config->accel_int_pin_cfg.lvl); + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT2_OD, int_config->accel_int_pin_cfg.output_mode); + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT2_IO, int_config->accel_int_pin_cfg.enable_int_pin); + + /* Write to interrupt pin configuration register */ + rslt = bmi088_set_accel_regs(reg_addr, &data, BMI088_ONE, dev); + } + } + + return rslt; + +} + +/*! + * @brief This API sets the data ready interrupt for accel sensor. + */ +static uint16_t set_accel_data_ready_int(const struct bmi088_int_cfg *int_config, struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, data; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if ((rslt == BMI088_OK) && (int_config != NULL)) + { + reg_addr = BMI088_ACCEL_INT1_INT2_MAP_DATA_REG; + /* Read interrupt map register */ + rslt = bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Update data to map data ready interrupt to appropriate interrupt pins */ + if (int_config->accel_int_channel == BMI088_INT_CHANNEL_1) + { + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT1_DRDY, BMI088_ENABLE); + } + + if (int_config->accel_int_channel == BMI088_INT_CHANNEL_2) + { + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT2_DRDY, BMI088_ENABLE); + } + + /* Write to interrupt map register */ + rslt = bmi088_set_accel_regs(reg_addr, &data, BMI088_ONE, dev); + /* Configure interrupt pins */ + rslt |= set_int_pin_config(int_config, dev); + } + } + + return rslt; + +} + +/*! + * @brief This API writes the config stream data in memory using burst mode. + */ +static uint16_t stream_transfer_write(const uint8_t *stream_data, uint16_t index, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t asic_msb = (uint8_t)((index / 2) >> 4); + uint8_t asic_lsb = ((index / 2) & 0x0F); + uint8_t reg_addr; + + /* Write to feature config register */ + reg_addr = BMI088_ACCEL_RESERVED_5B_REG; + rslt |= bmi088_set_accel_regs(reg_addr, &asic_lsb, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Write to feature config register */ + reg_addr = BMI088_ACCEL_RESERVED_5C_REG; + rslt |= bmi088_set_accel_regs(reg_addr, &asic_msb, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Write to feature config registers */ + reg_addr = BMI088_ACCEL_FEATURE_CFG_REG; + rslt |= bmi088_set_accel_regs(reg_addr, (uint8_t *)stream_data, dev->read_write_len, dev); + } + } + + return rslt; + +} + +/*! + * @brief This function enables and configures the Accel which is needed + * for Self test operation. + */ +static uint16_t set_accel_selftest_config(struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + + /* Configuring sensors to perform accel self test */ + dev->accel_cfg.odr = BMI088_ACCEL_ODR_1600_HZ; + dev->accel_cfg.bw = BMI088_ACCEL_BW_NORMAL; + dev->accel_cfg.range = BMI088_ACCEL_RANGE_24G; + + /* Enable Accel sensor */ + rslt = bmi088_accel_switch_control(dev, BMI088_ACCEL_POWER_ENABLE); + /* Configure sensors with above configured settings */ + rslt |= bmi088_set_accel_meas_conf(dev); + + return rslt; +} + +/*! + * @brief This function validates the Accel Self test data and decides the + * result of Self test operation. + */ +static uint16_t validate_selftest(const struct bmi088_sensor_data *accel_data_diff) +{ + uint16_t rslt; + + /* Validating accel data by comparing with minimum value of the axes in mg */ + /* x axis limit 1000mg, y axis limit 1000mg and z axis limit 500mg */ + if (accel_data_diff->x >= 1000 && accel_data_diff->y >= 1000 && accel_data_diff->z >= 500) + { + rslt = BMI088_OK; + } + else + { + rslt = BMI088_E_SELF_TEST_FAIL; + } + + return rslt; +} + +/*! + * @brief This API converts lsb value of axes to mg for self-test. + */ +static void convert_lsb_g(const struct bmi088_sensor_data *accel_data_diff, + struct bmi088_sensor_data *accel_data_diff_mg) +{ + uint32_t lsb_per_g; + /* Range considered for self-test is 24g */ + uint8_t range = 16; + + /* lsb_per_g for the 16-bit resolution and 24g range*/ + lsb_per_g = (uint32_t)(power(2, BMI088_16_BIT_RESOLUTION) / (2 * range)); + /* accel x value in mg */ + accel_data_diff_mg->x = (accel_data_diff->x / (int32_t)lsb_per_g) * 1000; + /* accel y value in mg */ + accel_data_diff_mg->y = (accel_data_diff->y / (int32_t)lsb_per_g) * 1000; + /* accel z value in mg */ + accel_data_diff_mg->z = (accel_data_diff->z / (int32_t)lsb_per_g) * 1000; +} + +/*! + * @brief This API is used to calculate the power of given + * base value. + */ +static int32_t power(int16_t base, uint8_t resolution) +{ + uint8_t i = 1; + /* Initialize variable to store the power of 2 value */ + int32_t value = 1; + + for (; i <= resolution; i++) + { + value = (int32_t)(value * base); + } + + return value; +} + +/** @}*/ + diff --git a/src/drivers/bosch/src/bmi088_fifo.c b/src/drivers/bosch/src/bmi088_fifo.c new file mode 100644 index 0000000000..940d84d791 --- /dev/null +++ b/src/drivers/bosch/src/bmi088_fifo.c @@ -0,0 +1,1804 @@ +/* + **************************************************************************** + * Copyright (C) 2015 - 2016 Bosch Sensortec GmbH + * + * File :bmi088_fifo.c + * + * Date: 30 Oct 2017 + * + * Revision: + * + * Usage: Sensor Driver for BMI088 family of sensors + * + **************************************************************************** + * Disclaimer + * + * Common: + * Bosch Sensortec products are developed for the consumer goods industry. + * They may only be used within the parameters of the respective valid + * product data sheet. Bosch Sensortec products are provided with the + * express understanding that there is no warranty of fitness for a + * particular purpose.They are not fit for use in life-sustaining, + * safety or security sensitive systems or any system or device + * that may lead to bodily harm or property damage if the system + * or device malfunctions. In addition,Bosch Sensortec products are + * not fit for use in products which interact with motor vehicle systems. + * The resale and or use of products are at the purchasers own risk and + * his own responsibility. The examination of fitness for the intended use + * is the sole responsibility of the Purchaser. + * + * The purchaser shall indemnify Bosch Sensortec from all third party + * claims, including any claims for incidental, or consequential damages, + * arising from any product use not covered by the parameters of + * the respective valid product data sheet or not approved by + * Bosch Sensortec and reimburse Bosch Sensortec for all costs in + * connection with such claims. + * + * The purchaser must monitor the market for the purchased products, + * particularly with regard to product safety and inform Bosch Sensortec + * without delay of all security relevant incidents. + * + * Engineering Samples are marked with an asterisk (*) or (e). + * Samples may vary from the valid technical specifications of the product + * series. They are therefore not intended or fit for resale to third + * parties or for use in end products. Their sole purpose is internal + * client testing. The testing of an engineering sample may in no way + * replace the testing of a product series. Bosch Sensortec assumes + * no liability for the use of engineering samples. + * By accepting the engineering samples, the Purchaser agrees to indemnify + * Bosch Sensortec from all claims arising from the use of engineering + * samples. + * + * Special: + * This software module (hereinafter called "Software") and any information + * on application-sheets (hereinafter called "Information") is provided + * free of charge for the sole purpose to support your application work. + * The Software and Information is subject to the following + * terms and conditions: + * + * The Software is specifically designed for the exclusive use for + * Bosch Sensortec products by personnel who have special experience + * and training. Do not use this Software if you do not have the + * proper experience or training. + * + * This Software package is provided `` as is `` and without any expressed + * or implied warranties,including without limitation, the implied warranties + * of merchantability and fitness for a particular purpose. + * + * Bosch Sensortec and their representatives and agents deny any liability + * for the functional impairment + * of this Software in terms of fitness, performance and safety. + * Bosch Sensortec and their representatives and agents shall not be liable + * for any direct or indirect damages or injury, except as + * otherwise stipulated in mandatory applicable law. + * + * The Information provided is believed to be accurate and reliable. + * Bosch Sensortec assumes no responsibility for the consequences of use + * of such Information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of Bosch. Specifications mentioned in the Information are + * subject to change without notice. + **************************************************************************/ +/*! \file bmi088_fifo.c + \brief Sensor Driver for BMI088 family of sensors */ +/***************************************************************************/ +/**\name Header files + ****************************************************************************/ +#ifdef USE_FIFO +#include "bmi088_fifo.h" + +/***************************************************************************/ +/**\name Local structures + ****************************************************************************/ + +/***************************************************************************/ +/*! Static Function Declarations + ****************************************************************************/ + +/*! + * @brief This API is used to validate the device structure pointer for + * null conditions. + * + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + * + */ +static uint16_t null_ptr_check(const struct bmi088_dev *dev); + +/*! + * @brief This API is used to reset the accel FIFO related configurations + * in the fifo_frame structure. + * + * @param dev[in,out] : Structure instance of bmi088_dev + * + * @return None + */ +static void reset_accel_fifo_data_structure(const struct bmi088_dev *dev); + +/*! + * @brief This API computes the number of bytes of accel FIFO data + * which is to be parsed in header-less mode + * + * @param[out] start_idx : The start index for parsing data + * @param[out] len : Number of bytes to be parsed + * @param[in] accel_count : Number of accelerometer frames to be read + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return None + */ +static void get_accel_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *accel_count, const struct bmi088_dev *dev); + +/*! + * @brief This API checks the accel fifo read data as empty frame, if it + * is empty frame then moves the index to last byte. + * + * @param[in,out] data_index : The index of the current data to + * be parsed from accelerometer fifo data + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return None + */ +static void check_empty_accel_fifo(uint16_t *data_index, const struct bmi088_dev *dev); + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data in header mode. + * + * @param[in,out] accel_data : Structure instance of bmi088_sensor_data where + * the accelerometer data in FIFO is stored. + * @param[in,out] accel_length : Number of accelerometer frames + * (x,y,z axes data) + * @param[in,out] dev : Structure instance of bmi088_dev. + * + * @return None + */ +static void extract_accel_header_mode(struct bmi088_sensor_data *accel_data, uint16_t *accel_length, const struct bmi088_dev *dev); + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data in both header mode and header-less mode. + * It updates the idx value which is used to store the index of + * the current data byte which is parsed. + * + * @param[in,out] accel : Structure instance of bmi088_sensor_data. + * @param[in,out] idx : Index value of number of bytes parsed + * @param[in,out] accel_idx : Index value of accelerometer data + * (x,y,z axes) frame to be parsed + * @param[in] frm : It consists of either fifo_data_enable + * parameter (Accel enabled in FIFO) + * in header-less mode or frame header data + * in header mode + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return None + */ +static void unpack_accel_frm(struct bmi088_sensor_data *accel, uint16_t *idx, uint16_t *accel_idx, uint8_t frm, const struct bmi088_dev *dev); + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data and store it in the instance of the structure bmi088_sensor_data. + * + * @param[out] accel_data : Structure instance of bmi088_sensor_data where + * the parsed accel data bytes are stored. + * @param[in] data_start_index : Index value of the accel data bytes + * which is to be parsed from the fifo data. + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return None + * + */ +static void unpack_accel_data(struct bmi088_sensor_data *accel_data, uint16_t data_start_index, const struct bmi088_dev *dev); + +/*! + * @brief This API is used to parse and store the sensor time from the + * FIFO data in the structure instance dev. + * + * @param[in,out] data_index : Index of the FIFO data which + * has the sensor time. + * @param[in,out] dev : Structure instance of bmi088_dev. + * + * @return None + */ +static void unpack_sensortime_frame(uint16_t *data_index, const struct bmi088_dev *dev); + +/*! + * @brief This API is used to parse and store the skipped_frame_count from + * the accelerometer FIFO data in the structure instance dev. + * + * @param[in,out] data_index : Index of the FIFO data which + * has the skipped frame count. + * @param[in,out] dev : Structure instance of bmi088_dev. + * + * @return None + */ +static void unpack_accel_skipped_frame(uint16_t *data_index, const struct bmi088_dev *dev); + +/*! + * @brief This API is used to parse and store the dropped_frame_count from + * the accelerometer FIFO data in the structure instance dev. + * + * @param[in,out] data_index : Index of the FIFO data which + * has the dropped frame data. + * @param[in,out] dev : Structure instance of bmi088_dev. + * + * @return None + */ +static void unpack_accel_dropped_frame(uint16_t *data_index, const struct bmi088_dev *dev); + +/*! + * @brief This API is used to move the data index ahead of the + * current_frame_length parameter when unnecessary FIFO data appears while + * extracting the accelerometer data. + * + * @param[in,out] data_index : Index of the FIFO data which + * is to be moved ahead of the + * current_frame_length + * @param[in] current_frame_length : Number of bytes in a particular frame + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return None + */ +static void move_to_next_accel_frame(uint16_t *data_index, uint8_t current_frame_length, const struct bmi088_dev *dev); + +/*! + * @brief This API is used to reset the gyro FIFO related configurations + * in the fifo_frame structure. + * + * @param dev[in,out] : Structure instance of bmi088_dev + * + * @return None + */ +static void reset_gyro_fifo_data_structure(const struct bmi088_dev *dev); + +/*! + * @brief This API computes the number of bytes of Gyro FIFO data which is + * to be parsed in header-less mode + * + * @param[out] start_idx : The start index for parsing data + * @param[out] len : Number of bytes to be parsed + * @param[in] gyro_count : Number of gyroscope frames to be read + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return None + */ +static void get_gyro_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *gyro_count, const struct bmi088_dev *dev); + +/*! + * @brief This API is used to parse the gyroscope data from the + * FIFO data in header-less mode and update the idx value + * which is used to store the index of the current data byte + * which is parsed. + * + * @param[in,out] data : Structure instance of bmi088_sensor_data. + * @param[in,out] idx : Index value of number of bytes parsed + * @param[in,out] gyro_idx : Index value gyroscope data frame (x,y,z,r) + * to be parsed + * @param[in] frm : It consists of either the fifo_data_enable parameter + * (Gyro data enabled in FIFO) in header-less mode + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +static uint16_t unpack_gyro_frm(struct bmi088_sensor_data *data, uint16_t *idx, uint16_t *gyro_idx, uint8_t frm, const struct bmi088_dev *dev); + +/*! + * @brief This API is used to parse the gyroscope data from + * the FIFO data and store it in the instance of the structure + * gyro_data. + * + * @param[out] gyro_data : Structure instance of bmi088_sensor_data where the + * parsed gyroscope data bytes are stored. + * @param[in] start_idx : Index value of the gyroscope data bytes + * which is to be parsed from the FIFO data + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return None + */ +static void unpack_gyro_data(struct bmi088_sensor_data *gyro_data, uint16_t start_idx, const struct bmi088_dev *dev); + +/*! + * @brief This API checks the gyro fifo read data as empty frame, if it + * is empty frame then moves the index to last byte. + * + * @param[in,out] data_index : The index of the current data to + * be parsed from gyroscope fifo data + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return None + */ +static void check_empty_gyro_fifo(uint16_t *data_index, const struct bmi088_dev *dev); + +/***************************************************************************/ +/**\name Extern Declarations + ****************************************************************************/ + +/***************************************************************************/ +/**\name Globals + ****************************************************************************/ + +/***************************************************************************/ +/**\name Function definitions + ****************************************************************************/ + +/*! + * @brief This API reads the FIFO data of Accel sensor. + */ +uint16_t bmi088_get_accel_fifo_data(struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0; + uint8_t reg_addr = BMI088_ACCEL_FIFO_DATA_REG; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + /* Reset the Accel FIFO related configurations */ + reset_accel_fifo_data_structure(dev); + + if (dev->interface == BMI088_SPI_INTF) + { + reg_addr = reg_addr | BMI088_SPI_RD_MASK; + } + + /* Read Accel FIFO data*/ + rslt |= dev->read(dev->accel_id, reg_addr, dev->accel_fifo->data, dev->accel_fifo->length); + reg_addr = BMI088_ACCEL_FIFO_CONFIG_1_REG; + /* Read fifo frame content configuration*/ + rslt |= bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + /* Filter fifo header enabled status */ + dev->accel_fifo->fifo_header_enable = data & BMI088_FIFO_HEADER; + /* Filter accel data enabled status */ + dev->accel_fifo->fifo_data_enable = data & BMI088_FIFO_A_ENABLE; + } + + return rslt; +} + +/*! + * @brief This API parses and extracts the accelerometer frames from + * FIFO data read by the "bmi088_get_accel_fifo_data" API and stores + * it in the "accel_data" structure instance. + */ +uint16_t bmi088_extract_accel(struct bmi088_sensor_data *accel_data, uint16_t *accel_length, const struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint16_t data_index = 0; + uint16_t accel_index = 0; + uint16_t data_read_length = 0; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + /* Parsing the Accel FIFO data in header-less mode */ + if (dev->accel_fifo->fifo_header_enable == 0) + { + /* Collects the number of bytes of Accel FIFO data + * which is to be parsed in header-less mode */ + get_accel_len_to_parse(&data_index, &data_read_length, accel_length, dev); + + for (; data_index < data_read_length;) + { + /* Unpack Accel data from fifo buffer */ + unpack_accel_frm(accel_data, &data_index, &accel_index, dev->accel_fifo->fifo_data_enable, dev); + /*Check for the availability of next + two bytes of accel FIFO data */ + check_empty_accel_fifo(&data_index, dev); + } + /* update number of Accel data read*/ + *accel_length = accel_index; + /*update the Accel byte index*/ + dev->accel_fifo->byte_start_idx = data_index; + } + else + { + /* Parsing the accel FIFO data in header mode */ + extract_accel_header_mode(accel_data, accel_length, dev); + } + } + + return rslt; +} + +/*! + * @brief This API reads the accel FIFO water mark level which is set + * in the sensor. + */ +uint16_t bmi088_get_accel_fifo_wm(uint16_t *fifo_wm, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data[2] = { 0, 0 }; + uint8_t reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_ACCEL_FIFO_WTM_0_REG; + /* Read the Accel FIFO watermark level*/ + rslt |= bmi088_get_accel_regs(reg_addr, data, BMI088_TWO, dev); + + if (rslt == BMI088_OK) + { + /* Update the fifo watermark level */ + *fifo_wm = (data[1] << BMI088_EIGHT) | (data[0]); + } + } + + return rslt; +} + +/*! + * @brief This API sets the accel FIFO watermark level in the sensor. + */ +uint16_t bmi088_set_accel_fifo_wm(uint16_t fifo_wm, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data[2] = { 0, 0 }; + uint8_t reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + data[0] = BMI088_GET_LSB(fifo_wm); + data[1] = BMI088_GET_MSB(fifo_wm); + + /* consecutive write is not possible in suspend mode hence + separate write is used with delay of 1 ms*/ + /* Write the Accel fifo watermark level*/ + reg_addr = BMI088_ACCEL_FIFO_WTM_0_REG; + rslt |= bmi088_set_accel_regs(reg_addr, &data[0], BMI088_ONE, dev); + dev->delay_ms(BMI088_ONE); + /* Write the Accel fifo watermark level */ + rslt |= bmi088_set_accel_regs((reg_addr + BMI088_ONE), &data[1], BMI088_ONE, dev); + } + + return rslt; +} + +/*! + * @brief This API checks whether the Accel FIFO data is set for filtered + * or unfiltered mode. + */ +uint16_t bmi088_get_accel_fifo_filt_data(uint8_t *accel_fifo_filter, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_ACCEL_FIFO_DOWN_REG; + /* Read the Accel FIFO filter data */ + rslt |= bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Update the accel fifo filter info */ + *accel_fifo_filter = BMI088_GET_BITSLICE(data, BMI088_ACCEL_FIFO_FILT_DATA); + } + } + + return rslt; +} + +/*! + * @brief This API sets the condition of Accel FIFO data either to + * filtered or unfiltered mode. + */ +uint16_t bmi088_set_accel_fifo_filt_data(uint8_t accel_fifo_filter, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + if (accel_fifo_filter <= BMI088_MAX_VALUE_FIFO_FILTER) + { + /* Read accel fifo down register */ + reg_addr = BMI088_ACCEL_FIFO_DOWN_REG; + rslt |= bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Write Accel FIFO filter data */ + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_FIFO_FILT_DATA, accel_fifo_filter); + rslt |= bmi088_set_accel_regs(reg_addr, &data, BMI088_ONE, dev); + } + } + else + { + rslt |= BMI088_E_OUT_OF_RANGE; + } + } + return rslt; +} + +/*! + * @brief This API reads the down sampling rates which is configured + * for Accel FIFO data. + */ +uint16_t bmi088_get_fifo_down_accel(uint8_t *fifo_down, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_ACCEL_FIFO_DOWN_REG; + /* Read the Accel FIFO down data */ + rslt |= bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Update the fifo down value */ + *fifo_down = BMI088_GET_BITSLICE(data, BMI088_ACCEL_FIFO_FILT_DOWN); + } + } + + return rslt; +} + +/*! + * @brief This API sets the down-sampling rates for Accel FIFO. + */ +uint16_t bmi088_set_fifo_down_accel(uint8_t fifo_down, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + if (fifo_down <= BMI088_MAX_VALUE_FIFO_DOWN) + { + reg_addr = BMI088_ACCEL_FIFO_DOWN_REG; + /* Read the Accel FIFO down register */ + rslt |= bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_FIFO_FILT_DOWN, fifo_down); + /* Write the Accel FIFO down data */ + rslt |= bmi088_set_accel_regs(reg_addr, &data, BMI088_ONE, dev); + } + } + else + { + rslt |= BMI088_E_OUT_OF_RANGE; + } + } + return rslt; +} + +/*! + * @brief This API reads the length of FIFO data available in the + * Accel sensor in the units of bytes. + */ +uint16_t bmi088_get_accel_fifo_length(uint16_t *fifo_length, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t index = 0, reg_addr; + uint8_t data[2] = { 0, 0 }; + + /* Check for null pointer in the device structure */ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_ACCEL_FIFO_LENGTH_0_REG; + /* Read Accel FIFO length */ + rslt |= bmi088_get_accel_regs(reg_addr, data, BMI088_TWO, dev); + + if (rslt == BMI088_OK) + { + /* Update fifo length */ + index = BMI088_ONE; + data[index] = BMI088_GET_BITSLICE(data[index], BMI088_FIFO_BYTE_COUNTER_MSB); + *fifo_length = ((data[index] << BMI088_EIGHT) | data[index - BMI088_ONE]); + } + } + + return rslt; +} + +/*! + * @brief This API sets the FIFO full interrupt of the accel sensor. + */ +uint16_t bmi088_set_accel_fifo_full_int(struct bmi088_int_cfg *int_config, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + /* update reg_addr based on channel inputs */ + if (int_config->accel_int_channel == BMI088_INT_CHANNEL_1) + { + reg_addr = BMI088_ACCEL_INT1_IO_CONF_REG; + } + + if (int_config->accel_int_channel == BMI088_INT_CHANNEL_2) + { + reg_addr = BMI088_ACCEL_INT2_IO_CONF_REG; + } + + /* Read interrupt pin configuration register */ + rslt = bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Update data with user configured bmi088_int_cfg structure */ + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT2_LVL, int_config->accel_int_pin_cfg.lvl); + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT2_OD, int_config->accel_int_pin_cfg.output_mode); + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT2_IO, int_config->accel_int_pin_cfg.enable_int_pin); + + /* Write to interrupt pin configuration register */ + rslt = bmi088_set_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + reg_addr = BMI088_ACCEL_INT1_INT2_MAP_DATA_REG; + /* Read the Accel Interrupt Map Register */ + rslt = bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Update data to map fifo full interrupt based on channel inputs */ + if (int_config->accel_int_channel == BMI088_INT_CHANNEL_1) + { + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT1_FIFO_FULL, BMI088_ONE); + } + else if (int_config->accel_int_channel == BMI088_INT_CHANNEL_2) + { + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT2_FIFO_FULL, BMI088_ONE); + } + else + { + /* do nothing */ + } + + /* Write the Accel Interrupt Map Register */ + rslt = bmi088_set_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + } + } + } + } + + return rslt; + +} + +/*! + * @brief This API sets the FIFO watermark interrupt of the accel sensor. + */ +uint16_t bmi088_set_accel_fifo_wm_int(struct bmi088_int_cfg *int_config, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + /* update reg_addr based on channel inputs */ + if (int_config->accel_int_channel == BMI088_INT_CHANNEL_1) + { + reg_addr = BMI088_ACCEL_INT1_IO_CONF_REG; + } + + if (int_config->accel_int_channel == BMI088_INT_CHANNEL_2) + { + reg_addr = BMI088_ACCEL_INT2_IO_CONF_REG; + } + + /* Read interrupt pin configuration register */ + rslt = bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Update data with user configured bmi088_int_cfg structure */ + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT2_LVL, int_config->accel_int_pin_cfg.lvl); + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT2_OD, int_config->accel_int_pin_cfg.output_mode); + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT2_IO, int_config->accel_int_pin_cfg.enable_int_pin); + + /* Write to interrupt pin configuration register */ + rslt = bmi088_set_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + reg_addr = BMI088_ACCEL_INT1_INT2_MAP_DATA_REG; + /* Read the Accel Interrupt Map Register */ + rslt = bmi088_get_accel_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Update data to map watermark interrupt based on channel inputs */ + if (int_config->accel_int_channel == BMI088_INT_CHANNEL_1) + { + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT1_FIFO_WM, BMI088_ONE); + } + else if (int_config->accel_int_channel == BMI088_INT_CHANNEL_2) + { + data = BMI088_SET_BITSLICE(data, BMI088_ACCEL_INT2_FIFO_WM, BMI088_ONE); + } + else + { + /* do nothing */ + } + + /* Write to the Accel Interrupt Map Register */ + rslt = bmi088_set_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + } + } + } + } + + return rslt; + +} + +/*! + * @brief This API reads the FIFO data of Gyro sensor. + */ +uint16_t bmi088_get_gyro_fifo_data(struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t reg_addr = BMI088_GYRO_FIFO_DATA_REG; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + /* Reset the gyro FIFO related configurations */ + reset_gyro_fifo_data_structure(dev); + + /* Read FIFO data*/ + if (dev->interface == BMI088_SPI_INTF) + { + reg_addr = reg_addr | BMI088_SPI_RD_MASK; + } + + rslt |= dev->read(dev->gyro_id, reg_addr, dev->gyro_fifo->data, dev->gyro_fifo->length); + + /* Update the data select axes info in fifo_data_enable variable found in device structure */ + rslt |= bmi088_get_gyro_fifo_data_sel(&dev->gyro_fifo->fifo_data_enable, dev); + + } + + return rslt; +} + +/*! + * @brief This API parses and extracts the gyroscope frames from + * FIFO data read by the "bmi088_get_gyro_fifo_data" API and + * stores it in the "gyro_data" structure instance parameter of + * this API. + */ +uint16_t bmi088_extract_gyro(struct bmi088_sensor_data *gyro_data, uint16_t *gyro_length, const struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint16_t data_index = 0; + uint16_t gyro_index = 0; + uint16_t data_read_length = 0; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + /* Collects the number of bytes of Gyro FIFO data + * which is to be parsed */ + get_gyro_len_to_parse(&data_index, &data_read_length, gyro_length, dev); + + for (; data_index < data_read_length;) + { + /* Unpack Gyro data from fifo buffer */ + rslt |= unpack_gyro_frm(gyro_data, &data_index, &gyro_index, dev->gyro_fifo->fifo_data_enable, dev); + /* Check for the availability of next + two bytes of FIFO data */ + check_empty_gyro_fifo(&data_index, dev); + } + + /* Update number of gyro data read*/ + *gyro_length = gyro_index; + /* Update the Gyro byte index*/ + dev->gyro_fifo->byte_start_idx = data_index; + } + + return rslt; + +} + +/*! + * @brief This API reads the Gyro FIFO water mark level which is set + * in the sensor. + */ +uint16_t bmi088_get_gyro_fifo_wm(uint8_t *fifo_wm, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_GYRO_FIFO_CONFIG_0_REG; + /* Read the Gyro FIFO water mark level*/ + rslt = bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Update the fifo watermark level */ + *fifo_wm = BMI088_GET_BITSLICE(data, BMI088_GYRO_FIFO_WM); + } + } + + return rslt; +} + +/*! + * @brief This API sets the gyro FIFO watermark level in the sensor. + */ +uint16_t bmi088_set_gyro_fifo_wm(uint8_t fifo_wm, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + if (fifo_wm <= BMI088_GYRO_FIFO_WM_MAX) + { + /* Read the fifo config 0 register */ + reg_addr = BMI088_GYRO_FIFO_CONFIG_0_REG; + rslt |= bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + /* Write the fifo watermark level*/ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_FIFO_WM, fifo_wm); + rslt |= bmi088_set_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + } + else + { + rslt = BMI088_E_OUT_OF_RANGE; + } + } + + return rslt; +} + +/*! + * @brief This API gets the FIFO operating mode in the gyro sensor. + */ +uint16_t bmi088_get_gyro_fifo_mode(uint8_t *fifo_mode, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_GYRO_FIFO_CONFIG_1_REG; + /* Read the Gyro fifo config 1 register */ + rslt = bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Update the fifo mode */ + *fifo_mode = BMI088_GET_BITSLICE(data, BMI088_GYRO_FIFO_MODE); + } + } + + return rslt; + +} + +/*! + * @brief This API sets the FIFO operating mode in the gyro sensor. + */ +uint16_t bmi088_set_gyro_fifo_mode(uint8_t fifo_mode, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + if (fifo_mode <= BMI088_GYRO_STREAM_OP_MODE) + { + /* Read the fifo config 1 register */ + reg_addr = BMI088_GYRO_FIFO_CONFIG_1_REG; + rslt |= bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + /* Write the fifo operating mode */ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_FIFO_MODE, fifo_mode); + rslt |= bmi088_set_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + } + else + { + rslt = BMI088_E_OUT_OF_RANGE; + } + } + + return rslt; + +} + +/*! + * @brief This API gets the data of axes to be stored in the FIFO in the gyro sensor. + */ +uint16_t bmi088_get_gyro_fifo_data_sel(uint8_t *fifo_data_select, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_GYRO_FIFO_CONFIG_1_REG; + /* Read the Gyro Fifo config 1 register */ + rslt = bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Update the fifo data select */ + *fifo_data_select = BMI088_GET_BITSLICE(data, BMI088_GYRO_FIFO_DATA_SELECT); + } + } + + return rslt; + +} + +/*! + * @brief This API sets the data of axes to be stored in the FIFO in the gyro sensor. + */ +uint16_t bmi088_set_gyro_fifo_data_sel(uint8_t fifo_data_select, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + if (fifo_data_select <= BMI088_GYRO_Z_DATA) + { + /* Read the fifo config 1 register */ + reg_addr = BMI088_GYRO_FIFO_CONFIG_1_REG; + rslt |= bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + /* Write the fifo operating mode */ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_FIFO_DATA_SELECT, fifo_data_select); + rslt |= bmi088_set_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + } + else + { + rslt = BMI088_E_OUT_OF_RANGE; + } + } + + return rslt; + +} + +/*! + * @brief This API reads the length of FIFO data available in the + * Gyro sensor in the units of bytes. + */ +uint16_t bmi088_get_gyro_fifo_length(uint8_t *fifo_length, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_GYRO_FIFO_STAT_REG; + /* Read Gyro FIFO length*/ + rslt |= bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Update the fifo length */ + *fifo_length = BMI088_GET_BITSLICE(data, BMI088_GYRO_FIFO_COUNTER); + } + } + + return rslt; +} + +/*! + * @brief This API gets the gyro FIFO overrun status. + */ +uint16_t bmi088_get_gyro_fifo_overrun(uint8_t *fifo_overrun_status, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_GYRO_FIFO_STAT_REG; + /* Read Gyro fifo Overrun status */ + rslt |= bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Update the fifo overrun status */ + *fifo_overrun_status = BMI088_GET_BITSLICE(data, BMI088_GYRO_FIFO_OVERRUN); + } + } + + return rslt; + +} + +/*! + * @brief This API gets the fifo tag status which is set in gyro sensor. + */ +uint16_t bmi088_get_gyro_fifo_tag(uint8_t *fifo_tag_status, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data = 0, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + /* Read the fifo config 0 register */ + reg_addr = BMI088_GYRO_FIFO_CONFIG_0_REG; + rslt = bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Update the fifo tag status */ + *fifo_tag_status = BMI088_GET_BITSLICE(data, BMI088_GYRO_FIFO_TAG); + } + } + + return rslt; + +} + +/*! + * @brief This API enables or disable fifo tag in gyro sensor. + */ +uint16_t bmi088_set_gyro_fifo_tag(uint8_t fifo_tag, struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t data, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + if (fifo_tag <= BMI088_ENABLE) + { + /* Read the fifo config 0 register */ + reg_addr = BMI088_GYRO_FIFO_CONFIG_0_REG; + rslt |= bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + /* Write the fifo tag */ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_FIFO_TAG, fifo_tag); + rslt |= bmi088_set_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + } + else + { + rslt = BMI088_E_OUT_OF_RANGE; + } + } + + return rslt; + +} + +/*! + * @brief This API enables or disables the FIFO full interrupt of the gyro sensor. + */ +uint16_t bmi088_set_gyro_fifo_full_int(struct bmi088_int_cfg *int_config, struct bmi088_dev *dev, uint8_t fifo_full_enable) +{ + uint16_t rslt = 0; + uint8_t data[2] = { 0, 0 }; + uint8_t reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + /* Read the Interrupt control register and Interrupt configuration register together */ + reg_addr = BMI088_GYRO_INT_CTRL_REG; + rslt |= bmi088_get_gyro_regs(reg_addr, data, BMI088_TWO, dev); + + if (rslt == BMI088_OK) + { + data[0] = BMI088_SET_BITSLICE(data[0], BMI088_GYRO_FIFO_EN, fifo_full_enable); + + /* Interrupt pin or channel 3 */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_3) + { + /* Update data with user configured bmi088_int_cfg structure */ + data[1] = BMI088_SET_BITSLICE(data[1], BMI088_GYRO_INT3_LVL, int_config->gyro_int_pin_3_cfg.lvl); + data[1] = BMI088_SET_BITSLICE(data[1], BMI088_GYRO_INT3_OD, int_config->gyro_int_pin_3_cfg.output_mode); + } + + /* Interrupt pin or channel 4 */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_4) + { + /* Update data with user configured bmi088_int_cfg structure */ + data[1] = BMI088_SET_BITSLICE(data[1], BMI088_GYRO_INT4_LVL, int_config->gyro_int_pin_4_cfg.lvl); + data[1] = BMI088_SET_BITSLICE(data[1], BMI088_GYRO_INT4_OD, int_config->gyro_int_pin_4_cfg.output_mode); + } + + /* Both Interrupt pins or channels */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_BOTH) + { + /* Update data with user configured bmi088_int_cfg structure */ + data[1] = BMI088_SET_BITSLICE(data[1], BMI088_GYRO_INT3_LVL, int_config->gyro_int_pin_3_cfg.lvl); + data[1] = BMI088_SET_BITSLICE(data[1], BMI088_GYRO_INT3_OD, int_config->gyro_int_pin_3_cfg.output_mode); + data[1] = BMI088_SET_BITSLICE(data[1], BMI088_GYRO_INT4_LVL, int_config->gyro_int_pin_4_cfg.lvl); + data[1] = BMI088_SET_BITSLICE(data[1], BMI088_GYRO_INT4_OD, int_config->gyro_int_pin_4_cfg.output_mode); + } + + /* Write to Interrupt control register and Interrupt configuration register together */ + rslt |= bmi088_set_gyro_regs(reg_addr, data, BMI088_TWO, dev); + + if (rslt == BMI088_OK) + { + /* Read the Interrupt Map register */ + reg_addr = BMI088_GYRO_INT3_INT4_IO_MAP_REG; + rslt |= bmi088_get_gyro_regs(reg_addr, &data[0], BMI088_ONE, dev); + + /* Interrupt pin or channel 3 */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_3) + { + /* Map Interrupt pin 3 */ + data[0] = BMI088_SET_BITSLICE(data[0], BMI088_GYRO_INT1_FIFO, BMI088_ONE); + } + + /* Interrupt pin or channel 4 */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_4) + { + /* Map Interrupt pin 4 */ + data[0] = BMI088_SET_BITSLICE(data[0], BMI088_GYRO_INT2_FIFO, BMI088_ONE); + } + + /* Both Interrupt pins or channels */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_BOTH) + { + /* Map both Interrupt pins */ + data[0] = BMI088_SET_BITSLICE(data[0], BMI088_GYRO_INT1_FIFO, BMI088_ONE); + data[0] = BMI088_SET_BITSLICE(data[0], BMI088_GYRO_INT2_FIFO, BMI088_ONE); + } + + /* Write to Interrupt Map register */ + rslt |= bmi088_set_gyro_regs(reg_addr, &data[0], BMI088_ONE, dev); + } + } + } + + return rslt; + +} + +/*! + * @brief This API enables or disables the FIFO watermark interrupt of the gyro sensor. + */ +uint16_t bmi088_set_gyro_fifo_wm_int(struct bmi088_int_cfg *int_config, struct bmi088_dev *dev, uint8_t fifo_wm_enable) +{ + uint16_t rslt = 0; + uint8_t data, reg_addr; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_GYRO_INT3_INT4_IO_CONF_REG; + /* Read interrupt configuration register */ + rslt = bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Interrupt pin or channel 3 */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_3) + { + /* Update data with user configured bmi088_int_cfg structure */ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT3_LVL, int_config->gyro_int_pin_3_cfg.lvl); + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT3_OD, int_config->gyro_int_pin_3_cfg.output_mode); + } + + /* Interrupt pin or channel 4 */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_4) + { + /* Update data with user configured bmi088_int_cfg structure */ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT4_LVL, int_config->gyro_int_pin_4_cfg.lvl); + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT4_OD, int_config->gyro_int_pin_4_cfg.output_mode); + } + + /* Both Interrupt pins or channels */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_BOTH) + { + /* Update data with user configured bmi088_int_cfg structure */ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT3_LVL, int_config->gyro_int_pin_3_cfg.lvl); + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT3_OD, int_config->gyro_int_pin_3_cfg.output_mode); + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT4_LVL, int_config->gyro_int_pin_4_cfg.lvl); + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT4_OD, int_config->gyro_int_pin_4_cfg.output_mode); + } + + /* write to interrupt configuration register */ + rslt = bmi088_set_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + } + + } + + /* Read the Interrupt Map register */ + reg_addr = BMI088_GYRO_INT3_INT4_IO_MAP_REG; + rslt |= bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + /* Interrupt pin or channel 3 */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_3) + { + /* Map Interrupt pin 3 */ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT1_FIFO, BMI088_ONE); + } + + /* Interrupt pin or channel 4 */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_4) + { + /* Map Interrupt pin 4 */ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT2_FIFO, BMI088_ONE); + } + + /* Both Interrupt pins or channels */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_BOTH) + { + /* Map both Interrupt pins */ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT1_FIFO, BMI088_ONE); + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT2_FIFO, BMI088_ONE); + } + + /* Write to Interrupt Map register */ + rslt |= bmi088_set_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + /* Read the Interrupt enable register */ + reg_addr = BMI088_GYRO_INT_EN_REG; + rslt |= bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + /* Write to Interrupt enable register */ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT_EN, fifo_wm_enable); + rslt |= bmi088_set_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + return rslt; + +} + +/*****************************************************************************/ +/* Static function definition */ +/*! + * @brief This API is used to validate the device structure pointer for + * null conditions. + */ +static uint16_t null_ptr_check(const struct bmi088_dev *dev) +{ + uint16_t rslt; + + if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL)) + { + /* Device structure pointer is not valid */ + rslt = BMI088_E_NULL_PTR; + } + else + { + /* Device structure is fine */ + rslt = BMI088_OK; + } + + return rslt; +} + +/*! + * @brief This API is used to reset the FIFO related configurations + * in the Accel fifo_frame structure. + */ +static void reset_accel_fifo_data_structure(const struct bmi088_dev *dev) +{ + /* Prepare for next accel FIFO read by resetting accel FIFO's + internal data structures*/ + dev->accel_fifo->byte_start_idx = 0; + dev->accel_fifo->sensor_time = 0; + dev->accel_fifo->skipped_frame_count = 0; + dev->accel_fifo->dropped_frame_count = 0; + +} + +/*! + * @brief This API computes the number of bytes of accel FIFO data + * which is to be parsed in header-less mode. + */ +static void get_accel_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *accel_count, const struct bmi088_dev *dev) +{ + uint8_t dummy_byte_spi = 0; + + /*Check if this is the first iteration of data unpacking + if yes, then consider dummy byte on SPI*/ + if (dev->accel_fifo->byte_start_idx == 0) + { + dummy_byte_spi = dev->dummy_byte; + } + + /*Data start index*/ + *start_idx = dev->accel_fifo->byte_start_idx + dummy_byte_spi; + + if (dev->accel_fifo->fifo_data_enable == BMI088_FIFO_A_ENABLE) + { + /* Len has the number of bytes to loop for */ + *len = (uint16_t)(((*accel_count) * BMI088_FIFO_A_LENGTH) + dummy_byte_spi); + } + else + { + /* No sensor is enabled in FIFO, + so there will be no accel data. + Update the data index as complete*/ + *start_idx = dev->accel_fifo->length; + } + + if ((*len) > dev->accel_fifo->length) + { + /* Handling the case where more data is requested + than available */ + *len = dev->accel_fifo->length; + } +} + +/*! + * @brief This API checks the accel fifo read data as empty frame, if it + * is empty frame then moves the index to last byte. + */ +static void check_empty_accel_fifo(uint16_t *data_index, const struct bmi088_dev *dev) +{ + if ((*data_index + 2) < dev->accel_fifo->length) + { + /* Check if FIFO is empty */ + if ((dev->accel_fifo->data[*data_index] == FIFO_MSB_CONFIG_CHECK) + && (dev->accel_fifo->data[*data_index + BMI088_ONE] == FIFO_LSB_CONFIG_CHECK)) + { + /* Update the data index as complete*/ + *data_index = dev->accel_fifo->length; + } + } +} + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data in header mode. + */ +static void extract_accel_header_mode(struct bmi088_sensor_data *accel_data, uint16_t *accel_length, const struct bmi088_dev *dev) +{ + uint8_t frame_header = 0; + uint16_t data_index; + uint16_t accel_index = 0; + uint16_t frame_to_read = *accel_length; + + /*Check if this is the first iteration of data unpacking + if yes, then consider dummy byte on SPI*/ + if (dev->accel_fifo->byte_start_idx == 0) + { + dev->accel_fifo->byte_start_idx = dev->dummy_byte; + } + + for (data_index = dev->accel_fifo->byte_start_idx; data_index < dev->accel_fifo->length;) + { + /* Header byte is stored in the variable frame_header */ + frame_header = dev->accel_fifo->data[data_index]; + /* Get the frame details from header */ + frame_header = frame_header & BMI088_FIFO_TAG_INTR_MASK; + /* Index is moved to next byte where the data is starting */ + data_index++; + + switch (frame_header) + { + /* Accel frame */ + case FIFO_HEAD_A: + { + unpack_accel_frm(accel_data, &data_index, &accel_index, frame_header, dev); + } + break; + + /* Sensor time frame */ + case FIFO_HEAD_SENSOR_TIME: + { + unpack_sensortime_frame(&data_index, dev); + } + break; + + /* Skip frame */ + case FIFO_HEAD_SKIP_FRAME: + { + unpack_accel_skipped_frame(&data_index, dev); + } + break; + + /* Input config frame */ + case FIFO_HEAD_INPUT_CONFIG: + { + move_to_next_accel_frame(&data_index, BMI088_ONE, dev); + } + break; + + /* Sample drop frame */ + case FIFO_HEAD_SAMPLE_DROP: + { + unpack_accel_dropped_frame(&data_index, dev); + } + break; + + /* Over read FIFO data */ + case FIFO_HEAD_OVER_READ_MSB: + { + /* Update the data index as complete */ + data_index = dev->accel_fifo->length; + } + break; + + default: + break; + } + + if (frame_to_read == accel_index) + { + /* Number of frames to be read is completed */ + break; + } + } + + /* Update number of accel data read */ + *accel_length = accel_index; + /* Update the accel frame index */ + dev->accel_fifo->byte_start_idx = data_index; +} + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data in both header mode and header-less mode. + * It updates the idx value which is used to store the index of + * the current data byte which is parsed. + */ +static void unpack_accel_frm(struct bmi088_sensor_data *accel, uint16_t *idx, uint16_t *accel_idx, uint8_t frm, const struct bmi088_dev *dev) +{ + uint8_t is_buffer_end_reached = 0; + + if ((frm == FIFO_HEAD_A) || (frm == BMI088_FIFO_A_ENABLE)) + { + /* Partial read, then skip the data */ + if ((*idx + BMI088_FIFO_A_LENGTH) > dev->accel_fifo->length) + { + /* Update the data index as complete */ + *idx = dev->accel_fifo->length; + is_buffer_end_reached = 1; + } + + if (!is_buffer_end_reached) + { + /* Unpack the data array into the structure instance "accel" */ + unpack_accel_data(&accel[*accel_idx], *idx, dev); + /* Move the data index */ + *idx = *idx + BMI088_FIFO_A_LENGTH; + (*accel_idx)++; + } + } + +} + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data and store it in the instance of the structure bmi088_sensor_data. + */ +static void unpack_accel_data(struct bmi088_sensor_data *accel_data, uint16_t data_start_index, const struct bmi088_dev *dev) +{ + uint16_t data_lsb; + uint16_t data_msb; + + /* Accel raw x data */ + data_lsb = dev->accel_fifo->data[data_start_index++]; + data_msb = dev->accel_fifo->data[data_start_index++]; + accel_data->x = (int16_t)((data_msb << BMI088_EIGHT) | data_lsb); + + /* Accel raw y data */ + data_lsb = dev->accel_fifo->data[data_start_index++]; + data_msb = dev->accel_fifo->data[data_start_index++]; + accel_data->y = (int16_t)((data_msb << BMI088_EIGHT) | data_lsb); + + /* Accel raw z data */ + data_lsb = dev->accel_fifo->data[data_start_index++]; + data_msb = dev->accel_fifo->data[data_start_index++]; + accel_data->z = (int16_t)((data_msb << BMI088_EIGHT) | data_lsb); + +} + +/*! + * @brief This API is used to parse and store the sensor time from the + * FIFO data in the structure instance dev. + */ +static void unpack_sensortime_frame(uint16_t *data_index, const struct bmi088_dev *dev) +{ + uint32_t sensor_time_byte3 = 0; + uint16_t sensor_time_byte2 = 0; + uint8_t sensor_time_byte1 = 0; + + /* Partial read, then move the data index to last data */ + if ((*data_index + BMI088_SENSOR_TIME_LENGTH) > dev->accel_fifo->length) + { + /* Update the data index as complete */ + *data_index = dev->accel_fifo->length; + } + else + { + sensor_time_byte3 = dev->accel_fifo->data[(*data_index) + BMI088_SENSOR_TIME_MSB_BYTE] << BMI088_SIXTEEN; + sensor_time_byte2 = dev->accel_fifo->data[(*data_index) + BMI088_SENSOR_TIME_XLSB_BYTE] << BMI088_EIGHT; + sensor_time_byte1 = dev->accel_fifo->data[(*data_index) + BMI088_SENSOR_TIME_LSB_BYTE]; + /* Sensor time */ + dev->accel_fifo->sensor_time = (uint32_t)(sensor_time_byte3 | sensor_time_byte2 | sensor_time_byte1); + *data_index = (*data_index) + BMI088_SENSOR_TIME_LENGTH; + } +} + +/*! + * @brief This API is used to parse and store the skipped_frame_count from + * the accelerometer FIFO data in the structure instance dev. + */ +static void unpack_accel_skipped_frame(uint16_t *data_index, const struct bmi088_dev *dev) +{ + /* Partial read, then move the data index to last data */ + if (*data_index >= dev->accel_fifo->length) + { + /* Update the data index as complete */ + *data_index = dev->accel_fifo->length; + } + else + { + dev->accel_fifo->skipped_frame_count = dev->accel_fifo->data[*data_index]; + /* Move the data index */ + *data_index = (*data_index) + 1; + } +} + +/*! + * @brief This API is used to parse and store the dropped_frame_count from + * the accelerometer FIFO data in the structure instance dev. + */ +static void unpack_accel_dropped_frame(uint16_t *data_index, const struct bmi088_dev *dev) +{ + uint8_t dropped_frame = 0; + /* Partial read, then move the data index to last data */ + if (*data_index >= dev->accel_fifo->length) + { + /*Update the data index as complete*/ + *data_index = dev->accel_fifo->length; + } + else + { + /* Extract accel dropped frame count */ + dropped_frame = dev->accel_fifo->data[*data_index] & ACCEL_FIFO_DROP; + + /* Move the data index and update the dropped frame count */ + if (dropped_frame == ACCEL_FIFO_DROP) + { + *data_index = (*data_index) + BMI088_FIFO_A_LENGTH; + dev->accel_fifo->dropped_frame_count = dev->accel_fifo->dropped_frame_count + 1; + } + } +} + +/*! + * @brief This API is used to move the data index ahead of the + * current_frame_length parameter when unnecessary FIFO data appears while + * extracting the accel data. + */ +static void move_to_next_accel_frame(uint16_t *data_index, uint8_t current_frame_length, const struct bmi088_dev *dev) +{ + /* Partial read, then move the data index to last data */ + if ((*data_index + current_frame_length) > dev->accel_fifo->length) + { + /* Update the data index as complete */ + *data_index = dev->accel_fifo->length; + } + else + { + /* Move the data index to next frame */ + *data_index = *data_index + current_frame_length; + } +} + +/*! + * @brief This API is used to reset the gyro FIFO related configurations + * in the fifo_frame structure. + */ +static void reset_gyro_fifo_data_structure(const struct bmi088_dev *dev) +{ + /* Prepare for next gyro FIFO read by resetting gyro FIFO's + internal data structures */ + dev->gyro_fifo->byte_start_idx = 0; + dev->gyro_fifo->sensor_time = 0; + dev->gyro_fifo->skipped_frame_count = 0; + dev->gyro_fifo->dropped_frame_count = 0; + +} + +/*! + * @brief This API computes the number of bytes of Gyro FIFO data which is + * to be parsed in header-less mode. + */ +static void get_gyro_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *gyro_count, const struct bmi088_dev *dev) +{ + /* Data start index */ + *start_idx = dev->gyro_fifo->byte_start_idx; + + if (dev->gyro_fifo->fifo_data_enable == BMI088_GYRO_ALL_INT_DATA) + { + dev->gyro_fifo->frame_length = BMI088_FIFO_G_ALL_DATA_LENGTH; + } + else if (dev->gyro_fifo->fifo_data_enable == BMI088_GYRO_X_DATA) + { + dev->gyro_fifo->frame_length = BMI088_FIFO_G_X_LENGTH; + } + else if (dev->gyro_fifo->fifo_data_enable == BMI088_GYRO_Y_DATA) + { + dev->gyro_fifo->frame_length = BMI088_FIFO_G_Y_LENGTH; + } + else if (dev->gyro_fifo->fifo_data_enable == BMI088_GYRO_Z_DATA) + { + dev->gyro_fifo->frame_length = BMI088_FIFO_G_Z_LENGTH; + } + else + { + /* No sensor is enabled in FIFO, + so there will be no gyro data. + Update the data index as complete */ + *start_idx = dev->gyro_fifo->length; + dev->gyro_fifo->frame_length = 0; + } + + /* Len has the number of bytes to loop for */ + *len = (uint16_t)((*gyro_count) * dev->gyro_fifo->frame_length); + + /* Handling the case where more data is requested than available */ + if ((*len) > dev->gyro_fifo->length) + { + /* Len is equal to the FIFO length */ + *len = dev->gyro_fifo->length; + } +} + +/*! + * @brief This API is used to parse the gyroscope data from the + * FIFO data in header-less mode and update the data_index value + * which is used to store the index of the current data byte + * which is parsed. + */ +static uint16_t unpack_gyro_frm(struct bmi088_sensor_data *data, uint16_t *idx, uint16_t *gyro_idx, uint8_t frm, + const struct bmi088_dev *dev) +{ + uint16_t rslt = 0; + uint8_t is_buffer_end_reached = 0; + + if ((frm == BMI088_GYRO_ALL_INT_DATA) || (frm == BMI088_GYRO_X_DATA) + || (frm == BMI088_GYRO_Y_DATA) + || (frm == BMI088_GYRO_Z_DATA)) + { + /* Partial read, then skip the data */ + if ((*idx + dev->gyro_fifo->frame_length) > dev->gyro_fifo->length) + { + /*update the data index as complete*/ + *idx = dev->gyro_fifo->length; + is_buffer_end_reached = 1; + } + + if (!is_buffer_end_reached) + { + /* Unpack the data array into Gyro sensor data structure */ + unpack_gyro_data(&data[*gyro_idx], *idx, dev); + /* move the data index */ + *idx = *idx + dev->gyro_fifo->frame_length; + (*gyro_idx)++; + } + + } + + return rslt; +} + +/*! + * @brief This API is used to parse the gyroscope data from + * the FIFO data and store it in the instance of the structure + * gyro_data. + */ +static void unpack_gyro_data(struct bmi088_sensor_data *gyro_data, uint16_t start_idx, const struct bmi088_dev *dev) +{ + uint16_t data_lsb; + uint16_t data_msb; + + /* Gyro raw x data */ + data_lsb = dev->gyro_fifo->data[start_idx++]; + data_msb = dev->gyro_fifo->data[start_idx++]; + gyro_data->x = (int16_t)((data_msb << BMI088_EIGHT) | data_lsb); + + /* Gyro raw y data */ + data_lsb = dev->gyro_fifo->data[start_idx++]; + data_msb = dev->gyro_fifo->data[start_idx++]; + gyro_data->y = (int16_t)((data_msb << BMI088_EIGHT) | data_lsb); + + /* Gyro raw z data */ + data_lsb = dev->gyro_fifo->data[start_idx++]; + data_msb = dev->gyro_fifo->data[start_idx++]; + gyro_data->z = (int16_t)((data_msb << BMI088_EIGHT) | data_lsb); + +} + +/*! + * @brief This API checks the gyro fifo read data as empty frame, if it + * is empty frame then moves the index to last byte. + */ +static void check_empty_gyro_fifo(uint16_t *data_index, const struct bmi088_dev *dev) +{ + if ((*data_index + 2) < dev->gyro_fifo->length) + { + /* Check if FIFO is empty */ + if ((dev->gyro_fifo->data[*data_index] == FIFO_MSB_CONFIG_CHECK) + && (dev->gyro_fifo->data[*data_index + BMI088_ONE] == FIFO_LSB_CONFIG_CHECK)) + { + /* Update the data index as complete */ + *data_index = dev->gyro_fifo->length; + } + } +} + +#endif +/** @}*/ + diff --git a/src/drivers/bosch/src/bmi088_gyro.c b/src/drivers/bosch/src/bmi088_gyro.c new file mode 100644 index 0000000000..b47e4ddbb2 --- /dev/null +++ b/src/drivers/bosch/src/bmi088_gyro.c @@ -0,0 +1,718 @@ +/* + **************************************************************************** + * Copyright (C) 2015 - 2016 Bosch Sensortec GmbH + * + * File :bmi088_gyro.c + * + * Date: 30 Oct 2017 + * + * Revision: + * + * Usage: Sensor Driver for BMI088 family of sensors + * + **************************************************************************** + * Disclaimer + * + * Common: + * Bosch Sensortec products are developed for the consumer goods industry. + * They may only be used within the parameters of the respective valid + * product data sheet. Bosch Sensortec products are provided with the + * express understanding that there is no warranty of fitness for a + * particular purpose.They are not fit for use in life-sustaining, + * safety or security sensitive systems or any system or device + * that may lead to bodily harm or property damage if the system + * or device malfunctions. In addition,Bosch Sensortec products are + * not fit for use in products which interact with motor vehicle systems. + * The resale and or use of products are at the purchasers own risk and + * his own responsibility. The examination of fitness for the intended use + * is the sole responsibility of the Purchaser. + * + * The purchaser shall indemnify Bosch Sensortec from all third party + * claims, including any claims for incidental, or consequential damages, + * arising from any product use not covered by the parameters of + * the respective valid product data sheet or not approved by + * Bosch Sensortec and reimburse Bosch Sensortec for all costs in + * connection with such claims. + * + * The purchaser must monitor the market for the purchased products, + * particularly with regard to product safety and inform Bosch Sensortec + * without delay of all security relevant incidents. + * + * Engineering Samples are marked with an asterisk (*) or (e). + * Samples may vary from the valid technical specifications of the product + * series. They are therefore not intended or fit for resale to third + * parties or for use in end products. Their sole purpose is internal + * client testing. The testing of an engineering sample may in no way + * replace the testing of a product series. Bosch Sensortec assumes + * no liability for the use of engineering samples. + * By accepting the engineering samples, the Purchaser agrees to indemnify + * Bosch Sensortec from all claims arising from the use of engineering + * samples. + * + * Special: + * This software module (hereinafter called "Software") and any information + * on application-sheets (hereinafter called "Information") is provided + * free of charge for the sole purpose to support your application work. + * The Software and Information is subject to the following + * terms and conditions: + * + * The Software is specifically designed for the exclusive use for + * Bosch Sensortec products by personnel who have special experience + * and training. Do not use this Software if you do not have the + * proper experience or training. + * + * This Software package is provided `` as is `` and without any expressed + * or implied warranties,including without limitation, the implied warranties + * of merchantability and fitness for a particular purpose. + * + * Bosch Sensortec and their representatives and agents deny any liability + * for the functional impairment + * of this Software in terms of fitness, performance and safety. + * Bosch Sensortec and their representatives and agents shall not be liable + * for any direct or indirect damages or injury, except as + * otherwise stipulated in mandatory applicable law. + * + * The Information provided is believed to be accurate and reliable. + * Bosch Sensortec assumes no responsibility for the consequences of use + * of such Information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of Bosch. Specifications mentioned in the Information are + * subject to change without notice. + **************************************************************************/ +/*! \file bmi088_gyro.c + \brief Sensor Driver for BMI088 family of sensors */ +/***************************************************************************/ +/**\name Header files + ****************************************************************************/ +#include "bmi088.h" + +/***************************************************************************/ +/**\name Local structures + ****************************************************************************/ + +/***************************************************************************/ +/*! Static Function Declarations + ****************************************************************************/ + +/*! + * @brief This API is used to validate the device structure pointer for + * null conditions. + * + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ +static uint16_t null_ptr_check(struct bmi088_dev *dev); + +/*! + * @brief This API sets the data ready interrupt for gyro sensor. + * + * @param[in] int_config : Structure instance of bmi088_int_cfg. + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ +static uint16_t set_gyro_data_ready_int(const struct bmi088_int_cfg *int_config, struct bmi088_dev *dev); + +/*! + * @brief This API configures the pins which fire the + * interrupt signal when any interrupt occurs. + * + * @param[in] int_config : Structure instance of bmi088_int_cfg. + * @param[in] dev : Structure instance of bmi088_dev. + * + * @return Result of API execution status + * @retval zero -> Success + * @retval Any non zero value -> Fail + */ +static uint16_t set_int_pin_config(const struct bmi088_int_cfg *int_config, struct bmi088_dev *dev); + +/***************************************************************************/ +/**\name Extern Declarations + ****************************************************************************/ + +/***************************************************************************/ +/**\name Globals + ****************************************************************************/ + +/* Copy of gyro_cfg structure of device structure. It + * prevents overwriting same gyro configuration data */ +static struct bmi088_cfg gyro_cfg_copy; + +/***************************************************************************/ +/**\name Function definitions + ****************************************************************************/ + +/*! + * @brief This API is the entry point for gyro sensor. + * It performs the selection of I2C/SPI read mechanism according to the + * selected interface and reads the chip-id of gyro sensor. + */ +uint16_t bmi088_gyro_init(struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, data = 0; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + reg_addr = BMI088_GYRO_CHIP_ID_REG; + /* Read gyro chip id */ + rslt |= bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Assign Chip Id */ + dev->gyro_chip_id = data; + + /* Initializing gyro sensor parameters with default values */ + dev->gyro_cfg.bw = BMI088_GYRO_ODR_RESET_VAL; + dev->gyro_cfg.power = BMI088_GYRO_PM_NORMAL; + dev->gyro_cfg.range = BMI088_GYRO_RANGE_2000_DPS; + + /* Copying gyro_cfg parameters of device structure to + * gyro_cfg_copy structure to maintain a copy. This will + * help us to prevent writing same configuration data + * again and again */ + gyro_cfg_copy.bw = dev->gyro_cfg.bw; + gyro_cfg_copy.power = dev->gyro_cfg.power; + gyro_cfg_copy.range = dev->gyro_cfg.range; + + } + else + { + rslt = BMI088_E_COM_FAIL; + } + + } + + return rslt; +} + +/*! + * @brief This API reads the data from the given register address + * of gyro sensor. + */ +uint16_t bmi088_get_gyro_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + /* Configuring reg_addr for SPI Interface */ + if (dev->interface == BMI088_SPI_INTF) + { + reg_addr = (reg_addr | BMI088_SPI_RD_MASK); + } + + /* read a gyro register */ + rslt = dev->read(dev->gyro_id, reg_addr, data, len); + + if (rslt != BMI088_OK) + { + rslt = BMI088_E_COM_FAIL; + } + } + + return rslt; +} + +/*! + * @brief This API writes the given data to the register address + * of gyro sensor. + */ +uint16_t bmi088_set_gyro_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if ((rslt == BMI088_OK) && (data != NULL) && (len != 0)) + { + /* Configuring reg_addr for SPI Interface */ + if (dev->interface == BMI088_SPI_INTF) + { + reg_addr = (reg_addr & BMI088_SPI_WR_MASK); + } + + /* write to a gyro register */ + rslt = dev->write(dev->gyro_id, reg_addr, data, len); + + if (rslt != BMI088_OK) + { + rslt = BMI088_E_COM_FAIL; + } + } + + return rslt; +} + +/*! + * @brief This API resets the gyro sensor. + */ +uint16_t bmi088_gyro_soft_reset(struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t data, reg_addr; + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + /* Reset gyro device */ + reg_addr = BMI088_GYRO_SOFTRESET_REG; + data = BMI088_SOFT_RESET_VAL; + rslt = bmi088_set_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* delay 30 ms after writing reset value to its register */ + dev->delay_ms(BMI088_GYRO_SOFTRESET_DELAY); + } + } + + return rslt; +} + +/*! + * @brief This API sets the power mode, range and bandwidth + * of gyro sensor. + */ +uint16_t bmi088_set_gyro_meas_conf(struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr; + bool is_range_invalid = false, is_odr_invalid = false; + uint8_t odr, range; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + odr = dev->gyro_cfg.odr; + range = dev->gyro_cfg.range; + + /* Check if range is not previously configured range */ + if (range != gyro_cfg_copy.range) + { + /* Check for valid range */ + if (range <= BMI088_GYRO_RANGE_125_DPS) + { + reg_addr = BMI088_GYRO_RANGE_REG; + /* Write range value to range register */ + rslt = bmi088_set_gyro_regs(reg_addr, &range, BMI088_ONE, dev); + + /* If rslt is ok, copy the current range to previous range to maintain a copy */ + if (rslt == BMI088_OK) + { + gyro_cfg_copy.range = range; + } + } + else + { + /* Set range as invalid */ + is_range_invalid = true; + } + } + + /* Check if odr is not previously configured odr */ + if (odr != gyro_cfg_copy.odr) + { + /* Check for valid odr */ + if (odr <= BMI088_GYRO_BW_32_ODR_100_HZ) + { + reg_addr = BMI088_GYRO_BANDWIDTH_REG; + /* Write odr value to odr register */ + rslt = bmi088_set_gyro_regs(reg_addr, &odr, BMI088_ONE, dev); + + /* If rslt is ok, copy the current odr to previous odr to maintain a copy */ + if (rslt == BMI088_OK) + { + gyro_cfg_copy.odr = odr; + } + } + else + { + /* Set odr as invalid */ + is_odr_invalid = true; + } + } + } + + /* If invalid conditions take place, make rslt as invalid */ + if ((is_range_invalid) || (is_odr_invalid)) + { + rslt = BMI088_E_INVALID_INPUT; + } + + return rslt; +} + +/*! + * @brief This API sets the power mode of the gyro sensor. + */ +uint16_t bmi088_set_gyro_power_mode(struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, power; + bool is_power_switching_mode_valid = true; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + power = dev->gyro_cfg.power; + + /* Check if power is not previously configured power */ + if (power != gyro_cfg_copy.power) + { + /* Check for invalid power switching (i.e) deep suspend to suspend */ + if ((power == BMI088_GYRO_PM_SUSPEND) && (gyro_cfg_copy.power == BMI088_GYRO_PM_DEEP_SUSPEND)) + { + is_power_switching_mode_valid = false; + } + + /* Check for invalid power switching (i.e) from suspend to deep suspend */ + if ((power == BMI088_GYRO_PM_DEEP_SUSPEND) && (gyro_cfg_copy.power == BMI088_GYRO_PM_SUSPEND)) + { + is_power_switching_mode_valid = false; + } + + /* Check if power switching mode is valid*/ + if (is_power_switching_mode_valid) + { + reg_addr = BMI088_GYRO_LPM1_REG; + /* Write power to power register */ + rslt = bmi088_set_gyro_regs(reg_addr, &power, BMI088_ONE, dev); + + /* If rslt is fine, copy current power to previous power to maintain a copy */ + if (rslt == BMI088_OK) + { + gyro_cfg_copy.power = power; + } + } + } + + } + + return rslt; +} + +/*! + * @brief This API reads the gyro data from the sensor, + * store it in the bmi088_sensor_data structure instance + * passed by the user. + */ +uint16_t bmi088_get_gyro_data(struct bmi088_sensor_data *gyro, struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t index = 0, reg_addr, data[6]; + uint32_t lsb, msb, msblsb; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if ((rslt == BMI088_OK) && (gyro != NULL)) + { + reg_addr = BMI088_GYRO_X_LSB_REG; + /* read gyro sensor data */ + rslt = bmi088_get_gyro_regs(reg_addr, data, BMI088_SIX, dev); + + if (rslt == BMI088_OK) + { + lsb = (uint32_t)data[index++]; + msb = (uint32_t)data[index++]; + msblsb = (msb << BMI088_EIGHT) | lsb; + gyro->x = (int16_t)msblsb; /* Data in X axis */ + + lsb = (uint32_t)data[index++]; + msb = (uint32_t)data[index++]; + msblsb = (msb << BMI088_EIGHT) | lsb; + gyro->y = (int16_t)msblsb; /* Data in Y axis */ + + lsb = (uint32_t)data[index++]; + msb = (uint32_t)data[index++]; + msblsb = (msb << BMI088_EIGHT) | lsb; + gyro->z = (int16_t)msblsb; /* Data in Z axis */ + } + } + + return rslt; +} + +/*! + * @brief This API configures the necessary gyro interrupt + * based on the user settings in the bmi088_int_cfg + * structure instance. + */ +uint16_t bmi088_set_gyro_int_config(const struct bmi088_int_cfg *int_config, struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + + switch (int_config->gyro_int_type) + { + case BMI088_GYRO_DATA_RDY_INT: + { + /* Data ready interrupt */ + rslt = set_gyro_data_ready_int(int_config, dev); + } + break; + default: + break; + } + + return rslt; + +} + +/*! + * @brief This API enables or disables the Gyro Self test feature in the + * sensor. + */ +uint16_t bmi088_set_gyro_selftest(uint8_t selftest, struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, data = 0; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + /* Check for valid selftest input */ + if ((selftest == BMI088_ENABLE) || (selftest == BMI088_DISABLE)) + { + reg_addr = BMI088_GYRO_SELF_TEST_REG; + /* Read self test register */ + rslt = bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Enable self-test */ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_SELF_TEST_EN, selftest); + /* write self test input value to self-test register */ + rslt = bmi088_set_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + } + } + else + { + rslt = BMI088_E_INVALID_INPUT; + } + } + + return rslt; +} + +/*! + * @brief This API checks whether the self test functionality of the + * gyro sensor is working or not. + */ +uint16_t bmi088_perform_gyro_selftest(int8_t *result, struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, data = 0, loop_break = 1; + + *result = BMI088_SELFTEST_FAIL; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMI088_OK) + { + /* Enable the gyro self-test */ + rslt = bmi088_set_gyro_selftest(BMI088_ENABLE, dev); + + if (rslt == BMI088_OK) + { + /* Loop till self-test ready bit is set */ + while (loop_break) + { + reg_addr = BMI088_GYRO_SELF_TEST_REG; + /* Read self-test register to check if self-test ready bit is set */ + rslt = bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + data = BMI088_GET_BITSLICE(data, BMI088_GYRO_SELF_TEST_RDY); + + /* If self-test ready bit is set, exit the loop */ + if (data) + { + loop_break = 0; + } + } + else + { + /* Exit the loop in case of communication failure */ + loop_break = 0; + } + } + + if (rslt == BMI088_OK) + { + /* Read self-test register to check for self-test Ok bit */ + rslt = bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + data = BMI088_GET_BITSLICE(data, BMI088_GYRO_SELF_TEST_RESULT); + + /* Update the self-test result based on self-test Ok bit */ + if (!data) + { + *result = BMI088_SELFTEST_PASS; + } + } + } + } + + } + + return rslt; +} + +/*****************************************************************************/ +/* Static function definition */ +/*! + * @brief This API is used to validate the device structure pointer for + * null conditions. + */ +static uint16_t null_ptr_check(struct bmi088_dev *dev) +{ + uint16_t rslt; + + if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL)) + { + /* Device structure pointer is not valid */ + rslt = BMI088_E_NULL_PTR; + } + else + { + /* Device structure is fine */ + rslt = BMI088_OK; + } + + return rslt; +} + +/*! + * @brief This API sets the data ready interrupt for gyro sensor. + */ +static uint16_t set_gyro_data_ready_int(const struct bmi088_int_cfg *int_config, struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, data; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if ((rslt == BMI088_OK) && (int_config != NULL)) + { + reg_addr = BMI088_GYRO_INT_CTRL_REG; + /* Data to enable new data ready interrupt */ + data = BMI088_GYRO_DRDY_INT_ENABLE_VAL; + + /* write data to interrupt control register */ + rslt = bmi088_set_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + reg_addr = BMI088_GYRO_INT3_INT4_IO_MAP_REG; + + /* update data to map data ready interrupt to appropriate pins */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_3) + { + data = BMI088_GYRO_MAP_DRDY_TO_INT3; + } + + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_4) + { + data = BMI088_GYRO_MAP_DRDY_TO_INT4; + } + + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_BOTH) + { + data = BMI088_GYRO_MAP_DRDY_TO_BOTH_INT3_INT4; + } + + /* write data to interrupt map register */ + rslt = bmi088_set_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + /* Configure interrupt pin */ + rslt |= set_int_pin_config(int_config, dev); + + } + } + + return rslt; + +} + +/*! + * @brief This API configures the pins which fire the + * interrupt signal when any interrupt occurs. + */ +static uint16_t set_int_pin_config(const struct bmi088_int_cfg *int_config, struct bmi088_dev *dev) +{ + uint16_t rslt = BMI088_OK; + uint8_t reg_addr, data; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if ((rslt == BMI088_OK) && (int_config != NULL)) + { + reg_addr = BMI088_GYRO_INT3_INT4_IO_CONF_REG; + /* Read interrupt configuration register */ + rslt = bmi088_get_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + + if (rslt == BMI088_OK) + { + /* Interrupt pin or channel 3 */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_3) + { + /* Update data with user configured bmi088_int_cfg structure */ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT3_LVL, int_config->gyro_int_pin_3_cfg.lvl); + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT3_OD, int_config->gyro_int_pin_3_cfg.output_mode); + } + + /* Interrupt pin or channel 4 */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_4) + { + /* Update data with user configured bmi088_int_cfg structure */ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT4_LVL, int_config->gyro_int_pin_4_cfg.lvl); + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT4_OD, int_config->gyro_int_pin_4_cfg.output_mode); + } + + /* Both Interrupt pins or channels */ + if (int_config->gyro_int_channel == BMI088_INT_CHANNEL_BOTH) + { + /* Update data with user configured bmi088_int_cfg structure */ + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT3_LVL, int_config->gyro_int_pin_3_cfg.lvl); + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT3_OD, int_config->gyro_int_pin_3_cfg.output_mode); + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT4_LVL, int_config->gyro_int_pin_4_cfg.lvl); + data = BMI088_SET_BITSLICE(data, BMI088_GYRO_INT4_OD, int_config->gyro_int_pin_4_cfg.output_mode); + } + + /* write to interrupt configuration register */ + rslt = bmi088_set_gyro_regs(reg_addr, &data, BMI088_ONE, dev); + } + } + + return rslt; + +} + +/** @}*/ + diff --git a/src/drivers/bosch/src/bmp3.c b/src/drivers/bosch/src/bmp3.c new file mode 100644 index 0000000000..9748754836 --- /dev/null +++ b/src/drivers/bosch/src/bmp3.c @@ -0,0 +1,2459 @@ +/**\mainpage + * Copyright (C) 2016 - 2017 Bosch Sensortec GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 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. + * + * Neither the name of the copyright holder nor the names of the + * 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 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 + * + * The information provided is believed to be accurate and reliable. + * The copyright holder assumes no responsibility + * for the consequences of use + * of such information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of the copyright holder. + * + * File bmp3.c + * Date 04 Dec 2017 + * Version 1.0.0 + * + */ + +/*! @file bmp3.c + @brief Sensor driver for BMP3 sensor */ +#include "bmp3.h" + +/***************** Internal macros ******************************/ + +/*! Power control settings */ +#define POWER_CNTL UINT16_C(0x0006) +/*! Odr and filter settings */ +#define ODR_FILTER UINT16_C(0x00F0) +/*! Interrupt control settings */ +#define INT_CTRL UINT16_C(0x0708) +/*! Advance settings */ +#define ADV_SETT UINT16_C(0x1800) + +/*! FIFO settings */ +/*! Mask for fifo_mode, fifo_stop_on_full, fifo_time_en, fifo_press_en and + fifo_temp_en settings */ +#define FIFO_CONFIG_1 UINT16_C(0x003E) +/*! Mask for fifo_sub_sampling and data_select settings */ +#define FIFO_CONFIG_2 UINT16_C(0x00C0) +/*! Mask for fwtm_en and ffull_en settings */ +#define FIFO_INT_CTRL UINT16_C(0x0300) + +/*! FIFO Header */ +/*! FIFO temperature pressure header frame */ +#define FIFO_TEMP_PRESS_FRAME UINT8_C(0x94) +/*! FIFO temperature header frame */ +#define FIFO_TEMP_FRAME UINT8_C(0x90) +/*! FIFO pressure header frame */ +#define FIFO_PRESS_FRAME UINT8_C(0x84) +/*! FIFO time header frame */ +#define FIFO_TIME_FRAME UINT8_C(0xA0) +/*! FIFO error header frame */ +#define FIFO_ERROR_FRAME UINT8_C(0x44) +/*! FIFO configuration change header frame */ +#define FIFO_CONFIG_CHANGE UINT8_C(0x48) + +/***************** Static function declarations ******************************/ +/*! + * @brief This internal API reads the calibration data from the sensor, parse + * it then compensates it and store in the device structure. + * + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t get_calib_data(struct bmp3_dev *dev); + +/*! + * @brief This internal API is used to parse the calibration data, compensates + * it and store it in device structure. + * + * @param[in] dev : Structure instance of bmp3_dev. + * @param[out] reg_data : Contains calibration data to be parsed. + * + */ +static void parse_calib_data(const uint8_t *reg_data, struct bmp3_dev *dev); + +/*! + * @brief This internal API gets the over sampling, odr and filter settings + * from the sensor. + * + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t get_odr_filter_settings(struct bmp3_dev *dev); + +/*! + * @brief This internal API is used to parse the pressure and temperature data + * and store it in the bmp3_uncomp_data structure instance. + * + * @param[in] reg_data : Contains the register data which needs to be parsed. + * @param[out] uncomp_data : Contains the uncompensated press and temp data. + * + */ +static void parse_sensor_data(const uint8_t *reg_data, struct bmp3_uncomp_data *uncomp_data); + +/*! + * @brief This internal API is used to compensate the pressure or temperature + * or both the data according to the component selected by the user. + * + * @param[in] sensor_comp : Used to select pressure or temperature. + * @param[in] uncomp_data : Contains the uncompensated pressure and + * temperature data. + * @param[out] comp_data : Contains the compensated pressure and + * temperature data. + * @param[in] calib_data : Pointer to the calibration data structure. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t compensate_data(uint8_t sensor_comp, const struct bmp3_uncomp_data *uncomp_data, + struct bmp3_data *comp_data, struct bmp3_calib_data *calib_data); +#ifdef FLOATING_POINT_COMPENSATION +/*! + * @brief This internal API is used to compensate the raw temperature data and + * return the compensated temperature data. + * + * @param[in] uncomp_data : Contains the uncompensated temperature data. + * @param[in] calib_data : Pointer to calibration data structure. + * + * @return Compensated temperature data. + * @retval Compensated temperature data in float. + */ +static float compensate_temperature(const struct bmp3_uncomp_data *uncomp_data, + struct bmp3_calib_data *calib_data); + +/*! + * @brief This internal API is used to compensate the pressure data and return + * the compensated pressure data. + * + * @param[in] uncomp_data : Contains the uncompensated pressure data. + * @param[in] calib_data : Pointer to the calibration data structure. + * + * @return Compensated pressure data. + * @retval Compensated pressure data in float. + */ +static float compensate_pressure(const struct bmp3_uncomp_data *uncomp_data, + const struct bmp3_calib_data *calib_data); + +/*! + * @brief This internal API is used to calculate the power functionality for + * floating point values. + * + * @param[in] base : Contains the base value. + * @param[in] power : Contains the power value. + * + * @return Output of power function. + * @retval Calculated power function output in float. + */ +static float bmp3_pow(float base, uint8_t power); +#else +/*! + * @brief This internal API is used to compensate the raw temperature data and + * return the compensated temperature data in integer data type. + * + * @param[in] uncomp_data : Contains the uncompensated temperature data. + * @param[in] calib_data : Pointer to calibration data structure. + * + * @return Compensated temperature data. + * @retval Compensated temperature data in integer. + */ +static int64_t compensate_temperature(const struct bmp3_uncomp_data *uncomp_data, + struct bmp3_calib_data *calib_data); + +/*! + * @brief This internal API is used to compensate the pressure data and return + * the compensated pressure data in integer data type. + * + * @param[in] uncomp_data : Contains the uncompensated pressure data. + * @param[in] calib_data : Pointer to the calibration data structure. + * + * @return Compensated pressure data. + * @retval Compensated pressure data in integer. + */ +static uint64_t compensate_pressure(const struct bmp3_uncomp_data *uncomp_data, + const struct bmp3_calib_data *calib_data); + +/*! + * @brief This internal API is used to calculate the power functionality. + * + * @param[in] base : Contains the base value. + * @param[in] power : Contains the power value. + * + * @return Output of power function. + * @retval Calculated power function output in integer. + */ +static uint32_t bmp3_pow(uint8_t base, uint8_t power); +#endif + + +/*! + * @brief This internal API is used to identify the settings which the user + * wants to modify in the sensor. + * + * @param[in] sub_settings : Contains the settings subset to identify particular + * group of settings which the user is interested to change. + * @param[in] settings : Contains the user specified settings. + * + * @return Indicates whether user is interested to modify the settings which + * are related to sub_settings. + * @retval True -> User wants to modify this group of settings + * @retval False -> User does not want to modify this group of settings + */ +static uint8_t are_settings_changed(uint32_t sub_settings, uint32_t settings); + +/*! + * @brief This internal API interleaves the register address between the + * register data buffer for burst write operation. + * + * @param[in] reg_addr : Contains the register address array. + * @param[out] temp_buff : Contains the temporary buffer to store the + * register data and register address. + * @param[in] reg_data : Contains the register data to be written in the + * temporary buffer. + * @param[in] len : No of bytes of data to be written for burst write. + * + */ +static void interleave_reg_addr(const uint8_t *reg_addr, uint8_t *temp_buff, const uint8_t *reg_data, uint8_t len); + +/*! + * @brief This internal API sets the pressure enable and + * temperature enable settings of the sensor. + * + * @param[in] desired_settings : Contains the settings which user wants to + * change. + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t set_pwr_ctrl_settings(uint32_t desired_settings, const struct bmp3_dev *dev); + +/*! + * @brief This internal API sets the over sampling, odr and filter settings of + * the sensor based on the settings selected by the user. + * + * @param[in] desired_settings : Variable used to select the settings which + * are to be set. + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t set_odr_filter_settings(uint32_t desired_settings, struct bmp3_dev *dev); + +/*! + * @brief This internal API sets the interrupt control (output mode, level, + * latch and data ready) settings of the sensor based on the settings + * selected by the user. + * + * @param[in] desired_settings : Variable used to select the settings which + * are to be set. + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t set_int_ctrl_settings(uint32_t desired_settings, const struct bmp3_dev *dev); + +/*! + * @brief This internal API sets the advance (i2c_wdt_en, i2c_wdt_sel) + * settings of the sensor based on the settings selected by the user. + * + * @param[in] desired_settings : Variable used to select the settings which + * are to be set. + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t set_advance_settings(uint32_t desired_settings, const struct bmp3_dev *dev); + +/*! + * @brief This internal API fills the register address and register data of the + * the over sampling settings for burst write operation. + * + * @param[in] desired_settings : Variable which specifies the settings which + * are to be set in the sensor. + * @param[out] addr : To store the address to fill in register buffer. + * @param[out] reg_data : To store the osr register data. + * @param[out] len : To store the len for burst write. + * @param[in] dev : Structure instance of bmp3_dev. + * + */ +static void fill_osr_data(uint32_t desired_settings, uint8_t *addr, uint8_t *reg_data, uint8_t *len, + const struct bmp3_dev *dev); + +/*! + * @brief This internal API fills the register address and register data of the + * the odr settings for burst write operation. + * + * @param[out] addr : To store the address to fill in register buffer. + * @param[out] reg_data : To store the register data to set the odr data. + * @param[out] len : To store the len for burst write. + * @param[in] dev : Structure instance of bmp3_dev. + * + */ +static void fill_odr_data(uint8_t *addr, uint8_t *reg_data, uint8_t *len, struct bmp3_dev *dev); + +/*! + * @brief This internal API fills the register address and register data of the + * the filter settings for burst write operation. + * + * @param[out] addr : To store the address to fill in register buffer. + * @param[out] reg_data : To store the register data to set the filter. + * @param[out] len : To store the len for burst write. + * @param[in] dev : Structure instance of bmp3_dev. + * + */ +static void fill_filter_data(uint8_t *addr, uint8_t *reg_data, uint8_t *len, const struct bmp3_dev *dev); + +/*! + * @brief This internal API is used to validate the device pointer for + * null conditions. + * + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t null_ptr_check(const struct bmp3_dev *dev); + +/*! + * @brief This internal API parse the power control(power mode, pressure enable + * and temperature enable), over sampling, odr, filter and interrupt control + * settings and store in the device structure. + * + * @param[in] reg_data : Register data to be parsed. + * @param[out] dev : Structure instance of bmp3_dev. + */ +static void parse_sett_data(const uint8_t *reg_data, struct bmp3_dev *dev); + +/*! + * @brief This internal API parse the power control(power mode, pressure enable + * and temperature enable) settings and store in the device structure. + * + * @param[in] reg_data : Pointer variable which stores the register data to + * parse. + * @param[out] settings : Structure instance of bmp3_settings. + */ +static void parse_pwr_ctrl_settings(const uint8_t *reg_data, struct bmp3_settings *settings); + +/*! + * @brief This internal API parse the over sampling, odr and filter + * settings and store in the device structure. + * + * @param[in] reg_data : Pointer variable which stores the register data to + * parse. + * @param[out] settings : Structure instance of bmp3_odr_filter_settings. + */ +static void parse_odr_filter_settings(const uint8_t *reg_data, struct bmp3_odr_filter_settings *settings); + +/*! + * @brief This internal API parse the interrupt control(output mode, level, + * latch and data ready) settings and store in the device structure. + * + * @param[in] reg_data : Pointer variable which stores the register data to + * parse. + * @param[out] settings : Structure instance of bmp3_int_ctrl_settings. + */ +static void parse_int_ctrl_settings(const uint8_t *reg_data, struct bmp3_int_ctrl_settings *settings); + +/*! + * @brief This internal API parse the advance (i2c_wdt_en, i2c_wdt_sel) + * settings and store in the device structure. + * + * @param[in] reg_data : Pointer variable which stores the register data to + * parse. + * @param[out] settings : Structure instance of bmp3_adv_settings. + */ +static void parse_advance_settings(const uint8_t *reg_data, struct bmp3_adv_settings *settings); + +/*! + * @brief This internal API validate the normal mode settings of the sensor. + * + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t validate_normal_mode_settings(struct bmp3_dev *dev); + +/*! + * @brief This internal API validate the over sampling, odr settings of the + * sensor. + * + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Indicates whether odr and osr settings are valid or not. + * @retval zero -> Success / -ve value -> Error + */ +static int8_t validate_osr_and_odr_settings(const struct bmp3_dev *dev); + +/*! + * @brief This internal API calculates the pressure measurement duration of the + * sensor. + * + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Pressure measurement time + * @retval Pressure measurement time in milli secs + */ +static uint16_t calculate_press_meas_time(const struct bmp3_dev *dev); + +/*! + * @brief This internal API calculates the temperature measurement duration of + * the sensor. + * + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Temperature measurement time + * @retval Temperature measurement time in millisecs + */ +static uint16_t calculate_temp_meas_time(const struct bmp3_dev *dev); + +/*! + * @brief This internal API checks whether the measurement time and odr duration + * of the sensor are proper. + * + * @param[in] meas_t : Pressure and temperature measurement time in millisecs. + * @param[in] odr_duration : Duration in millisecs corresponding to the odr + * value. + * + * @return Indicates whether odr and osr settings are valid or not. + * @retval zero -> Success / +ve value -> Warning + */ +static int8_t verify_meas_time_and_odr_duration(uint16_t meas_t, uint32_t odr_duration); + +/*! + * @brief This internal API puts the device to sleep mode. + * + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status. + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t put_device_to_sleep(const struct bmp3_dev *dev); + +/*! + * @brief This internal API sets the normal mode in the sensor. + * + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status. + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t set_normal_mode(struct bmp3_dev *dev); + +/*! + * @brief This internal API writes the power mode in the sensor. + * + * @param[in] dev : Structure instance of bmp3_dev. + * + * @return Result of API execution status. + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t write_power_mode(const struct bmp3_dev *dev); + +/*! + * @brief This internal API fills the fifo_config_1(fifo_mode, + * fifo_stop_on_full, fifo_time_en, fifo_press_en, fifo_temp_en) settings in the + * reg_data variable so as to burst write in the sensor. + * + * @param[in] desired_settings : Variable which specifies the settings which + * are to be set in the sensor. + * @param[out] reg_data : Pointer variable where the fifo_config_1 register + * data will be stored so as to burst write in the register. + * @param[in] dev_fifo : Structure instance of bmp3_fifo_settings which + * contains the fifo_config_1 values set by the user. + */ +static void fill_fifo_config_1(uint16_t desired_settings, uint8_t *reg_data, + struct bmp3_fifo_settings *dev_fifo); + +/*! + * @brief This internal API fills the fifo_config_2(fifo_sub_sampling, + * data_select) settings in the reg_data variable so as to burst write + * in the sensor. + * + * @param[in] desired_settings : Variable which specifies the settings which + * are to be set in the sensor. + * @param[out] reg_data : Pointer variable where the fifo_config_2 register + * data will be stored so as to burst write in the register. + * @param[in] dev_fifo : Structure instance of bmp3_fifo_settings which + * contains the fifo_config_2 values set by the user. + */ +static void fill_fifo_config_2(uint16_t desired_settings, uint8_t *reg_data, + const struct bmp3_fifo_settings *dev_fifo); + +/*! + * @brief This internal API fills the fifo interrupt control(fwtm_en, ffull_en) + * settings in the reg_data variable so as to burst write in the sensor. + * + * @param[in] desired_settings : Variable which specifies the settings which + * are to be set in the sensor. + * @param[out] reg_data : Pointer variable where the fifo interrupt control + * register data will be stored so as to burst write in the register. + * @param[in] dev_fifo : Structure instance of bmp3_fifo_settings which + * contains the fifo interrupt control values set by the user. + */ +static void fill_fifo_int_ctrl(uint16_t desired_settings, uint8_t *reg_data, + const struct bmp3_fifo_settings *dev_fifo); + +/*! + * @brief This internal API is used to parse the fifo_config_1(fifo_mode, + * fifo_stop_on_full, fifo_time_en, fifo_press_en, fifo_temp_en), + * fifo_config_2(fifo_subsampling, data_select) and int_ctrl(fwtm_en, ffull_en) + * settings and store it in device structure + * + * @param[in] reg_data : Pointer variable which stores the fifo settings data + * read from the sensor. + * @param[out] dev_fifo : Structure instance of bmp3_fifo_settings which + * contains the fifo settings after parsing. + */ +static void parse_fifo_settings(const uint8_t *reg_data, struct bmp3_fifo_settings *dev_fifo); + +/*! + * @brief This internal API parse the FIFO data frame from the fifo buffer and + * fills the byte count, uncompensated pressure and/or temperature data and no + * of parsed frames. + * + * @param[in] header : Pointer variable which stores the fifo settings data + * read from the sensor. + * @param[in,out] fifo : Structure instance of bmp3_fifo which stores the + * read fifo data. + * @param[out] byte_index : Byte count which is incremented according to the + * of data. + * @param[out] uncomp_data : Uncompensated pressure and/or temperature data + * which is stored after parsing fifo buffer data. + * @param[out] parsed_frames : Total number of parsed frames. + * + * @return Result of API execution status. + * @retval zero -> Success / -ve value -> Error + */ +static uint8_t parse_fifo_data_frame(uint8_t header, struct bmp3_fifo *fifo, uint16_t *byte_index, + struct bmp3_uncomp_data *uncomp_data, uint8_t *parsed_frames); + +/*! + * @brief This internal API unpacks the FIFO data frame from the fifo buffer and + * fills the byte count, uncompensated pressure and/or temperature data. + * + * @param[out] byte_index : Byte count of fifo buffer. + * @param[in] fifo_buffer : FIFO buffer from where the temperature and pressure + * frames are unpacked. + * @param[out] uncomp_data : Uncompensated temperature and pressure data after + * unpacking from fifo buffer. + */ +static void unpack_temp_press_frame(uint16_t *byte_index, const uint8_t *fifo_buffer, + struct bmp3_uncomp_data *uncomp_data); + +/*! + * @brief This internal API unpacks the FIFO data frame from the fifo buffer and + * fills the byte count and uncompensated pressure data. + * + * @param[out] byte_index : Byte count of fifo buffer. + * @param[in] fifo_buffer : FIFO buffer from where the pressure frames are + * unpacked. + * @param[out] uncomp_data : Uncompensated pressure data after unpacking from + * fifo buffer. + */ +static void unpack_press_frame(uint16_t *byte_index, const uint8_t *fifo_buffer, + struct bmp3_uncomp_data *uncomp_data); + +/*! + * @brief This internal API unpacks the FIFO data frame from the fifo buffer and + * fills the byte count and uncompensated temperature data. + * + * @param[out] byte_index : Byte count of fifo buffer. + * @param[in] fifo_buffer : FIFO buffer from where the temperature frames + * are unpacked. + * @param[out] uncomp_data : Uncompensated temperature data after unpacking from + * fifo buffer. + */ +static void unpack_temp_frame(uint16_t *byte_index, const uint8_t *fifo_buffer, struct bmp3_uncomp_data *uncomp_data); + +/*! + * @brief This internal API unpacks the time frame from the fifo data buffer and + * fills the byte count and update the sensor time variable. + * + * @param[out] byte_index : Byte count of fifo buffer. + * @param[in] fifo_buffer : FIFO buffer from where the sensor time frames + * are unpacked. + * @param[out] sensor_time : Variable used to store the sensor time. + */ +static void unpack_time_frame(uint16_t *byte_index, const uint8_t *fifo_buffer, uint32_t *sensor_time); + +/*! + * @brief This internal API parses the FIFO buffer and gets the header info. + * + * @param[out] header : Variable used to store the fifo header data. + * @param[in] fifo_buffer : FIFO buffer from where the header data is retrieved. + * @param[out] byte_index : Byte count of fifo buffer. + */ +static void get_header_info(uint8_t *header, const uint8_t *fifo_buffer, uint16_t *byte_index); + +/*! + * @brief This internal API parses the FIFO data frame from the fifo buffer and + * fills uncompensated temperature and/or pressure data. + * + * @param[in] sensor_comp : Variable used to select either temperature or + * pressure or both while parsing the fifo frames. + * @param[in] fifo_buffer : FIFO buffer where the temperature or pressure or + * both the data to be parsed. + * @param[out] uncomp_data : Uncompensated temperature or pressure or both the + * data after unpacking from fifo buffer. + */ +static void parse_fifo_sensor_data(uint8_t sensor_comp, const uint8_t *fifo_buffer, + struct bmp3_uncomp_data *uncomp_data); + +/*! + * @brief This internal API resets the FIFO buffer, start index, + * parsed frame count, configuration change, configuration error and + * frame_not_available variables. + * + * @param[out] fifo : FIFO structure instance where the fifo related variables + * are reset. + */ +static void reset_fifo_index(struct bmp3_fifo *fifo); + +/*! + * @brief This API gets the command ready, data ready for pressure and + * temperature, power on reset status from the sensor. + * + * @param[in,out] dev : Structure instance of bmp3_dev + * + * @return Result of API execution status. + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t get_sensor_status(struct bmp3_dev *dev); + +/*! + * @brief This API gets the interrupt (fifo watermark, fifo full, data ready) + * status from the sensor. + * + * @param[in,out] dev : Structure instance of bmp3_dev + * + * @return Result of API execution status. + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t get_int_status(struct bmp3_dev *dev); + +/*! + * @brief This API gets the fatal, command and configuration error + * from the sensor. + * + * @param[in,out] dev : Structure instance of bmp3_dev + * + * @return Result of API execution status. + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t get_err_status(struct bmp3_dev *dev); + +/*! + * @brief This internal API converts the no. of frames required by the user to + * bytes so as to write in the watermark length register. + * + * @param[in] dev : Structure instance of bmp3_dev + * @param[out] watermark_len : Pointer variable which contains the watermark + * length. + * + * @return Result of API execution status. + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t convert_frames_to_bytes(uint16_t *watermark_len, const struct bmp3_dev *dev); + +/****************** Global Function Definitions *******************************/ +/*! + * @brief This API is the entry point. + * It performs the selection of I2C/SPI read mechanism according to the + * selected interface and reads the chip-id and calibration data of the sensor. + */ +int8_t bmp3_init(struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t chip_id = 0; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMP3_OK) { + /* Read mechanism according to selected interface */ + if (dev->intf != BMP3_I2C_INTF) { + /* If SPI interface is selected, read extra byte */ + dev->dummy_byte = 1; + } else { + /* If I2C interface is selected, no need to read + extra byte */ + dev->dummy_byte = 0; + } + /* Read the chip-id of bmp3 sensor */ + rslt = bmp3_get_regs(BMP3_CHIP_ID_ADDR, &chip_id, 1, dev); + /* Proceed if everything is fine until now */ + if (rslt == BMP3_OK) { + /* Check for chip id validity */ + if (chip_id == BMP3_CHIP_ID) { + dev->chip_id = chip_id; + /* Reset the sensor */ + rslt = bmp3_soft_reset(dev); + if (rslt == BMP3_OK) { + /* Read the calibration data */ + rslt = get_calib_data(dev); + } + } else { + rslt = BMP3_E_DEV_NOT_FOUND; + } + } + } + + return rslt; +} + +/*! + * @brief This API reads the data from the given register address of the sensor. + */ +int8_t bmp3_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, const struct bmp3_dev *dev) +{ + int8_t rslt; + uint16_t temp_len = len + dev->dummy_byte; + uint16_t i; + uint8_t temp_buff[len + dev->dummy_byte]; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMP3_OK) { + /* If interface selected is SPI */ + if (dev->intf != BMP3_I2C_INTF) { + reg_addr = reg_addr | 0x80; + /* Read the data from the register */ + rslt = dev->read(dev->dev_id, reg_addr, temp_buff, temp_len); + + for (i = 0; i < len; i++) + reg_data[i] = temp_buff[i + dev->dummy_byte]; + } else { + /* Read the data using I2C */ + rslt = dev->read(dev->dev_id, reg_addr, reg_data, len); + } + /* Check for communication error */ + if (rslt != BMP3_OK) + rslt = BMP3_E_COMM_FAIL; + } + + return rslt; +} + +/*! + * @brief This API writes the given data to the register address + * of the sensor. + */ +int8_t bmp3_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, const struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t temp_buff[len * 2]; + uint16_t temp_len; + uint8_t reg_addr_cnt; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Check for arguments validity */ + if ((rslt == BMP3_OK) && (reg_addr != NULL) && (reg_data != NULL)) { + if (len != 0) { + temp_buff[0] = reg_data[0]; + /* If interface selected is SPI */ + if (dev->intf == BMP3_SPI_INTF) { + for (reg_addr_cnt = 0; reg_addr_cnt < len; reg_addr_cnt++) + reg_addr[reg_addr_cnt] = reg_addr[reg_addr_cnt] & 0x7F; + } + /* Burst write mode */ + if (len > 1) { + /* Interleave register address w.r.t data for + burst write*/ + interleave_reg_addr(reg_addr, temp_buff, reg_data, len); + temp_len = len * 2; + } else { + temp_len = len; + } + rslt = dev->write(dev->dev_id, reg_addr[0], temp_buff, temp_len); + /* Check for communication error */ + if (rslt != BMP3_OK) + rslt = BMP3_E_COMM_FAIL; + } else { + rslt = BMP3_E_INVALID_LEN; + } + } else { + rslt = BMP3_E_NULL_PTR; + } + + + return rslt; +} + +/*! + * @brief This API sets the power control(pressure enable and + * temperature enable), over sampling, odr and filter + * settings in the sensor. + */ +int8_t bmp3_set_sensor_settings(uint32_t desired_settings, struct bmp3_dev *dev) +{ + int8_t rslt; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMP3_OK) { + if (are_settings_changed(POWER_CNTL, desired_settings)) { + /* Set the power control settings */ + rslt = set_pwr_ctrl_settings(desired_settings, dev); + } + if (are_settings_changed(ODR_FILTER, desired_settings) && (!rslt)) { + /* Set the over sampling, odr and filter settings*/ + rslt = set_odr_filter_settings(desired_settings, dev); + } + if (are_settings_changed(INT_CTRL, desired_settings) && (!rslt)) { + /* Set the interrupt control settings */ + rslt = set_int_ctrl_settings(desired_settings, dev); + } + if (are_settings_changed(ADV_SETT, desired_settings) && (!rslt)) { + /* Set the advance settings */ + rslt = set_advance_settings(desired_settings, dev); + } + } + + return rslt; +} + +/*! + * @brief This API gets the power control(power mode, pressure enable and + * temperature enable), over sampling, odr, filter, interrupt control and + * advance settings from the sensor. + */ +int8_t bmp3_get_sensor_settings(struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t settings_data[BMP3_GEN_SETT_LEN]; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMP3_OK) { + rslt = bmp3_get_regs(BMP3_INT_CTRL_ADDR, settings_data, BMP3_GEN_SETT_LEN, dev); + + if (rslt == BMP3_OK) { + /* Parse the settings data */ + parse_sett_data(settings_data, dev); + } + } + + return rslt; +} + +/*! + * @brief This API sets the fifo_config_1(fifo_mode, + * fifo_stop_on_full, fifo_time_en, fifo_press_en, fifo_temp_en), + * fifo_config_2(fifo_subsampling, data_select) and int_ctrl(fwtm_en, ffull_en) + * settings in the sensor. + */ +int8_t bmp3_set_fifo_settings(uint16_t desired_settings, const struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t fifo_sett[5]; + uint8_t len = 3; + uint8_t reg_addr[3] = {BMP3_FIFO_CONFIG_1_ADDR, BMP3_FIFO_CONFIG_1_ADDR+1, BMP3_FIFO_CONFIG_1_ADDR+2}; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if ((rslt == BMP3_OK) && (dev->fifo != NULL)) { + rslt = bmp3_get_regs(reg_addr[0], fifo_sett, len, dev); + + if (rslt == BMP3_OK) { + if (are_settings_changed(FIFO_CONFIG_1, desired_settings)) { + /* Fill the FIFO config 1 register data */ + fill_fifo_config_1(desired_settings, &fifo_sett[0], &dev->fifo->settings); + } + if (are_settings_changed(desired_settings, FIFO_CONFIG_2)) { + /* Fill the FIFO config 2 register data */ + fill_fifo_config_2(desired_settings, &fifo_sett[1], &dev->fifo->settings); + } + if (are_settings_changed(desired_settings, FIFO_INT_CTRL)) { + /* Fill the FIFO interrupt ctrl register data */ + fill_fifo_int_ctrl(desired_settings, &fifo_sett[2], &dev->fifo->settings); + } + /* Write the FIFO settings in the sensor */ + rslt = bmp3_set_regs(reg_addr, fifo_sett, len, dev); + } + } else { + rslt = BMP3_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API gets the fifo_config_1(fifo_mode, + * fifo_stop_on_full, fifo_time_en, fifo_press_en, fifo_temp_en), + * fifo_config_2(fifo_subsampling, data_select) and int_ctrl(fwtm_en, ffull_en) + * settings from the sensor. + */ +int8_t bmp3_get_fifo_settings(const struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t fifo_sett[3]; + uint8_t len = 3; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if ((rslt == BMP3_OK) && (dev->fifo != NULL)) { + rslt = bmp3_get_regs(BMP3_FIFO_CONFIG_1_ADDR, fifo_sett, len, dev); + /* Parse the fifo settings */ + parse_fifo_settings(fifo_sett, &dev->fifo->settings); + } else { + rslt = BMP3_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API gets the fifo data from the sensor. + */ +int8_t bmp3_get_fifo_data(const struct bmp3_dev *dev) +{ + int8_t rslt; + uint16_t fifo_len; + struct bmp3_fifo *fifo = dev->fifo; + + rslt = null_ptr_check(dev); + + if ((rslt == BMP3_OK) && (fifo != NULL)) { + reset_fifo_index(dev->fifo); + /* Get the total no of bytes available in FIFO */ + rslt = bmp3_get_fifo_length(&fifo_len, dev); + /* For sensor time frame */ + if (dev->fifo->settings.time_en == TRUE) + fifo_len = fifo_len + 4; + /* Update the fifo length in the fifo structure */ + dev->fifo->data.byte_count = fifo_len; + if (rslt == BMP3_OK) { + /* Read the fifo data */ + rslt = bmp3_get_regs(BMP3_FIFO_DATA_ADDR, fifo->data.buffer, fifo_len, dev); + } + } else { + rslt = BMP3_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API sets the fifo watermark length according to the frames count + * set by the user in the device structure. Refer below for usage. + */ +int8_t bmp3_set_fifo_watermark(const struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t reg_data[2]; + uint8_t reg_addr[2] = {BMP3_FIFO_WM_ADDR, BMP3_FIFO_WM_ADDR+1}; + uint16_t watermark_len; + + rslt = null_ptr_check(dev); + + if ((rslt == BMP3_OK) && (dev->fifo != NULL)) { + rslt = convert_frames_to_bytes(&watermark_len, dev); + if (rslt == BMP3_OK) { + reg_data[0] = BMP3_GET_LSB(watermark_len); + reg_data[1] = BMP3_GET_MSB(watermark_len) & 0x01; + rslt = bmp3_set_regs(reg_addr, reg_data, 2, dev); + } + } + + return rslt; +} + +/*! + * @brief This API extracts the temperature and/or pressure data from the FIFO + * data which is already read from the fifo. + */ +int8_t bmp3_extract_fifo_data(struct bmp3_data *data, struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t header; + uint16_t byte_index = dev->fifo->data.start_idx; + uint8_t parsed_frames = 0; + uint8_t t_p_frame; + struct bmp3_uncomp_data uncomp_data; + + rslt = null_ptr_check(dev); + + if ((rslt == BMP3_OK) && (dev->fifo != NULL) && (data != NULL)) { + while ((parsed_frames < (dev->fifo->data.req_frames)) && (byte_index < dev->fifo->data.byte_count)) { + get_header_info(&header, dev->fifo->data.buffer, &byte_index); + t_p_frame = parse_fifo_data_frame(header, dev->fifo, &byte_index, &uncomp_data, &parsed_frames); + /* If the frame is pressure and/or temperature data */ + if (t_p_frame != FALSE) { + /* Compensate temperature and pressure data */ + rslt = compensate_data(t_p_frame, &uncomp_data, &data[parsed_frames-1], + &dev->calib_data); + } + } + /* Check if any frames are parsed in FIFO */ + if (parsed_frames != 0) { + /* Update the bytes parsed in the device structure */ + dev->fifo->data.start_idx = byte_index; + dev->fifo->data.parsed_frames += parsed_frames; + } else { + /* No frames are there to parse. It is time to + read the FIFO, if more frames are needed */ + dev->fifo->data.frame_not_available = TRUE; + } + } else { + rslt = BMP3_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API gets the command ready, data ready for pressure and + * temperature and interrupt (fifo watermark, fifo full, data ready) and + * error status from the sensor. + */ +int8_t bmp3_get_status(struct bmp3_dev *dev) +{ + int8_t rslt; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + + if (rslt == BMP3_OK) { + rslt = get_sensor_status(dev); + /* Proceed further if the earlier operation is fine */ + if (rslt == BMP3_OK) { + rslt = get_int_status(dev); + /* Proceed further if the earlier operation is fine */ + if (rslt == BMP3_OK) { + /* Get the error status */ + rslt = get_err_status(dev); + } + } + } + + return rslt; +} + +/*! + * @brief This API gets the fifo length from the sensor. + */ +int8_t bmp3_get_fifo_length(uint16_t *fifo_length, const struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t reg_data[2]; + + rslt = null_ptr_check(dev); + + if (rslt == BMP3_OK) { + rslt = bmp3_get_regs(BMP3_FIFO_LENGTH_ADDR, reg_data, 2, dev); + /* Proceed if read from register is fine */ + if (rslt == BMP3_OK) { + /* Update the fifo length */ + *fifo_length = BMP3_CONCAT_BYTES(reg_data[1], reg_data[0]); + } + } + + return rslt; +} + +/*! + * @brief This API performs the soft reset of the sensor. + */ +int8_t bmp3_soft_reset(const struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t reg_addr = BMP3_CMD_ADDR; + /* 0xB6 is the soft reset command */ + uint8_t soft_rst_cmd = 0xB6; + uint8_t cmd_rdy_status; + uint8_t cmd_err_status; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + /* Proceed if null check is fine */ + if (rslt == BMP3_OK) { + /* Check for command ready status */ + rslt = bmp3_get_regs(BMP3_SENS_STATUS_REG_ADDR, &cmd_rdy_status, 1, dev); + /* Device is ready to accept new command */ + if ((cmd_rdy_status & BMP3_CMD_RDY) && (rslt == BMP3_OK)) { + /* Write the soft reset command in the sensor */ + rslt = bmp3_set_regs(®_addr, &soft_rst_cmd, 1, dev); + /* Proceed if everything is fine until now */ + if (rslt == BMP3_OK) { + /* Wait for 2 ms */ + dev->delay_ms(2); + /* Read for command error status */ + rslt = bmp3_get_regs(BMP3_ERR_REG_ADDR, &cmd_err_status, 1, dev); + /* check for command error status */ + if ((cmd_err_status & BMP3_CMD_ERR) || (rslt != BMP3_OK)) { + /* Command not written hence return + error */ + rslt = BMP3_E_CMD_EXEC_FAILED; + } + } + } else { + rslt = BMP3_E_CMD_EXEC_FAILED; + } + } + + return rslt; +} + +/*! + * @brief This API sets the power mode of the sensor. + */ +int8_t bmp3_set_op_mode(struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t last_set_mode; + uint8_t curr_mode = dev->settings.op_mode; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + + if (rslt == BMP3_OK) { + rslt = bmp3_get_op_mode(&last_set_mode, dev); + /* If the sensor is not in sleep mode put the device to sleep + mode */ + if (last_set_mode != BMP3_SLEEP_MODE) { + /* Device should be put to sleep before transiting to + forced mode or normal mode */ + rslt = put_device_to_sleep(dev); + /* Give some time for device to go into sleep mode */ + dev->delay_ms(5); + } + /* Set the power mode */ + if (rslt == BMP3_OK) { + if (curr_mode == BMP3_NORMAL_MODE) { + /* Set normal mode and validate + necessary settings */ + rslt = set_normal_mode(dev); + } else if (curr_mode == BMP3_FORCED_MODE) { + /* Set forced mode */ + rslt = write_power_mode(dev); + } + } + } + + return rslt; +} + +/*! + * @brief This API gets the power mode of the sensor. + */ +int8_t bmp3_get_op_mode(uint8_t *op_mode, const struct bmp3_dev *dev) +{ + int8_t rslt; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + + if (rslt == BMP3_OK) { + /* Read the power mode register */ + rslt = bmp3_get_regs(BMP3_PWR_CTRL_ADDR, op_mode, 1, dev); + /* Assign the power mode in the device structure */ + *op_mode = BMP3_GET_BITS(*op_mode, BMP3_OP_MODE); + } + + return rslt; +} + +/*! + * @brief This API reads the pressure, temperature or both data from the + * sensor, compensates the data and store it in the bmp3_data structure + * instance passed by the user. + */ +int8_t bmp3_get_sensor_data(uint8_t sensor_comp, struct bmp3_data *comp_data, struct bmp3_dev *dev) +{ + int8_t rslt; + /* Array to store the pressure and temperature data read from + the sensor */ + uint8_t reg_data[BMP3_P_T_DATA_LEN] = {0}; + struct bmp3_uncomp_data uncomp_data = {0}; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + + if ((rslt == BMP3_OK) && (comp_data != NULL)) { + /* Read the pressure and temperature data from the sensor */ + rslt = bmp3_get_regs(BMP3_DATA_ADDR, reg_data, BMP3_P_T_DATA_LEN, dev); + + if (rslt == BMP3_OK) { + /* Parse the read data from the sensor */ + parse_sensor_data(reg_data, &uncomp_data); + /* Compensate the pressure/temperature/both data read + from the sensor */ + rslt = compensate_data(sensor_comp, &uncomp_data, comp_data, &dev->calib_data); + } + } else { + rslt = BMP3_E_NULL_PTR; + } + + return rslt; +} + +/****************** Static Function Definitions *******************************/ +/*! + * @brief This internal API converts the no. of frames required by the user to + * bytes so as to write in the watermark length register. + */ +static int8_t convert_frames_to_bytes(uint16_t *watermark_len, const struct bmp3_dev *dev) +{ + int8_t rslt = BMP3_OK; + + if ((dev->fifo->data.req_frames > 0) && (dev->fifo->data.req_frames <= BMP3_FIFO_MAX_FRAMES)) { + if (dev->fifo->settings.press_en && dev->fifo->settings.temp_en) { + /* Multiply with pressure and temperature header len */ + *watermark_len = dev->fifo->data.req_frames * BMP3_P_AND_T_HEADER_DATA_LEN; + } else if (dev->fifo->settings.temp_en || dev->fifo->settings.press_en) { + /* Multiply with pressure or temperature header len */ + *watermark_len = dev->fifo->data.req_frames * BMP3_P_OR_T_HEADER_DATA_LEN; + } else { + /* No sensor is enabled */ + rslt = BMP3_W_SENSOR_NOT_ENABLED; + } + } else { + /* Required frame count is zero, which is invalid */ + rslt = BMP3_W_INVALID_FIFO_REQ_FRAME_CNT; + } + + return rslt; +} +/*! + * @brief This internal API resets the FIFO buffer, start index, + * parsed frame count, configuration change, configuration error and + * frame_not_available variables. + */ +static void reset_fifo_index(struct bmp3_fifo *fifo) +{ + /* Loop variable */ + uint16_t i; + + for (i = 0; i < 512; i++) { + /* Initialize data buffer to zero */ + fifo->data.buffer[i] = 0; + } + fifo->data.byte_count = 0; + fifo->data.start_idx = 0; + fifo->data.parsed_frames = 0; + fifo->data.config_change = 0; + fifo->data.config_err = 0; + fifo->data.frame_not_available = 0; +} + +/*! + * @brief This internal API parse the FIFO data frame from the fifo buffer and + * fills the byte count, uncompensated pressure and/or temperature data and no + * of parsed frames. + */ +static uint8_t parse_fifo_data_frame(uint8_t header, struct bmp3_fifo *fifo, uint16_t *byte_index, + struct bmp3_uncomp_data *uncomp_data, uint8_t *parsed_frames) +{ + uint8_t t_p_frame = 0; + + switch (header) { + case FIFO_TEMP_PRESS_FRAME: + unpack_temp_press_frame(byte_index, fifo->data.buffer, uncomp_data); + *parsed_frames = *parsed_frames + 1; + t_p_frame = BMP3_PRESS | BMP3_TEMP; + break; + + case FIFO_TEMP_FRAME: + unpack_temp_frame(byte_index, fifo->data.buffer, uncomp_data); + *parsed_frames = *parsed_frames + 1; + t_p_frame = BMP3_TEMP; + break; + + case FIFO_PRESS_FRAME: + unpack_press_frame(byte_index, fifo->data.buffer, uncomp_data); + *parsed_frames = *parsed_frames + 1; + t_p_frame = BMP3_PRESS; + break; + + case FIFO_TIME_FRAME: + unpack_time_frame(byte_index, fifo->data.buffer, &fifo->data.sensor_time); + break; + + case FIFO_CONFIG_CHANGE: + fifo->data.config_change = 1; + *byte_index = *byte_index + 1; + break; + + case FIFO_ERROR_FRAME: + fifo->data.config_err = 1; + *byte_index = *byte_index + 1; + break; + + default: + fifo->data.config_err = 1; + *byte_index = *byte_index + 1; + break; + + } + + return t_p_frame; +} + +/*! + * @brief This internal API unpacks the FIFO data frame from the fifo buffer and + * fills the byte count, uncompensated pressure and/or temperature data. + */ +static void unpack_temp_press_frame(uint16_t *byte_index, const uint8_t *fifo_buffer, + struct bmp3_uncomp_data *uncomp_data) +{ + parse_fifo_sensor_data((BMP3_PRESS | BMP3_TEMP), &fifo_buffer[*byte_index], uncomp_data); + *byte_index = *byte_index + BMP3_P_T_DATA_LEN; +} + +/*! + * @brief This internal API unpacks the FIFO data frame from the fifo buffer and + * fills the byte count and uncompensated temperature data. + */ +static void unpack_temp_frame(uint16_t *byte_index, const uint8_t *fifo_buffer, struct bmp3_uncomp_data *uncomp_data) +{ + parse_fifo_sensor_data(BMP3_TEMP, &fifo_buffer[*byte_index], uncomp_data); + *byte_index = *byte_index + BMP3_T_DATA_LEN; +} + +/*! + * @brief This internal API unpacks the FIFO data frame from the fifo buffer and + * fills the byte count and uncompensated pressure data. + */ +static void unpack_press_frame(uint16_t *byte_index, const uint8_t *fifo_buffer, struct bmp3_uncomp_data *uncomp_data) +{ + parse_fifo_sensor_data(BMP3_PRESS, &fifo_buffer[*byte_index], uncomp_data); + *byte_index = *byte_index + BMP3_P_DATA_LEN; +} + +/*! + * @brief This internal API unpacks the time frame from the fifo data buffer and + * fills the byte count and update the sensor time variable. + */ +static void unpack_time_frame(uint16_t *byte_index, const uint8_t *fifo_buffer, uint32_t *sensor_time) +{ + uint16_t index = *byte_index; + uint32_t xlsb = fifo_buffer[index]; + uint32_t lsb = ((uint32_t)fifo_buffer[index + 1]) << 8; + uint32_t msb = ((uint32_t)fifo_buffer[index + 2]) << 16; + + *sensor_time = msb | lsb | xlsb; + *byte_index = *byte_index + BMP3_SENSOR_TIME_LEN; +} + +/*! + * @brief This internal API parses the FIFO data frame from the fifo buffer and + * fills uncompensated temperature and/or pressure data. + */ +static void parse_fifo_sensor_data(uint8_t sensor_comp, const uint8_t *fifo_buffer, + struct bmp3_uncomp_data *uncomp_data) +{ + /* Temporary variables to store the sensor data */ + uint32_t data_xlsb; + uint32_t data_lsb; + uint32_t data_msb; + + /* Store the parsed register values for temperature data */ + data_xlsb = (uint32_t)fifo_buffer[0]; + data_lsb = (uint32_t)fifo_buffer[1] << 8; + data_msb = (uint32_t)fifo_buffer[2] << 16; + + if (sensor_comp == BMP3_TEMP) { + /* Update uncompensated temperature */ + uncomp_data->temperature = data_msb | data_lsb | data_xlsb; + } + if (sensor_comp == BMP3_PRESS) { + /* Update uncompensated pressure */ + uncomp_data->pressure = data_msb | data_lsb | data_xlsb; + } + if (sensor_comp == (BMP3_TEMP | BMP3_PRESS)) { + uncomp_data->temperature = data_msb | data_lsb | data_xlsb; + /* Store the parsed register values for pressure data */ + data_xlsb = (uint32_t)fifo_buffer[3]; + data_lsb = (uint32_t)fifo_buffer[4] << 8; + data_msb = (uint32_t)fifo_buffer[5] << 16; + uncomp_data->pressure = data_msb | data_lsb | data_xlsb; + } +} + +/*! + * @brief This internal API parses the FIFO buffer and gets the header info. + */ +static void get_header_info(uint8_t *header, const uint8_t *fifo_buffer, uint16_t *byte_index) +{ + *header = fifo_buffer[*byte_index]; + *byte_index = *byte_index + 1; +} + + +/*! + * @brief This internal API sets the normal mode in the sensor. + */ +static int8_t set_normal_mode(struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t conf_err_status; + + rslt = validate_normal_mode_settings(dev); + /* If osr and odr settings are proper then write the power mode */ + if (rslt == BMP3_OK) { + rslt = write_power_mode(dev); + /* check for configuration error */ + if (rslt == BMP3_OK) { + /* Read the configuration error status */ + rslt = bmp3_get_regs(BMP3_ERR_REG_ADDR, &conf_err_status, 1, dev); + /* Check if conf. error flag is set */ + if (rslt == BMP3_OK) { + if (conf_err_status & BMP3_CONF_ERR) { + /* Osr and odr configuration is + not proper */ + rslt = BMP3_E_CONFIGURATION_ERR; + } + } + } + } + + return rslt; +} + +/*! + * @brief This internal API writes the power mode in the sensor. + */ +static int8_t write_power_mode(const struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t reg_addr = BMP3_PWR_CTRL_ADDR; + uint8_t op_mode = dev->settings.op_mode; + /* Temporary variable to store the value read from op-mode register */ + uint8_t op_mode_reg_val; + + /* Read the power mode register */ + rslt = bmp3_get_regs(reg_addr, &op_mode_reg_val, 1, dev); + /* Set the power mode */ + if (rslt == BMP3_OK) { + op_mode_reg_val = BMP3_SET_BITS(op_mode_reg_val, BMP3_OP_MODE, op_mode); + /* Write the power mode in the register */ + rslt = bmp3_set_regs(®_addr, &op_mode_reg_val, 1, dev); + } + + return rslt; +} + +/*! + * @brief This internal API puts the device to sleep mode. + */ +static int8_t put_device_to_sleep(const struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t reg_addr = BMP3_PWR_CTRL_ADDR; + /* Temporary variable to store the value read from op-mode register */ + uint8_t op_mode_reg_val; + + rslt = bmp3_get_regs(BMP3_PWR_CTRL_ADDR, &op_mode_reg_val, 1, dev); + + if (rslt == BMP3_OK) { + /* Set the power mode */ + op_mode_reg_val = op_mode_reg_val & (~(BMP3_OP_MODE_MSK)); + + /* Write the power mode in the register */ + rslt = bmp3_set_regs(®_addr, &op_mode_reg_val, 1, dev); + } + + return rslt; +} + +/*! + * @brief This internal API validate the normal mode settings of the sensor. + */ +static int8_t validate_normal_mode_settings(struct bmp3_dev *dev) +{ + int8_t rslt; + + rslt = get_odr_filter_settings(dev); + + if (rslt == BMP3_OK) + rslt = validate_osr_and_odr_settings(dev); + + return rslt; +} + +/*! + * @brief This internal API reads the calibration data from the sensor, parse + * it then compensates it and store in the device structure. + */ +static int8_t get_calib_data(struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t reg_addr = BMP3_CALIB_DATA_ADDR; + /* Array to store calibration data */ + uint8_t calib_data[BMP3_CALIB_DATA_LEN] = {0}; + + /* Read the calibration data from the sensor */ + rslt = bmp3_get_regs(reg_addr, calib_data, BMP3_CALIB_DATA_LEN, dev); + /* Parse calibration data and store it in device structure */ + parse_calib_data(calib_data, dev); + + return rslt; +} + + + +/*! + * @brief This internal API interleaves the register address between the + * register data buffer for burst write operation. + */ +static void interleave_reg_addr(const uint8_t *reg_addr, uint8_t *temp_buff, const uint8_t *reg_data, uint8_t len) +{ + uint8_t index; + + for (index = 1; index < len; index++) { + temp_buff[(index * 2) - 1] = reg_addr[index]; + temp_buff[index * 2] = reg_data[index]; + } +} + +/*! + * @brief This internal API parse the power control(power mode, pressure enable + * and temperature enable), over sampling, odr, filter, interrupt control and + * advance settings and store in the device structure. + */ +static void parse_sett_data(const uint8_t *reg_data, struct bmp3_dev *dev) +{ + /* Parse interrupt control settings and store in device structure */ + parse_int_ctrl_settings(®_data[0], &dev->settings.int_settings); + /* Parse advance settings and store in device structure */ + parse_advance_settings(®_data[1], &dev->settings.adv_settings); + /* Parse power control settings and store in device structure */ + parse_pwr_ctrl_settings(®_data[2], &dev->settings); + /* Parse odr and filter settings and store in device structure */ + parse_odr_filter_settings(®_data[3], &dev->settings.odr_filter); + +} + +/*! + * @brief This internal API parse the interrupt control(output mode, level, + * latch and data ready) settings and store in the device structure. + */ +static void parse_int_ctrl_settings(const uint8_t *reg_data, struct bmp3_int_ctrl_settings *settings) +{ + settings->output_mode = BMP3_GET_BITS_POS_0(*reg_data, BMP3_INT_OUTPUT_MODE); + settings->level = BMP3_GET_BITS(*reg_data, BMP3_INT_LEVEL); + settings->latch = BMP3_GET_BITS(*reg_data, BMP3_INT_LATCH); + settings->drdy_en = BMP3_GET_BITS(*reg_data, BMP3_INT_DRDY_EN); +} + + +static void parse_advance_settings(const uint8_t *reg_data, struct bmp3_adv_settings *settings) +{ + settings->i2c_wdt_en = BMP3_GET_BITS(*reg_data, BMP3_I2C_WDT_EN); + settings->i2c_wdt_sel = BMP3_GET_BITS(*reg_data, BMP3_I2C_WDT_SEL); +} + +/*! + * @brief This internal API parse the power control(power mode, pressure enable + * and temperature enable) settings and store in the device structure. + */ +static void parse_pwr_ctrl_settings(const uint8_t *reg_data, struct bmp3_settings *settings) +{ + settings->op_mode = BMP3_GET_BITS(*reg_data, BMP3_OP_MODE); + settings->press_en = BMP3_GET_BITS_POS_0(*reg_data, BMP3_PRESS_EN); + settings->temp_en = BMP3_GET_BITS(*reg_data, BMP3_TEMP_EN); +} + +/*! + * @brief This internal API parse the over sampling, odr and filter + * settings and store in the device structure. + */ +static void parse_odr_filter_settings(const uint8_t *reg_data, struct bmp3_odr_filter_settings *settings) +{ + uint8_t index = 0; + + /* Odr and filter settings index starts from one (0x1C register) */ + settings->press_os = BMP3_GET_BITS_POS_0(reg_data[index], BMP3_PRESS_OS); + settings->temp_os = BMP3_GET_BITS(reg_data[index], BMP3_TEMP_OS); + + /* Move index to 0x1D register */ + index++; + settings->odr = BMP3_GET_BITS_POS_0(reg_data[index], BMP3_ODR); + + /* Move index to 0x1F register */ + index = index + 2; + settings->iir_filter = BMP3_GET_BITS(reg_data[index], BMP3_IIR_FILTER); +} + +/*! + * @brief This API sets the pressure enable and temperature enable + * settings of the sensor. + */ +static int8_t set_pwr_ctrl_settings(uint32_t desired_settings, const struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t reg_addr = BMP3_PWR_CTRL_ADDR; + uint8_t reg_data; + + rslt = bmp3_get_regs(reg_addr, ®_data, 1, dev); + + if (rslt == BMP3_OK) { + if (desired_settings & BMP3_PRESS_EN_SEL) { + /* Set the pressure enable settings in the + register variable */ + reg_data = BMP3_SET_BITS_POS_0(reg_data, BMP3_PRESS_EN, dev->settings.press_en); + } + if (desired_settings & BMP3_TEMP_EN_SEL) { + /* Set the temperature enable settings in the + register variable */ + reg_data = BMP3_SET_BITS(reg_data, BMP3_TEMP_EN, dev->settings.temp_en); + } + /* Write the power control settings in the register */ + rslt = bmp3_set_regs(®_addr, ®_data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This internal API sets the over sampling, odr and filter settings + * of the sensor based on the settings selected by the user. + */ +static int8_t set_odr_filter_settings(uint32_t desired_settings, struct bmp3_dev *dev) +{ + int8_t rslt; + /* No of registers to be configured is 3*/ + uint8_t reg_addr[3] = {0}; + /* No of register data to be read is 4 */ + uint8_t reg_data[4]; + uint8_t len = 0; + + rslt = bmp3_get_regs(BMP3_OSR_ADDR, reg_data, 4, dev); + + if (rslt == BMP3_OK) { + if (are_settings_changed((BMP3_PRESS_OS_SEL | BMP3_TEMP_OS_SEL), desired_settings)) { + /* Fill the over sampling register address and + register data to be written in the sensor */ + fill_osr_data(desired_settings, reg_addr, reg_data, &len, dev); + } + if (are_settings_changed(BMP3_ODR_SEL, desired_settings)) { + /* Fill the output data rate register address and + register data to be written in the sensor */ + fill_odr_data(reg_addr, reg_data, &len, dev); + } + if (are_settings_changed(BMP3_IIR_FILTER_SEL, desired_settings)) { + /* Fill the iir filter register address and + register data to be written in the sensor */ + fill_filter_data(reg_addr, reg_data, &len, dev); + } + if (dev->settings.op_mode == BMP3_NORMAL_MODE) { + /* For normal mode, osr and odr settings should + be proper */ + rslt = validate_osr_and_odr_settings(dev); + } + if (rslt == BMP3_OK) { + /* Burst write the over sampling, odr and filter + settings in the register */ + rslt = bmp3_set_regs(reg_addr, reg_data, len, dev); + } + } + + return rslt; +} + +/*! +* @brief This internal API sets the interrupt control (output mode, level, +* latch and data ready) settings of the sensor based on the settings +* selected by the user. +*/ +static int8_t set_int_ctrl_settings(uint32_t desired_settings, const struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + uint8_t reg_addr; + struct bmp3_int_ctrl_settings int_settings; + + reg_addr = BMP3_INT_CTRL_ADDR; + rslt = bmp3_get_regs(reg_addr, ®_data, 1, dev); + + if (rslt == BMP3_OK) { + int_settings = dev->settings.int_settings; + + if (desired_settings & BMP3_OUTPUT_MODE_SEL) { + /* Set the interrupt output mode bits */ + reg_data = BMP3_SET_BITS_POS_0(reg_data, BMP3_INT_OUTPUT_MODE, int_settings.output_mode); + } + if (desired_settings & BMP3_LEVEL_SEL) { + /* Set the interrupt level bits */ + reg_data = BMP3_SET_BITS(reg_data, BMP3_INT_LEVEL, int_settings.level); + } + if (desired_settings & BMP3_LATCH_SEL) { + /* Set the interrupt latch bits */ + reg_data = BMP3_SET_BITS(reg_data, BMP3_INT_LATCH, int_settings.latch); + } + if (desired_settings & BMP3_DRDY_EN_SEL) { + /* Set the interrupt data ready bits */ + reg_data = BMP3_SET_BITS(reg_data, BMP3_INT_DRDY_EN, int_settings.drdy_en); + } + + rslt = bmp3_set_regs(®_addr, ®_data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This internal API sets the advance (i2c_wdt_en, i2c_wdt_sel) + * settings of the sensor based on the settings selected by the user. + */ +static int8_t set_advance_settings(uint32_t desired_settings, const struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t reg_addr; + uint8_t reg_data; + struct bmp3_adv_settings adv_settings = dev->settings.adv_settings; + + reg_addr = BMP3_IF_CONF_ADDR; + rslt = bmp3_get_regs(reg_addr, ®_data, 1, dev); + + if (rslt == BMP3_OK) { + if (desired_settings & BMP3_I2C_WDT_EN_SEL) { + /* Set the i2c watch dog enable bits */ + reg_data = BMP3_SET_BITS(reg_data, BMP3_I2C_WDT_EN, adv_settings.i2c_wdt_en); + } + if (desired_settings & BMP3_I2C_WDT_SEL_SEL) { + /* Set the i2c watch dog select bits */ + reg_data = BMP3_SET_BITS(reg_data, BMP3_I2C_WDT_SEL, adv_settings.i2c_wdt_sel); + } + + rslt = bmp3_set_regs(®_addr, ®_data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This internal API gets the over sampling, odr and filter settings + * of the sensor. + */ +static int8_t get_odr_filter_settings(struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t reg_data[4]; + + /* Read data beginning from 0x1C register */ + rslt = bmp3_get_regs(BMP3_OSR_ADDR, reg_data, 4, dev); + /* Parse the read data and store it in dev structure */ + parse_odr_filter_settings(reg_data, &dev->settings.odr_filter); + + return rslt; +} + +/*! + * @brief This internal API validate the over sampling, odr settings of the + * sensor. + */ +static int8_t validate_osr_and_odr_settings(const struct bmp3_dev *dev) +{ + int8_t rslt; + uint16_t meas_t = 0; + /* Odr values in milli secs */ + uint32_t odr[18] = {5, 10, 20, 40, 80, 160, 320, 640, 1280, 2560, 5120, 10240, + 20480, 40960, 81920, 163840, 327680, 655360}; + + if (dev->settings.press_en) { + /* Calculate the pressure measurement duration */ + meas_t = calculate_press_meas_time(dev); + } + if (dev->settings.temp_en) { + /* Calculate the temperature measurement duration */ + meas_t += calculate_temp_meas_time(dev); + } + rslt = verify_meas_time_and_odr_duration(meas_t, odr[dev->settings.odr_filter.odr]); + + return rslt; +} + +/*! + * @brief This internal API checks whether the measurement time and odr duration + * of the sensor are proper. + */ +static int8_t verify_meas_time_and_odr_duration(uint16_t meas_t, uint32_t odr_duration) +{ + int8_t rslt; + + if (meas_t < odr_duration) { + /* If measurement duration is less than odr duration + then osr and odr settings are fine */ + rslt = BMP3_OK; + } else { + /* Osr and odr settings are not proper */ + rslt = BMP3_E_INVALID_ODR_OSR_SETTINGS; + } + + return rslt; +} + +/*! + * @brief This internal API calculates the pressure measurement duration of the + * sensor. + */ +static uint16_t calculate_press_meas_time(const struct bmp3_dev *dev) +{ + uint16_t press_meas_t; + struct bmp3_odr_filter_settings odr_filter = dev->settings.odr_filter; +#ifdef FLOATING_POINT_COMPENSATION + float base = 2.0; + float partial_out; +#else + uint8_t base = 2; + uint32_t partial_out; +#endif + + partial_out = bmp3_pow(base, odr_filter.press_os); + press_meas_t = (uint16_t)(BMP3_PRESS_SETTLE_TIME + partial_out * BMP3_ADC_CONV_TIME); + /* convert into mill seconds */ + press_meas_t = press_meas_t / 1000; + + return press_meas_t; +} + +/*! + * @brief This internal API calculates the temperature measurement duration of + * the sensor. + */ +static uint16_t calculate_temp_meas_time(const struct bmp3_dev *dev) +{ + uint16_t temp_meas_t; + struct bmp3_odr_filter_settings odr_filter = dev->settings.odr_filter; +#ifdef FLOATING_POINT_COMPENSATION + float base = 2.0; + float partial_out; +#else + uint8_t base = 2; + uint32_t partial_out; +#endif + + partial_out = bmp3_pow(base, odr_filter.temp_os); + temp_meas_t = (uint16_t)(BMP3_TEMP_SETTLE_TIME + partial_out * BMP3_ADC_CONV_TIME); + /* convert into mill seconds */ + temp_meas_t = temp_meas_t / 1000; + + return temp_meas_t; +} + +/*! + * @brief This internal API fills the register address and register data of + * the over sampling settings for burst write operation. + */ +static void fill_osr_data(uint32_t settings, uint8_t *addr, uint8_t *reg_data, uint8_t *len, + const struct bmp3_dev *dev) +{ + struct bmp3_odr_filter_settings osr_settings = dev->settings.odr_filter; + + if (settings & (BMP3_PRESS_OS_SEL | BMP3_TEMP_OS_SEL)) { + /* Pressure over sampling settings check */ + if (settings & BMP3_PRESS_OS_SEL) { + /* Set the pressure over sampling settings in the + register variable */ + reg_data[*len] = BMP3_SET_BITS_POS_0(reg_data[0], BMP3_PRESS_OS, osr_settings.press_os); + } + /* Temperature over sampling settings check */ + if (settings & BMP3_TEMP_OS_SEL) { + /* Set the temperature over sampling settings in the + register variable */ + reg_data[*len] = BMP3_SET_BITS(reg_data[0], BMP3_TEMP_OS, osr_settings.temp_os); + } + /* 0x1C is the register address of over sampling register */ + addr[*len] = BMP3_OSR_ADDR; + (*len)++; + } +} + +/*! + * @brief This internal API fills the register address and register data of + * the odr settings for burst write operation. + */ +static void fill_odr_data(uint8_t *addr, uint8_t *reg_data, uint8_t *len, struct bmp3_dev *dev) +{ + struct bmp3_odr_filter_settings *osr_settings = &dev->settings.odr_filter; + + /* Limit the ODR to 0.001525879 Hz*/ + if (osr_settings->odr > BMP3_ODR_0_001_HZ) + osr_settings->odr = BMP3_ODR_0_001_HZ; + /* Set the odr settings in the register variable */ + reg_data[*len] = BMP3_SET_BITS_POS_0(reg_data[1], BMP3_ODR, osr_settings->odr); + /* 0x1D is the register address of output data rate register */ + addr[*len] = 0x1D; + (*len)++; +} + +/*! + * @brief This internal API fills the register address and register data of + * the filter settings for burst write operation. + */ +static void fill_filter_data(uint8_t *addr, uint8_t *reg_data, uint8_t *len, const struct bmp3_dev *dev) +{ + struct bmp3_odr_filter_settings osr_settings = dev->settings.odr_filter; + + /* Set the iir settings in the register variable */ + reg_data[*len] = BMP3_SET_BITS(reg_data[3], BMP3_IIR_FILTER, osr_settings.iir_filter); + /* 0x1F is the register address of iir filter register */ + addr[*len] = 0x1F; + (*len)++; +} + +/*! + * @brief This internal API is used to parse the pressure or temperature or + * both the data and store it in the bmp3_uncomp_data structure instance. + */ +static void parse_sensor_data(const uint8_t *reg_data, struct bmp3_uncomp_data *uncomp_data) +{ + /* Temporary variables to store the sensor data */ + uint32_t data_xlsb; + uint32_t data_lsb; + uint32_t data_msb; + + /* Store the parsed register values for pressure data */ + data_xlsb = (uint32_t)reg_data[0]; + data_lsb = (uint32_t)reg_data[1] << 8; + data_msb = (uint32_t)reg_data[2] << 16; + uncomp_data->pressure = data_msb | data_lsb | data_xlsb; + + /* Store the parsed register values for temperature data */ + data_xlsb = (uint32_t)reg_data[3]; + data_lsb = (uint32_t)reg_data[4] << 8; + data_msb = (uint32_t)reg_data[5] << 16; + uncomp_data->temperature = data_msb | data_lsb | data_xlsb; +} + +/*! + * @brief This internal API is used to compensate the pressure or temperature + * or both the data according to the component selected by the user. + */ +static int8_t compensate_data(uint8_t sensor_comp, const struct bmp3_uncomp_data *uncomp_data, + struct bmp3_data *comp_data, struct bmp3_calib_data *calib_data) +{ + int8_t rslt = BMP3_OK; + + if ((uncomp_data != NULL) && (comp_data != NULL) && (calib_data != NULL)) { + /* If pressure or temperature component is selected */ + if (sensor_comp & (BMP3_PRESS | BMP3_TEMP)) { + /* Compensate the temperature data */ + comp_data->temperature = compensate_temperature(uncomp_data, calib_data); + } + if (sensor_comp & BMP3_PRESS) { + /* Compensate the pressure data */ + comp_data->pressure = compensate_pressure(uncomp_data, calib_data); + } + } else { + rslt = BMP3_E_NULL_PTR; + } + + return rslt; +} + +#ifdef FLOATING_POINT_COMPENSATION +/*! + * @brief This internal API is used to parse the calibration data, compensates + * it and store it in device structure + */ +static void parse_calib_data(const uint8_t *reg_data, struct bmp3_dev *dev) +{ + /* Temporary variable to store the aligned trim data */ + struct bmp3_reg_calib_data *reg_calib_data = &dev->calib_data.reg_calib_data; + struct bmp3_quantized_calib_data *quantized_calib_data = &dev->calib_data.quantized_calib_data; + /* Temporary variable */ + float temp_var; + + /* 1 / 2^8 */ + temp_var = 0.00390625f; + reg_calib_data->par_t1 = BMP3_CONCAT_BYTES(reg_data[1], reg_data[0]); + quantized_calib_data->par_t1 = ((float)reg_calib_data->par_t1 / temp_var); + + reg_calib_data->par_t2 = BMP3_CONCAT_BYTES(reg_data[3], reg_data[2]); + temp_var = 1073741824.0f; + quantized_calib_data->par_t2 = ((float)reg_calib_data->par_t2 / temp_var); + + reg_calib_data->par_t3 = (int8_t)reg_data[4]; + temp_var = 281474976710656.0f; + quantized_calib_data->par_t3 = ((float)reg_calib_data->par_t3 / temp_var); + + reg_calib_data->par_p1 = (int16_t)BMP3_CONCAT_BYTES(reg_data[6], reg_data[5]); + temp_var = 1048576.0f; + quantized_calib_data->par_p1 = ((float)(reg_calib_data->par_p1 - (16384)) / temp_var); + + reg_calib_data->par_p2 = (int16_t)BMP3_CONCAT_BYTES(reg_data[8], reg_data[7]); + temp_var = 536870912.0f; + quantized_calib_data->par_p2 = ((float)(reg_calib_data->par_p2 - (16384)) / temp_var); + + reg_calib_data->par_p3 = (int8_t)reg_data[9]; + temp_var = 4294967296.0f; + quantized_calib_data->par_p3 = ((float)reg_calib_data->par_p3 / temp_var); + + reg_calib_data->par_p4 = (int8_t)reg_data[10]; + temp_var = 137438953472.0f; + quantized_calib_data->par_p4 = ((float)reg_calib_data->par_p4 / temp_var); + + reg_calib_data->par_p5 = BMP3_CONCAT_BYTES(reg_data[12], reg_data[11]); + /* 1 / 2^3 */ + temp_var = 0.125f; + quantized_calib_data->par_p5 = ((float)reg_calib_data->par_p5 / temp_var); + + reg_calib_data->par_p6 = BMP3_CONCAT_BYTES(reg_data[14], reg_data[13]); + temp_var = 64.0f; + quantized_calib_data->par_p6 = ((float)reg_calib_data->par_p6 / temp_var); + + reg_calib_data->par_p7 = (int8_t)reg_data[15]; + temp_var = 256.0f; + quantized_calib_data->par_p7 = ((float)reg_calib_data->par_p7 / temp_var); + + reg_calib_data->par_p8 = (int8_t)reg_data[16]; + temp_var = 32768.0f; + quantized_calib_data->par_p8 = ((float)reg_calib_data->par_p8 / temp_var); + + reg_calib_data->par_p9 = (int16_t)BMP3_CONCAT_BYTES(reg_data[18], reg_data[17]); + temp_var = 281474976710656.0f; + quantized_calib_data->par_p9 = ((float)reg_calib_data->par_p9 / temp_var); + + reg_calib_data->par_p10 = (int8_t)reg_data[19]; + temp_var = 281474976710656.0f; + quantized_calib_data->par_p10 = ((float)reg_calib_data->par_p10 / temp_var); + + reg_calib_data->par_p11 = (int8_t)reg_data[20]; + temp_var = 36893488147419103232.0f; + quantized_calib_data->par_p11 = ((float)reg_calib_data->par_p11 / temp_var); +} + +/*! + * @brief This internal API is used to compensate the raw temperature data and + * return the compensated temperature data in float data type. + */ +static float compensate_temperature(const struct bmp3_uncomp_data *uncomp_data, + struct bmp3_calib_data *calib_data) +{ + uint32_t uncomp_temp = uncomp_data->temperature; + float partial_data1; + float partial_data2; + + partial_data1 = (float)(uncomp_temp - calib_data->quantized_calib_data.par_t1); + partial_data2 = (float)(partial_data1 * calib_data->quantized_calib_data.par_t2); + /* Update the compensated temperature in calib structure since this is + needed for pressure calculation */ + calib_data->quantized_calib_data.t_lin = partial_data2 + (partial_data1 * partial_data1) + * calib_data->quantized_calib_data.par_t3; + + /* Returns compensated temperature */ + return calib_data->quantized_calib_data.t_lin; +} + +/*! + * @brief This internal API is used to compensate the raw pressure data and + * return the compensated pressure data in float data type. + */ +static float compensate_pressure(const struct bmp3_uncomp_data *uncomp_data, + const struct bmp3_calib_data *calib_data) +{ + const struct bmp3_quantized_calib_data *quantized_calib_data = &calib_data->quantized_calib_data; + /* Variable to store the compensated pressure */ + float comp_press; + /* Temporary variables used for compensation */ + float partial_data1; + float partial_data2; + float partial_data3; + float partial_data4; + float partial_out1; + float partial_out2; + + partial_data1 = quantized_calib_data->par_p6 * quantized_calib_data->t_lin; + partial_data2 = quantized_calib_data->par_p7 * bmp3_pow(quantized_calib_data->t_lin, 2); + partial_data3 = quantized_calib_data->par_p8 * bmp3_pow(quantized_calib_data->t_lin, 3); + partial_out1 = quantized_calib_data->par_p5 + partial_data1 + partial_data2 + partial_data3; + + partial_data1 = quantized_calib_data->par_p2 * quantized_calib_data->t_lin; + partial_data2 = quantized_calib_data->par_p3 * bmp3_pow(quantized_calib_data->t_lin, 2); + partial_data3 = quantized_calib_data->par_p4 * bmp3_pow(quantized_calib_data->t_lin, 3); + partial_out2 = uncomp_data->pressure * + (quantized_calib_data->par_p1 + partial_data1 + partial_data2 + partial_data3); + + partial_data1 = bmp3_pow((float)uncomp_data->pressure, 2); + partial_data2 = quantized_calib_data->par_p9 + quantized_calib_data->par_p10 * quantized_calib_data->t_lin; + partial_data3 = partial_data1 * partial_data2; + partial_data4 = partial_data3 + bmp3_pow((float)uncomp_data->pressure, 3) * quantized_calib_data->par_p11; + comp_press = partial_out1 + partial_out2 + partial_data4; + + return comp_press; +} + +/*! + * @brief This internal API is used to calculate the power functionality for + * floating point values. + */ +static float bmp3_pow(float base, uint8_t power) +{ + float pow_output = 1; + + while (power != 0) { + pow_output = base * pow_output; + power--; + } + + return pow_output; +} +#else + +/*! + * @brief This internal API is used to parse the calibration data, compensates + * it and store it in device structure + */ +static void parse_calib_data(const uint8_t *reg_data, struct bmp3_dev *dev) +{ + /* Temporary variable to store the aligned trim data */ + struct bmp3_reg_calib_data *reg_calib_data = &dev->calib_data.reg_calib_data; + + reg_calib_data->par_t1 = BMP3_CONCAT_BYTES(reg_data[1], reg_data[0]); + reg_calib_data->par_t2 = BMP3_CONCAT_BYTES(reg_data[3], reg_data[2]); + reg_calib_data->par_t3 = (int8_t)reg_data[4]; + reg_calib_data->par_p1 = (int16_t)BMP3_CONCAT_BYTES(reg_data[6], reg_data[5]); + reg_calib_data->par_p2 = (int16_t)BMP3_CONCAT_BYTES(reg_data[8], reg_data[7]); + reg_calib_data->par_p3 = (int8_t)reg_data[9]; + reg_calib_data->par_p4 = (int8_t)reg_data[10]; + reg_calib_data->par_p5 = BMP3_CONCAT_BYTES(reg_data[12], reg_data[11]); + reg_calib_data->par_p6 = BMP3_CONCAT_BYTES(reg_data[14], reg_data[13]); + reg_calib_data->par_p7 = (int8_t)reg_data[15]; + reg_calib_data->par_p8 = (int8_t)reg_data[16]; + reg_calib_data->par_p9 = (int16_t)BMP3_CONCAT_BYTES(reg_data[18], reg_data[17]); + reg_calib_data->par_p10 = (int8_t)reg_data[19]; + reg_calib_data->par_p11 = (int8_t)reg_data[20]; +} + +/*! + * @brief This internal API is used to compensate the raw temperature data and + * return the compensated temperature data in integer data type. + */ +static int64_t compensate_temperature(const struct bmp3_uncomp_data *uncomp_data, + struct bmp3_calib_data *calib_data) +{ + uint64_t partial_data1; + uint64_t partial_data2; + uint64_t partial_data3; + int64_t partial_data4; + int64_t partial_data5; + int64_t partial_data6; + int64_t comp_temp; + + partial_data1 = uncomp_data->temperature - (256 * calib_data->reg_calib_data.par_t1); + partial_data2 = calib_data->reg_calib_data.par_t2 * partial_data1; + partial_data3 = partial_data1 * partial_data1; + partial_data4 = (int64_t)partial_data3 * calib_data->reg_calib_data.par_t3; + partial_data5 = ((int64_t)(partial_data2 * 262144) + partial_data4); + partial_data6 = partial_data5 / 4294967296; + /* Store t_lin in dev. structure for pressure calculation */ + calib_data->reg_calib_data.t_lin = partial_data6; + comp_temp = (int64_t)((partial_data6 * 25) / 16384); + + return comp_temp; +} + +/*! + * @brief This internal API is used to compensate the raw pressure data and + * return the compensated pressure data in integer data type. + */ +static uint64_t compensate_pressure(const struct bmp3_uncomp_data *uncomp_data, + const struct bmp3_calib_data *calib_data) +{ + const struct bmp3_reg_calib_data *reg_calib_data = &calib_data->reg_calib_data; + int64_t partial_data1; + int64_t partial_data2; + int64_t partial_data3; + int64_t partial_data4; + int64_t partial_data5; + int64_t partial_data6; + int64_t offset; + int64_t sensitivity; + uint64_t comp_press; + + partial_data1 = reg_calib_data->t_lin * reg_calib_data->t_lin; + partial_data2 = partial_data1 / 64; + partial_data3 = (partial_data2 * reg_calib_data->t_lin) / 256; + partial_data4 = (reg_calib_data->par_p8 * partial_data3) / 32; + partial_data5 = (reg_calib_data->par_p7 * partial_data1) * 16; + partial_data6 = (reg_calib_data->par_p6 * reg_calib_data->t_lin) * 4194304; + offset = (reg_calib_data->par_p5 * 140737488355328) + partial_data4 + partial_data5 + partial_data6; + + partial_data2 = (reg_calib_data->par_p4 * partial_data3) / 32; + partial_data4 = (reg_calib_data->par_p3 * partial_data1) * 4; + partial_data5 = (reg_calib_data->par_p2 - 16384) * reg_calib_data->t_lin * 2097152; + sensitivity = ((reg_calib_data->par_p1 - 16384) * 70368744177664) + partial_data2 + partial_data4 + + partial_data5; + + partial_data1 = (sensitivity / 16777216) * uncomp_data->pressure; + partial_data2 = reg_calib_data->par_p10 * reg_calib_data->t_lin; + partial_data3 = partial_data2 + (65536 * reg_calib_data->par_p9); + partial_data4 = (partial_data3 * uncomp_data->pressure) / 8192; + partial_data5 = (partial_data4 * uncomp_data->pressure) / 512; + partial_data6 = (int64_t)((uint64_t)uncomp_data->pressure * (uint64_t)uncomp_data->pressure); + partial_data2 = (reg_calib_data->par_p11 * partial_data6) / 65536; + partial_data3 = (partial_data2 * uncomp_data->pressure) / 128; + partial_data4 = (offset / 4) + partial_data1 + partial_data5 + partial_data3; + comp_press = (((uint64_t)partial_data4 * 25) / (uint64_t)1099511627776); + + return comp_press; +} + +/*! + * @brief This internal API is used to calculate the power functionality. + */ +static uint32_t bmp3_pow(uint8_t base, uint8_t power) +{ + uint32_t pow_output = 1; + + while (power != 0) { + pow_output = base * pow_output; + power--; + } + + return pow_output; +} + +#endif + +/*! + * @brief This internal API is used to identify the settings which the user + * wants to modify in the sensor. + */ +static uint8_t are_settings_changed(uint32_t sub_settings, uint32_t desired_settings) +{ + uint8_t settings_changed = FALSE; + + if (sub_settings & desired_settings) { + /* User wants to modify this particular settings */ + settings_changed = TRUE; + } else { + /* User don't want to modify this particular settings */ + settings_changed = FALSE; + } + + return settings_changed; +} + +/*! + * @brief This internal API is used to validate the device structure pointer for + * null conditions. + */ +static int8_t null_ptr_check(const struct bmp3_dev *dev) +{ + int8_t rslt; + + if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL)) { + /* Device structure pointer is not valid */ + rslt = BMP3_E_NULL_PTR; + } else { + /* Device structure is fine */ + rslt = BMP3_OK; + } + + return rslt; +} + +/*! + * @brief This internal API is used to parse the fifo_config_1(fifo_mode, + * fifo_stop_on_full, fifo_time_en, fifo_press_en, fifo_temp_en), + * fifo_config_2(fifo_subsampling, data_select) and int_ctrl(fwtm_en, ffull_en) + * settings and store it in device structure + */ +static void parse_fifo_settings(const uint8_t *reg_data, struct bmp3_fifo_settings *dev_fifo) +{ + uint8_t fifo_config_1_data = reg_data[0]; + uint8_t fifo_config_2_data = reg_data[1]; + uint8_t fifo_int_ctrl_data = reg_data[2]; + + /* Parse fifo config 1 register data */ + dev_fifo->mode = BMP3_GET_BITS_POS_0(fifo_config_1_data, BMP3_FIFO_MODE); + dev_fifo->stop_on_full_en = BMP3_GET_BITS(fifo_config_1_data, BMP3_FIFO_STOP_ON_FULL); + dev_fifo->time_en = BMP3_GET_BITS(fifo_config_1_data, BMP3_FIFO_TIME_EN); + dev_fifo->press_en = BMP3_GET_BITS(fifo_config_1_data, BMP3_FIFO_PRESS_EN); + dev_fifo->temp_en = BMP3_GET_BITS(fifo_config_1_data, BMP3_FIFO_TEMP_EN); + + /* Parse fifo config 2 register data */ + dev_fifo->down_sampling = BMP3_GET_BITS_POS_0(fifo_config_2_data, BMP3_FIFO_DOWN_SAMPLING); + dev_fifo->filter_en = BMP3_GET_BITS(fifo_config_2_data, BMP3_FIFO_FILTER_EN); + + /* Parse fifo related interrupt control data */ + dev_fifo->ffull_en = BMP3_GET_BITS(fifo_int_ctrl_data, BMP3_FIFO_FULL_EN); + dev_fifo->fwtm_en = BMP3_GET_BITS(fifo_int_ctrl_data, BMP3_FIFO_FWTM_EN); +} + +/*! + * @brief This internal API fills the fifo_config_1(fifo_mode, + * fifo_stop_on_full, fifo_time_en, fifo_press_en, fifo_temp_en) settings in the + * reg_data variable so as to burst write in the sensor. + */ +static void fill_fifo_config_1(uint16_t desired_settings, uint8_t *reg_data, + struct bmp3_fifo_settings *dev_fifo) +{ + if (desired_settings & BMP3_FIFO_MODE_SEL) { + /* Fill the FIFO mode register data */ + *reg_data = BMP3_SET_BITS_POS_0(*reg_data, BMP3_FIFO_MODE, dev_fifo->mode); + } + if (desired_settings & BMP3_FIFO_STOP_ON_FULL_EN_SEL) { + /* Fill the stop on full data */ + *reg_data = BMP3_SET_BITS(*reg_data, BMP3_FIFO_STOP_ON_FULL, dev_fifo->stop_on_full_en); + } + if (desired_settings & BMP3_FIFO_TIME_EN_SEL) { + /* Fill the time enable data */ + *reg_data = BMP3_SET_BITS(*reg_data, BMP3_FIFO_TIME_EN, dev_fifo->time_en); + } + if (desired_settings & + (BMP3_FIFO_PRESS_EN_SEL | BMP3_FIFO_TEMP_EN_SEL)) { + /* Fill the FIFO pressure enable */ + if (desired_settings & BMP3_FIFO_PRESS_EN_SEL) { + if ((dev_fifo->temp_en == 0) && (dev_fifo->press_en == 1)) { + /* Set the temperature sensor to be enabled */ + dev_fifo->temp_en = 1; + } + /* Fill the pressure enable data */ + *reg_data = BMP3_SET_BITS(*reg_data, BMP3_FIFO_PRESS_EN, dev_fifo->press_en); + } + /* Temperature should be enabled to get the pressure data */ + *reg_data = BMP3_SET_BITS(*reg_data, BMP3_FIFO_TEMP_EN, dev_fifo->temp_en); + } + +} + +/*! + * @brief This internal API fills the fifo_config_2(fifo_subsampling, + * data_select) settings in the reg_data variable so as to burst write + * in the sensor. + */ +static void fill_fifo_config_2(uint16_t desired_settings, uint8_t *reg_data, + const struct bmp3_fifo_settings *dev_fifo) +{ + if (desired_settings & BMP3_FIFO_DOWN_SAMPLING_SEL) { + /* To do check Normal mode */ + /* Fill the down-sampling data */ + *reg_data = BMP3_SET_BITS_POS_0(*reg_data, BMP3_FIFO_DOWN_SAMPLING, dev_fifo->down_sampling); + } + if (desired_settings & BMP3_FIFO_FILTER_EN_SEL) { + /* Fill the filter enable data */ + *reg_data = BMP3_SET_BITS(*reg_data, BMP3_FIFO_FILTER_EN, dev_fifo->filter_en); + } +} + +/*! + * @brief This internal API fills the fifo interrupt control(fwtm_en, ffull_en) + * settings in the reg_data variable so as to burst write in the sensor. + */ +static void fill_fifo_int_ctrl(uint16_t desired_settings, uint8_t *reg_data, + const struct bmp3_fifo_settings *dev_fifo) +{ + if (desired_settings & BMP3_FIFO_FWTM_EN_SEL) { + /* Fill the FIFO watermark interrupt enable data */ + *reg_data = BMP3_SET_BITS(*reg_data, BMP3_FIFO_FWTM_EN, dev_fifo->fwtm_en); + } + if (desired_settings & BMP3_FIFO_FULL_EN_SEL) { + /* Fill the FIFO full interrupt enable data */ + *reg_data = BMP3_SET_BITS(*reg_data, BMP3_FIFO_FULL_EN, dev_fifo->ffull_en); + } +} + +/*! + * @brief This API gets the command ready, data ready for pressure and + * temperature, power on reset status from the sensor. + */ +static int8_t get_sensor_status(struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t reg_addr; + uint8_t reg_data; + + reg_addr = BMP3_SENS_STATUS_REG_ADDR; + rslt = bmp3_get_regs(reg_addr, ®_data, 1, dev); + + if (rslt == BMP3_OK) { + dev->status.sensor.cmd_rdy = BMP3_GET_BITS(reg_data, BMP3_STATUS_CMD_RDY); + dev->status.sensor.drdy_press = BMP3_GET_BITS(reg_data, BMP3_STATUS_DRDY_PRESS); + dev->status.sensor.drdy_temp = BMP3_GET_BITS(reg_data, BMP3_STATUS_DRDY_TEMP); + + reg_addr = BMP3_EVENT_ADDR; + rslt = bmp3_get_regs(reg_addr, ®_data, 1, dev); + dev->status.pwr_on_rst = reg_data & 0x01; + } + + return rslt; +} + +/*! + * @brief This API gets the interrupt (fifo watermark, fifo full, data ready) + * status from the sensor. + */ +static int8_t get_int_status(struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + + rslt = bmp3_get_regs(BMP3_INT_STATUS_REG_ADDR, ®_data, 1, dev); + + if (rslt == BMP3_OK) { + dev->status.intr.fifo_wm = BMP3_GET_BITS_POS_0(reg_data, BMP3_INT_STATUS_FWTM); + dev->status.intr.fifo_full = BMP3_GET_BITS(reg_data, BMP3_INT_STATUS_FFULL); + dev->status.intr.drdy = BMP3_GET_BITS(reg_data, BMP3_INT_STATUS_DRDY); + } + + return rslt; +} + +/*! + * @brief This API gets the fatal, command and configuration error + * from the sensor. + */ +static int8_t get_err_status(struct bmp3_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + + rslt = bmp3_get_regs(BMP3_ERR_REG_ADDR, ®_data, 1, dev); + + if (rslt == BMP3_OK) { + dev->status.err.cmd = BMP3_GET_BITS_POS_0(reg_data, BMP3_ERR_FATAL); + dev->status.err.conf = BMP3_GET_BITS(reg_data, BMP3_ERR_CMD); + dev->status.err.fatal = BMP3_GET_BITS(reg_data, BMP3_ERR_CONF); + } + + return rslt; +} diff --git a/src/hal/interface/sensors_bosch.h b/src/hal/interface/sensors_bosch.h index 342bc4f704..4128e181f6 100644 --- a/src/hal/interface/sensors_bosch.h +++ b/src/hal/interface/sensors_bosch.h @@ -51,9 +51,11 @@ /* Bosch Sensortec Drivers */ #include "bmi055.h" +#include "bmi088.h" #include "bmi160.h" #include "bmm150.h" #include "bmp280.h" +#include "bmp3.h" #include "bstdr_comm_support.h" #define SENSORS_READ_RATE_HZ 1000 @@ -80,7 +82,16 @@ #define SENSORS_BMI055_ACCEL_CFG 16 #define SENSORS_BMI055_ACCEL_FS_CFG BMI055_ACCEL_RANGE_16G #define SENSORS_BMI055_G_PER_LSB_CFG (2.0f * (float)SENSORS_BMI055_ACCEL_CFG) / 65536.0f -#define SENSORS_BMI055_1G_IN_LSB 65536 / SENSORS_BMI055_ACCEL_CFG / 2 +#define SENSORS_BMI055_1G_IN_LSB (65536 / SENSORS_BMI055_ACCEL_CFG / 2) + +/* BMI088 */ +#define SENSORS_BMI088_GYRO_FS_CFG BMI088_GYRO_RANGE_2000_DPS +#define SENSORS_BMI088_DEG_PER_LSB_CFG (2.0f *2000.0f) / 65536.0f + +#define SENSORS_BMI088_ACCEL_CFG 24 +#define SENSORS_BMI088_ACCEL_FS_CFG BMI088_ACCEL_RANGE_24G +#define SENSORS_BMI088_G_PER_LSB_CFG (2.0f * (float)SENSORS_BMI088_ACCEL_CFG) / 65536.0f +#define SENSORS_BMI088_1G_IN_LSB (65536 / SENSORS_BMI088_ACCEL_CFG / 2) #define SENSORS_VARIANCE_MAN_TEST_TIMEOUT M2T(1000) // Timeout in ms #define SENSORS_MAN_TEST_LEVEL_MAX 5.0f // Max degrees off