mirror of https://github.com/sqfmi/Watchy.git
4205 lines
136 KiB
C
4205 lines
136 KiB
C
/*
|
|
****************************************************************************
|
|
* Copyright (C) 2015 - 2016 Bosch Sensortec GmbH
|
|
*
|
|
* File :bma4.c
|
|
*
|
|
* Date: 12 Oct 2017
|
|
*
|
|
* Revision: 2.1.9 $
|
|
*
|
|
* Usage: Sensor Driver for BMA4 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 bma4.c
|
|
\brief Sensor Driver for BMA4 family of sensors */
|
|
/***************************************************************************/
|
|
/**\name Header files
|
|
****************************************************************************/
|
|
#include "bma4.h"
|
|
|
|
/***************************************************************************/
|
|
/**\name Static Data Buffer
|
|
****************************************************************************/
|
|
/* Local array to store the values read from the register
|
|
* using read_regs API */
|
|
static uint8_t temp_buff[BMA4_MAX_BUFFER_SIZE] = {0};
|
|
|
|
/***************************************************************************/
|
|
/**\name Local structures
|
|
****************************************************************************/
|
|
/*!
|
|
* @brief Accel difference value of axis.
|
|
*/
|
|
struct data_with_sign {
|
|
/*! Difference value */
|
|
int16_t val;
|
|
/*! Indicates negative value if set */
|
|
uint8_t is_negative;
|
|
};
|
|
|
|
/*!
|
|
* @brief Accel data deviation from ideal value
|
|
*/
|
|
struct offset_delta {
|
|
/*! Accel x axis */
|
|
struct data_with_sign x;
|
|
/*! Accel y axis */
|
|
struct data_with_sign y;
|
|
/*! Accel z axis */
|
|
struct data_with_sign z;
|
|
};
|
|
|
|
/*!
|
|
* @brief Accel offset xyz structure
|
|
*/
|
|
struct accel_offset {
|
|
/*! Accel offset X data */
|
|
uint8_t x;
|
|
/*! Accel offset Y data */
|
|
uint8_t y;
|
|
/*! Accel offset Z data */
|
|
uint8_t z;
|
|
};
|
|
|
|
/*!
|
|
* @brief Accel self test diff xyz data structure
|
|
*/
|
|
struct selftest_delta_limit {
|
|
/*! Accel X data */
|
|
int32_t x;
|
|
/*! Accel Y data */
|
|
int32_t y;
|
|
/*! Accel Z data */
|
|
int32_t z;
|
|
};
|
|
|
|
/*!
|
|
* @brief Structure to store temp data values
|
|
*/
|
|
struct accel_temp {
|
|
/*! Accel X temp data */
|
|
int32_t x;
|
|
/*! Accel Y temp data */
|
|
int32_t y;
|
|
/*! Accel Z temp data */
|
|
int32_t z;
|
|
};
|
|
|
|
/***************************************************************************/
|
|
/*! Static Function Declarations
|
|
****************************************************************************/
|
|
|
|
/*!
|
|
* @brief This API validates the bandwidth and perfmode
|
|
* value set by the user.
|
|
*
|
|
* param bandwidth[in] : bandwidth value set by the user.
|
|
* param perf_mode[in] : perf_mode value set by the user.
|
|
*/
|
|
static uint16_t validate_bandwidth_perfmode(uint8_t bandwidth, uint8_t perf_mode);
|
|
|
|
/*!
|
|
* @brief @brief This API validates the ODR value set by the user.
|
|
*
|
|
* param bandwidth[in] : odr for accelerometer
|
|
*/
|
|
static uint16_t validate_odr(uint8_t odr);
|
|
|
|
/*!
|
|
* @brief This API is used to reset the FIFO related configurations
|
|
* in the fifo_frame structure.
|
|
*
|
|
* @param dev[in,out] : Structure instance of bma4_dev
|
|
*
|
|
*/
|
|
static void reset_fifo_data_structure(const struct bma4_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] acc_count : Number of accelerometer frames to be read
|
|
* @param[in] dev : Structure instance of bma4_dev.
|
|
*
|
|
*/
|
|
static void get_accel_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *acc_count,
|
|
const struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This API checks the 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 fifo data
|
|
* @param[in] dev : Structure instance of bma4_dev.
|
|
*/
|
|
static void check_empty_fifo(uint16_t *data_index, const struct bma4_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 bma4_accel 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 bma4_dev.
|
|
*
|
|
*/
|
|
static void extract_accel_header_mode(struct bma4_accel *accel_data, uint16_t *accel_length,
|
|
const struct bma4_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 update the idx value which is used to store the index of
|
|
* the current data byte which is parsed.
|
|
*
|
|
* @param[in,out] acc : Structure instance of bma4_accel.
|
|
* @param[in,out] idx : Index value of number of bytes parsed
|
|
* @param[in,out] acc_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 and/or mag data enabled in FIFO)
|
|
* in header-less mode or frame header data
|
|
* in header mode
|
|
* @param[in] dev : Structure instance of bma4_dev.
|
|
*
|
|
*/
|
|
static void unpack_acc_frm(struct bma4_accel *acc, uint16_t *idx, uint16_t *acc_idx, uint8_t frm,
|
|
const struct bma4_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 bma4_accel.
|
|
*
|
|
* @param[out] accel_data : Structure instance of bma4_accel 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 bma4_dev.
|
|
*
|
|
*/
|
|
static void unpack_accel_data(struct bma4_accel *accel_data, uint16_t data_start_index, const struct bma4_dev *dev);
|
|
/*!
|
|
* @brief This API computes the number of bytes of Mag 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] mag_count : Number of magnetometer frames to be read
|
|
* @param[in] dev : Structure instance of bma4_dev.
|
|
*
|
|
*/
|
|
static void get_mag_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *mag_count,
|
|
const struct bma4_dev *dev);
|
|
/*!
|
|
* @brief This API is used to parse the magnetometer data from the
|
|
* FIFO data in header mode.
|
|
*
|
|
* @param[in,out] data : Structure instance of bma4_mag_xyzr where
|
|
* the magnetometer data in FIFO is extracted
|
|
* and stored.
|
|
* @param[in,out] len : Number of magnetometer frames
|
|
* (x,y,z,r data)
|
|
* @param[in,out] dev : Structure instance of bma4_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*
|
|
*/
|
|
static uint16_t extract_mag_header_mode(struct bma4_mag *data, uint16_t *len, const struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This API is used to parse the magnetometer data from the
|
|
* FIFO data in both header mode and header-less mode and update the
|
|
* idx value which is used to store the index of the current
|
|
* data byte which is parsed.
|
|
*
|
|
* @param data : Structure instance of bma4_mag_xyzr.
|
|
* @param idx : Index value of number of bytes parsed
|
|
* @param mag_idx : Index value magnetometer data frame (x,y,z,r)
|
|
* to be parsed
|
|
* @param frm : It consists of either the fifo_data_enable parameter
|
|
* (Accel and/or mag data enabled in FIFO) in
|
|
* header-less mode and frame header data in header mode
|
|
* @param dev : Structure instance of bma4_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*
|
|
*/
|
|
static uint16_t unpack_mag_frm(struct bma4_mag *data, uint16_t *idx, uint16_t *mag_idx, uint8_t frm,
|
|
const struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This API is used to parse the auxiliary magnetometer data from
|
|
* the FIFO data and store it in the instance of the structure mag_data.
|
|
*
|
|
* @param mag_data : Structure instance of bma4_mag_xyzr where the
|
|
* parsed magnetometer data bytes are stored.
|
|
* @param start_idx : Index value of the magnetometer data bytes
|
|
* which is to be parsed from the FIFO data
|
|
* @param dev : Structure instance of bma4_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*
|
|
*/
|
|
static uint16_t unpack_mag_data(struct bma4_mag *mag_data, uint16_t start_idx, const struct bma4_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 bma4_dev.
|
|
*
|
|
*/
|
|
static void unpack_sensortime_frame(uint16_t *data_index, const struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This API is used to parse and store the skipped_frame_count from
|
|
* the 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 bma4_dev.
|
|
*
|
|
*/
|
|
static void unpack_skipped_frame(uint16_t *data_index, const struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This API is used to parse and store the dropped_frame_count from
|
|
* the 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 bma4_dev.
|
|
*
|
|
*/
|
|
static void unpack_dropped_frame(uint16_t *data_index, const struct bma4_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 user specified 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 bma4_dev.
|
|
*
|
|
*/
|
|
static void move_next_frame(uint16_t *data_index, uint8_t current_frame_length, const struct bma4_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 bma4_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 bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This API enables or disables the Accel Self test feature in the
|
|
* sensor.
|
|
*
|
|
* @param[in] accel_selftest_enable : Variable used to enable or disable
|
|
* the Accel self test feature
|
|
* Value | Description
|
|
* --------|---------------
|
|
* 0x00 | BMA4_DISABLE
|
|
* 0x01 | BMA4_ENABLE
|
|
*
|
|
* @param[in] dev : Structure instance of bma4_dev
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*
|
|
*/
|
|
static uint16_t set_accel_selftest_enable(uint8_t accel_selftest_axis, struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This API selects the sign of Accel self-test excitation
|
|
*
|
|
* @param[in] accel_selftest_sign: Variable used to select the Accel
|
|
* self test sign
|
|
* Value | Description
|
|
* --------|--------------------------
|
|
* 0x00 | BMA4_DISABLE (negative)
|
|
* 0x01 | BMA4_ENABLE (positive)
|
|
*
|
|
* @param[in] dev : Structure instance of bma4_dev
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*
|
|
*/
|
|
static uint16_t set_accel_selftest_sign(uint8_t accel_selftest_sign, struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This API sets the Accel self test amplitude in the sensor.
|
|
*
|
|
* @param[in] accel_selftest_amp : Variable used to specify the Accel self
|
|
* test amplitude
|
|
* Value | Description
|
|
* --------|------------------------------------
|
|
* 0x00 | BMA4_SELFTEST_AMP_LOW
|
|
* 0x01 | BMA4_SELFTEST_AMP_HIGH
|
|
*
|
|
* @param[in] dev : structure instance of bma4_dev
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*
|
|
*/
|
|
static uint16_t set_accel_selftest_amp(uint8_t accel_selftest_amp, struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This function enables and configures the Accel which is needed
|
|
* for Self test operation.
|
|
*
|
|
* @param[in] dev : Structure instance of bma4_dev
|
|
*
|
|
* @return results of self test
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*
|
|
*/
|
|
static uint16_t set_accel_selftest_config(struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This API validates the Accel g value provided as input by the
|
|
* user for Accel offset compensation.
|
|
*
|
|
* @param[in] gvalue : Pointer variable used to specify the g value
|
|
* set by the user for Accel offset compensation.
|
|
*
|
|
* @note The g-values to be passed to the parameter should be
|
|
* multiples of 1000000.
|
|
*
|
|
* @return results of the status of user input validation
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*
|
|
*/
|
|
static uint16_t validate_user_input(const int32_t *gvalue);
|
|
/*!
|
|
* @brief This API converts the range value into corresponding integer
|
|
* value.
|
|
*
|
|
* @param[in] range_in : input range value.
|
|
* @param[out] range_out : pointer to store the integer value of range.
|
|
*
|
|
* @return results of the status of user input validation
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*
|
|
*/
|
|
static void map_range(uint8_t range_in, uint8_t *range_out);
|
|
|
|
/*!
|
|
* @brief This API normalise the data with offset.
|
|
*
|
|
* @param[out] compensated_data : pointer to store the compensated data.
|
|
* @param[in] offset_data : pointer of offset.
|
|
*
|
|
* @return results of the status of user input validation
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*
|
|
*/
|
|
static void normalise_offset(const struct offset_delta *compensated_data, struct accel_offset *offset_data);
|
|
|
|
/*!
|
|
* @brief This API normalise the data with offset.
|
|
*
|
|
* @param[in] res : resolution of the sensor.
|
|
* @param[in] range : G-range of the accel.
|
|
* @param[in] delta : pointer of offset_delta.
|
|
* @param[out] data : pointer to store accel_offset data.
|
|
*
|
|
* @return results of the status of user input validation
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*
|
|
*/
|
|
static void scale_offset(uint8_t res, uint8_t range, const struct offset_delta *delta, struct accel_offset *data);
|
|
|
|
/*!
|
|
* @brief This API compensate the accel data against gravity.
|
|
*
|
|
* @param[in] lsb_per_g : lsb value pre 1g.
|
|
* @param[in] g_val : G reference value of all axis.
|
|
* @param[in] data : pointer of accel_offset data.
|
|
* @param[out] comp_data : pointer to store compensated data.
|
|
*
|
|
* @note The g-values to be passed to the parameter should be
|
|
* multiples of 1000000.
|
|
*
|
|
* @return results of the status of user input validation
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*
|
|
*/
|
|
static void comp_for_grvty(uint16_t lsb_per_g, const int32_t g_val[3], const struct bma4_accel *data,
|
|
struct offset_delta *comp_data);
|
|
/*!
|
|
* @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
|
|
* @param[in] dev : Structure instance of bma4_dev
|
|
*
|
|
* @return results of self test operation
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*
|
|
*/
|
|
static uint16_t validate_selftest(const struct selftest_delta_limit *accel_data_diff,
|
|
const struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This function configure the Accel for FOC.
|
|
*
|
|
* @param[in] acc_conf : accel config structure instance
|
|
* @param[in] acc_en : enables the accel
|
|
* @param[in] pwr_mode : set the power mode
|
|
* @param[in] dev : Structure instance of bma4_dev
|
|
*
|
|
* @return results of self test operation
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*
|
|
*/
|
|
static uint16_t foc_config(struct bma4_accel_config *acc_conf, uint8_t *acc_en, uint8_t *pwr_mode,
|
|
struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @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
|
|
* @param[out] dev : Structure instance of bma4_dev
|
|
*
|
|
* @return None *
|
|
*/
|
|
static void convert_lsb_g(const struct selftest_delta_limit *accel_data_diff,
|
|
struct selftest_delta_limit *accel_data_diff_mg,
|
|
const struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This API sets the feature config. data start address in the sensor.
|
|
*
|
|
* @param[in] dev : Structure instance of bma4_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*/
|
|
static uint16_t set_feature_config_start_addr(struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This API increments the feature config. data address according to the user
|
|
* provided read/write length in the dev structure.
|
|
*
|
|
* @param[in] dev : Structure instance of bma4_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval Any non zero value -> Fail
|
|
*/
|
|
static uint16_t increment_feature_config_addr(const struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This API reads the 8-bit data from the given register
|
|
* in the sensor.
|
|
*/
|
|
static uint16_t read_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This API writes the 8-bit data to the given register
|
|
* in the sensor.
|
|
*/
|
|
static uint16_t write_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This API sets the feature config. data start address in the sensor.
|
|
*/
|
|
static uint16_t get_feature_config_start_addr(struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @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 : return the value of base^resolution
|
|
*/
|
|
|
|
static int32_t power(int16_t base, uint8_t resolution);
|
|
|
|
/*!
|
|
* @brief This API performs roundoff on given value
|
|
*
|
|
* @param[in] value : Value which is need to be rounded off
|
|
*
|
|
* @return : None
|
|
*/
|
|
static int8_t roundoff(int32_t value);
|
|
|
|
/*!
|
|
* @brief This API finds the bit position of 3.9mg according to given range
|
|
* and resolution.
|
|
*
|
|
* @param[in] range : range of the accel.
|
|
* @param[in] res : resolution of the accel.
|
|
*
|
|
* @return : bit position of 3.9mg
|
|
*/
|
|
static int8_t get_bit_pos_3_9mg(uint8_t range, uint8_t res);
|
|
|
|
/*!
|
|
* @brief This API finds the the null error of the device pointer structure
|
|
*
|
|
* @param[in] dev : Structure instance of bma4_dev.
|
|
*
|
|
* @return Null error
|
|
*/
|
|
static uint16_t bma4_null_pointer_check(const struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This internal API brings up the secondary interface to access
|
|
* auxiliary sensor
|
|
*
|
|
* @param[in] dev : Structure instance of bma4_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
*
|
|
* @retval 0 if success, else fail
|
|
*/
|
|
static uint16_t bma4_set_aux_interface_config(struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This internal API reads the data from the auxiliary sensor
|
|
* depending on burst length configured
|
|
*
|
|
* @param[in] dev : Structure instance of bma4_dev.
|
|
* @param[out] aux_data : Pointer variable to store data read
|
|
* @param[in] aux_reg_addr : Variable to pass address from where
|
|
* data is to be read
|
|
*
|
|
* @return Result of API execution status
|
|
*
|
|
* @retval 0 if success, else fail
|
|
*/
|
|
static uint16_t bma4_extract_aux_data(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev);
|
|
|
|
/*!
|
|
* @brief This internal API maps the actual burst read length with user length set.
|
|
*
|
|
* @param[in] dev : Structure instance of bma4_dev.
|
|
* @param[out] len : Pointer variable to store mapped length
|
|
*
|
|
* @return Result of API execution status
|
|
*
|
|
* @retval 0 if success, else fail
|
|
*/
|
|
static uint16_t bma4_map_read_len(uint8_t *len, const struct bma4_dev *dev);
|
|
|
|
/***************************************************************************/
|
|
/**\name Extern Declarations
|
|
****************************************************************************/
|
|
|
|
/***************************************************************************/
|
|
/**\name Globals
|
|
****************************************************************************/
|
|
|
|
|
|
/***************************************************************************/
|
|
/**\name Function definitions
|
|
****************************************************************************/
|
|
/*!
|
|
* @brief This API is the entry point.
|
|
* Call this API before using all other APIs.
|
|
* This API reads the chip-id of the sensor which is the first step to
|
|
* verify the sensor and also it configures the read mechanism of SPI and
|
|
* I2C interface.
|
|
*/
|
|
uint16_t bma4_init(struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
/* Check the bma4 structure as NULL */
|
|
if ((dev == NULL) || (dev->bus_read == NULL) || (dev->bus_write == NULL)) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
if (dev->interface == BMA4_SPI_INTERFACE)
|
|
dev->dummy_byte = 1;
|
|
else
|
|
dev->dummy_byte = 0;
|
|
|
|
rslt |= bma4_read_regs(BMA4_CHIP_ID_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
/* Assign Chip Id */
|
|
dev->chip_id = data;
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API is used to write the binary configuration in the sensor
|
|
*/
|
|
uint16_t bma4_write_config_file(struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt;
|
|
/* Config loading disable*/
|
|
uint8_t config_load = 0;
|
|
uint16_t index = 0;
|
|
uint8_t config_stream_status = 0;
|
|
|
|
/* Disable advanced power save */
|
|
rslt = bma4_set_advance_power_save(BMA4_DISABLE, dev);
|
|
/* Wait for sensor time synchronization. Refer the data-sheet for
|
|
more information*/
|
|
dev->delay(1);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
/* Disable config loading*/
|
|
rslt |= bma4_write_regs(BMA4_INIT_CTRL_ADDR, &config_load, 1, dev);
|
|
/* Write the config stream */
|
|
for (index = 0; index < BMA4_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 = 0x01;
|
|
rslt |= bma4_write_regs(BMA4_INIT_CTRL_ADDR, &config_load, 1, dev);
|
|
/* Wait till ASIC is initialized. Refer the data-sheet for
|
|
more information*/
|
|
dev->delay(150);
|
|
/* Read the status of config stream operation */
|
|
rslt |= bma4_read_regs(BMA4_INTERNAL_STAT, &config_stream_status, 1, dev);
|
|
|
|
if (config_stream_status != BMA4_ASIC_INITIALIZED) {
|
|
rslt |= BMA4_E_CONFIG_STREAM_ERROR;
|
|
} else {
|
|
/* Enable advanced power save */
|
|
rslt |= bma4_set_advance_power_save(BMA4_ENABLE, dev);
|
|
rslt |= get_feature_config_start_addr(dev);
|
|
}
|
|
}
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API checks whether the write operation requested is for feature
|
|
* config or register write and accordingly writes the data in the sensor.
|
|
*/
|
|
uint16_t bma4_write_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev)
|
|
{
|
|
uint8_t i;
|
|
uint8_t loop_count;
|
|
uint8_t overflow;
|
|
uint8_t index;
|
|
uint16_t rslt = BMA4_OK;
|
|
uint8_t adv_pwr_save = 0;
|
|
|
|
/* Check the dev structure as NULL*/
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
if (addr == BMA4_FEATURE_CONFIG_ADDR) {
|
|
/* Disable APS if enabled before writing the feature config register */
|
|
rslt = bma4_get_advance_power_save(&adv_pwr_save, dev);
|
|
if (adv_pwr_save == BMA4_ENABLE) {
|
|
rslt |= bma4_set_advance_power_save(BMA4_DISABLE, dev);
|
|
/* Wait for sensor time synchronization. Refer the data-sheet for
|
|
more information*/
|
|
dev->delay(1);
|
|
}
|
|
|
|
if (((len % 2) == 0) && (len <= dev->feature_len) && (rslt == BMA4_OK)) {
|
|
if (dev->read_write_len < len) {
|
|
/* Calculate the no of writes to be performed according
|
|
to the read/write length */
|
|
loop_count = len / dev->read_write_len;
|
|
overflow = len % dev->read_write_len;
|
|
index = 0;
|
|
rslt = set_feature_config_start_addr(dev);
|
|
for (i = 0; i < loop_count; i++) {
|
|
rslt |= write_regs(BMA4_FEATURE_CONFIG_ADDR, data + index,
|
|
dev->read_write_len, dev);
|
|
rslt |= increment_feature_config_addr(dev);
|
|
index = index + dev->read_write_len;
|
|
}
|
|
if (overflow)
|
|
rslt |= write_regs(BMA4_FEATURE_CONFIG_ADDR, data + index,
|
|
overflow, dev);
|
|
rslt |= set_feature_config_start_addr(dev);
|
|
} else {
|
|
rslt = write_regs(BMA4_FEATURE_CONFIG_ADDR, data, len, dev);
|
|
}
|
|
} else {
|
|
rslt = BMA4_E_RD_WR_LENGTH_INVALID;
|
|
}
|
|
|
|
if (rslt == BMA4_OK) {
|
|
/* Enable APS once write feature config register is done */
|
|
rslt = bma4_get_advance_power_save(&adv_pwr_save, dev);
|
|
if (adv_pwr_save == BMA4_DISABLE) {
|
|
rslt |= bma4_set_advance_power_save(BMA4_ENABLE, dev);
|
|
/* Wait for sensor time synchronization. Refer the data-sheet for
|
|
more information*/
|
|
dev->delay(1);
|
|
}
|
|
}
|
|
|
|
} else {
|
|
rslt = write_regs(addr, data, len, dev);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API writes the 8-bit data to the given register
|
|
* in the sensor.
|
|
*/
|
|
static uint16_t write_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
if (dev->interface == BMA4_SPI_INTERFACE)
|
|
addr = addr & BMA4_SPI_WR_MASK;
|
|
/* write data in the register*/
|
|
rslt |= dev->bus_write(dev->dev_addr, addr, data, len);
|
|
}
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the feature config. data start address in the sensor.
|
|
*/
|
|
static uint16_t get_feature_config_start_addr(struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt;
|
|
uint8_t asic_lsb;
|
|
uint8_t asic_msb;
|
|
|
|
rslt = read_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev);
|
|
rslt |= read_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev);
|
|
|
|
/* Store asic info in dev structure */
|
|
dev->asic_data.asic_lsb = asic_lsb & 0x0F;
|
|
dev->asic_data.asic_msb = asic_msb;
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the feature config. data start address in the sensor.
|
|
*/
|
|
static uint16_t set_feature_config_start_addr(struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt;
|
|
|
|
rslt = write_regs(BMA4_RESERVED_REG_5B_ADDR, &dev->asic_data.asic_lsb, 1, dev);
|
|
rslt |= write_regs(BMA4_RESERVED_REG_5C_ADDR, &dev->asic_data.asic_msb, 1, dev);
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API increments the feature config. data address according to the user
|
|
* provided read/write length in the dev structure.
|
|
*/
|
|
static uint16_t increment_feature_config_addr(const struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt;
|
|
uint16_t asic_addr;
|
|
uint8_t asic_lsb;
|
|
uint8_t asic_msb;
|
|
|
|
/* Read the asic address from the sensor */
|
|
rslt = read_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev);
|
|
rslt |= read_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev);
|
|
/* Get the asic address */
|
|
asic_addr = (asic_msb << 4) | (asic_lsb & 0x0F);
|
|
/* Sum the asic address with read/write length after converting from
|
|
byte to word */
|
|
asic_addr = asic_addr + (dev->read_write_len / 2);
|
|
/* Split the asic address */
|
|
asic_lsb = asic_addr & 0x0F;
|
|
asic_msb = (uint8_t)(asic_addr >> 4);
|
|
/* Write the asic address in the sensor */
|
|
rslt |= write_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev);
|
|
rslt |= write_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev);
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API checks whether the read operation requested is for feature
|
|
* or register read and accordingly reads the data from the sensor.
|
|
*/
|
|
uint16_t bma4_read_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev)
|
|
{
|
|
uint8_t i;
|
|
uint8_t loop_count;
|
|
uint8_t overflow;
|
|
uint8_t index;
|
|
uint16_t rslt = BMA4_OK;
|
|
uint8_t adv_pwr_save = 0;
|
|
|
|
/* Check the dev structure as NULL*/
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
if (addr == BMA4_FEATURE_CONFIG_ADDR) {
|
|
/* Disable APS if enabled before reading the feature config register */
|
|
rslt = bma4_get_advance_power_save(&adv_pwr_save, dev);
|
|
if (adv_pwr_save == BMA4_ENABLE) {
|
|
rslt |= bma4_set_advance_power_save(BMA4_DISABLE, dev);
|
|
/* Wait for sensor time synchronization. Refer the data-sheet for
|
|
more information*/
|
|
dev->delay(1);
|
|
}
|
|
|
|
if (((len % 2) == 0) && (len <= dev->feature_len) && (rslt == BMA4_OK)) {
|
|
if (dev->read_write_len < len) {
|
|
/* Calculate the no of writes to be performed according
|
|
to the read/write length */
|
|
loop_count = len / dev->read_write_len;
|
|
overflow = len % dev->read_write_len;
|
|
index = 0;
|
|
rslt = set_feature_config_start_addr(dev);
|
|
for (i = 0; i < loop_count; i++) {
|
|
rslt |= read_regs(BMA4_FEATURE_CONFIG_ADDR, data + index,
|
|
dev->read_write_len, dev);
|
|
rslt |= increment_feature_config_addr(dev);
|
|
index = index + dev->read_write_len;
|
|
}
|
|
if (overflow)
|
|
rslt |= read_regs(BMA4_FEATURE_CONFIG_ADDR, data + index,
|
|
overflow, dev);
|
|
rslt |= set_feature_config_start_addr(dev);
|
|
} else {
|
|
rslt = read_regs(BMA4_FEATURE_CONFIG_ADDR, data, len, dev);
|
|
}
|
|
} else {
|
|
rslt = BMA4_E_RD_WR_LENGTH_INVALID;
|
|
}
|
|
if (rslt == BMA4_OK) {
|
|
/* Enable APS once read feature config register is done */
|
|
rslt = bma4_get_advance_power_save(&adv_pwr_save, dev);
|
|
if (adv_pwr_save == BMA4_DISABLE) {
|
|
rslt |= bma4_set_advance_power_save(BMA4_ENABLE, dev);
|
|
/* Wait for sensor time synchronization. Refer the data-sheet for
|
|
more information*/
|
|
dev->delay(1);
|
|
}
|
|
}
|
|
} else {
|
|
rslt = read_regs(addr, data, len, dev);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the 8-bit data from the given register
|
|
* in the sensor.
|
|
*/
|
|
static uint16_t read_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev)
|
|
{
|
|
/* variable used to return the status of communication result*/
|
|
uint16_t rslt = 0;
|
|
uint16_t temp_len = len + dev->dummy_byte;
|
|
uint16_t i;
|
|
|
|
if (dev->interface == BMA4_SPI_INTERFACE) {
|
|
/* SPI mask added */
|
|
addr = addr | BMA4_SPI_RD_MASK;
|
|
}
|
|
|
|
if (temp_len > BMA4_MAX_BUFFER_SIZE) {
|
|
/* Buffer size is not sufficient */
|
|
rslt |= BMA4_E_OUT_OF_RANGE;
|
|
}
|
|
|
|
if (rslt == BMA4_OK) {
|
|
/* Read the data from the register */
|
|
rslt |= dev->bus_read(dev->dev_addr, addr, temp_buff, temp_len);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
/* Parsing and storing the valid data */
|
|
data[i] = temp_buff[i + dev->dummy_byte];
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the error status from the sensor.
|
|
*/
|
|
uint16_t bma4_get_error_status(struct bma4_err_reg *err_reg, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Read the error codes*/
|
|
rslt |= bma4_read_regs(BMA4_ERROR_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
/* Fatal error*/
|
|
err_reg->fatal_err = BMA4_GET_BITS_POS_0(data, BMA4_FATAL_ERR);
|
|
/* Cmd error*/
|
|
err_reg->cmd_err = BMA4_GET_BITSLICE(data, BMA4_CMD_ERR);
|
|
/* User error*/
|
|
err_reg->err_code = BMA4_GET_BITSLICE(data, BMA4_ERR_CODE);
|
|
/* FIFO error*/
|
|
err_reg->fifo_err = BMA4_GET_BITSLICE(data, BMA4_FIFO_ERR);
|
|
/* Mag data ready error*/
|
|
err_reg->aux_err = BMA4_GET_BITSLICE(data, BMA4_AUX_ERR);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the sensor status from the sensor.
|
|
*/
|
|
uint16_t bma4_get_status(uint8_t *status, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Read the error codes*/
|
|
rslt |= bma4_read_regs(BMA4_STATUS_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*status = data;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the Accel data for x,y and z axis from the sensor.
|
|
* The data units is in LSB format.
|
|
*/
|
|
uint16_t bma4_read_accel_xyz(struct bma4_accel *accel, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint16_t lsb = 0;
|
|
uint16_t msb = 0;
|
|
uint8_t data[BMA4_ACCEL_DATA_LENGTH] = {0};
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_DATA_8_ADDR, data, BMA4_ACCEL_DATA_LENGTH, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
msb = data[1];
|
|
lsb = data[0];
|
|
/* Accel data x axis */
|
|
accel->x = (int16_t)((msb << 8) | lsb);
|
|
|
|
msb = data[3];
|
|
lsb = data[2];
|
|
/* Accel data y axis */
|
|
accel->y = (int16_t)((msb << 8) | lsb);
|
|
|
|
msb = data[5];
|
|
lsb = data[4];
|
|
/* Accel data z axis */
|
|
accel->z = (int16_t)((msb << 8) | lsb);
|
|
|
|
if (dev->resolution == BMA4_12_BIT_RESOLUTION) {
|
|
accel->x = (accel->x / 0x10);
|
|
accel->y = (accel->y / 0x10);
|
|
accel->z = (accel->z / 0x10);
|
|
} else if (dev->resolution == BMA4_14_BIT_RESOLUTION) {
|
|
accel->x = (accel->x / 0x04);
|
|
accel->y = (accel->y / 0x04);
|
|
accel->z = (accel->z / 0x04);
|
|
}
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the sensor time of Sensor time gets updated
|
|
* with every update of data register or FIFO.
|
|
*/
|
|
uint16_t bma4_get_sensor_time(uint32_t *sensor_time, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data[BMA4_SENSOR_TIME_LENGTH] = {0};
|
|
uint8_t msb = 0;
|
|
uint8_t xlsb = 0;
|
|
uint8_t lsb = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_SENSORTIME_0_ADDR, data, BMA4_SENSOR_TIME_LENGTH, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
msb = data[BMA4_SENSOR_TIME_MSB_BYTE];
|
|
xlsb = data[BMA4_SENSOR_TIME_XLSB_BYTE];
|
|
lsb = data[BMA4_SENSOR_TIME_LSB_BYTE];
|
|
*sensor_time = (uint32_t)((msb << 16) | (xlsb << 8) | lsb);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the chip temperature of sensor.
|
|
*
|
|
* @note Using a scaling factor of 1000, to obtain integer values, which
|
|
* at the user end, are used to get accurate temperature value .
|
|
* BMA4_FAHREN_SCALED = 1.8 * 1000, BMA4_KELVIN_SCALED = 273.15 * 1000
|
|
*/
|
|
uint16_t bma4_get_temperature(int32_t *temp, uint8_t temp_unit, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data[BMA4_TEMP_DATA_SIZE] = {0};
|
|
int32_t temp_raw_scaled = 0;
|
|
|
|
/* Check for Null pointer error */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Read temperature value from the register */
|
|
rslt |= bma4_read_regs(BMA4_TEMPERATURE_ADDR, data, BMA4_TEMP_DATA_SIZE, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
temp_raw_scaled = (int32_t)data[BMA4_TEMP_BYTE] * BMA4_SCALE_TEMP;
|
|
|
|
/* '0' value read from the register corresponds to 23 degree C */
|
|
(*temp) = temp_raw_scaled + (BMA4_OFFSET_TEMP * BMA4_SCALE_TEMP);
|
|
|
|
switch (temp_unit) {
|
|
case BMA4_DEG:
|
|
break;
|
|
|
|
case BMA4_FAHREN:
|
|
/* Temperature in degree Fahrenheit */
|
|
(*temp) = (((*temp) / BMA4_SCALE_TEMP) * BMA4_FAHREN_SCALED) + (32 * BMA4_SCALE_TEMP);
|
|
break;
|
|
|
|
case BMA4_KELVIN:
|
|
/* Temperature in degree Kelvin */
|
|
(*temp) = (*temp) + BMA4_KELVIN_SCALED;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the Output data rate, Bandwidth, perf_mode
|
|
* and Range of accel.
|
|
*/
|
|
uint16_t bma4_get_accel_config(struct bma4_accel_config *accel, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data[2] = {0};
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_ACCEL_CONFIG_ADDR, data, BMA4_ACCEL_CONFIG_LENGTH, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
/* To get the ODR */
|
|
accel->odr = BMA4_GET_BITS_POS_0(data[0], BMA4_ACCEL_ODR);
|
|
/* To get the bandwidth */
|
|
accel->bandwidth = BMA4_GET_BITSLICE(data[0], BMA4_ACCEL_BW);
|
|
/* To get the under sampling mode */
|
|
accel->perf_mode = BMA4_GET_BITSLICE(data[0], BMA4_ACCEL_PERFMODE);
|
|
/* Read the Accel range */
|
|
accel->range = BMA4_GET_BITS_POS_0(data[1], BMA4_ACCEL_RANGE);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the output_data_rate, bandwidth, perf_mode
|
|
* and range of Accel.
|
|
*/
|
|
uint16_t bma4_set_accel_config(const struct bma4_accel_config *accel, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t accel_config_data[2] = {0, 0};
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* check whether the bandwidth and perfmode
|
|
settings are valid */
|
|
rslt = validate_bandwidth_perfmode(accel->bandwidth, accel->perf_mode);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
/* check ODR is valid */
|
|
rslt |= validate_odr(accel->odr);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
accel_config_data[0] = accel->odr & BMA4_ACCEL_ODR_MSK;
|
|
accel_config_data[0] |= (uint8_t)(accel->bandwidth << BMA4_ACCEL_BW_POS);
|
|
accel_config_data[0] |= (uint8_t)(accel->perf_mode << BMA4_ACCEL_PERFMODE_POS);
|
|
accel_config_data[1] = accel->range & BMA4_ACCEL_RANGE_MSK;
|
|
|
|
/* Burst write is not possible in
|
|
suspend mode hence individual write is
|
|
used with delay of 1 ms */
|
|
rslt |= bma4_write_regs(BMA4_ACCEL_CONFIG_ADDR, &accel_config_data[0], 1, dev);
|
|
dev->delay(BMA4_GEN_READ_WRITE_DELAY);
|
|
rslt |= bma4_write_regs((BMA4_ACCEL_CONFIG_ADDR + 1), &accel_config_data[1],
|
|
1, dev);
|
|
}
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API validates the bandwidth and perf_mode
|
|
* value set by the user.
|
|
*/
|
|
static uint16_t validate_bandwidth_perfmode(uint8_t bandwidth, uint8_t perf_mode)
|
|
{
|
|
uint16_t rslt = BMA4_OK;
|
|
|
|
if (perf_mode == BMA4_CONTINUOUS_MODE) {
|
|
if (bandwidth > BMA4_ACCEL_NORMAL_AVG4) {
|
|
/* Invalid bandwidth error for continuous mode */
|
|
rslt = BMA4_E_OUT_OF_RANGE;
|
|
}
|
|
} else if (perf_mode == BMA4_CIC_AVG_MODE) {
|
|
if (bandwidth > BMA4_ACCEL_RES_AVG128) {
|
|
/* Invalid bandwidth error for CIC avg. mode */
|
|
rslt = BMA4_E_OUT_OF_RANGE;
|
|
}
|
|
} else {
|
|
rslt = BMA4_E_OUT_OF_RANGE;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API validates the ODR value set by the user.
|
|
*/
|
|
static uint16_t validate_odr(uint8_t odr)
|
|
{
|
|
uint16_t rslt = BMA4_OK;
|
|
|
|
if ((odr < BMA4_OUTPUT_DATA_RATE_0_78HZ) || (odr > BMA4_OUTPUT_DATA_RATE_1600HZ)) {
|
|
/* If odr is not valid return error */
|
|
rslt = BMA4_E_OUT_OF_RANGE;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the advance power save mode in the sensor.
|
|
*/
|
|
uint16_t bma4_set_advance_power_save(uint8_t adv_pwr_save, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = BMA4_OK;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev);
|
|
if (rslt == BMA4_OK) {
|
|
data = BMA4_SET_BITS_POS_0(data, BMA4_ADVANCE_POWER_SAVE, adv_pwr_save);
|
|
rslt |= bma4_write_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the status of advance power save mode
|
|
* from the sensor.
|
|
*/
|
|
uint16_t bma4_get_advance_power_save(uint8_t *adv_pwr_save, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = BMA4_OK;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*adv_pwr_save = BMA4_GET_BITS_POS_0(data, BMA4_ADVANCE_POWER_SAVE);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the FIFO self wake up functionality in the sensor.
|
|
*/
|
|
uint16_t bma4_set_fifo_self_wakeup(uint8_t fifo_self_wakeup, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
data = BMA4_SET_BITSLICE(data, BMA4_FIFO_SELF_WAKE_UP, fifo_self_wakeup);
|
|
rslt |= bma4_write_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API gets the status of FIFO self wake up functionality from
|
|
* the sensor.
|
|
*/
|
|
uint16_t bma4_get_fifo_self_wakeup(uint8_t *fifo_self_wake_up, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*fifo_self_wake_up = BMA4_GET_BITSLICE(data, BMA4_FIFO_SELF_WAKE_UP);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API enables or disables the Accel in the sensor.
|
|
*/
|
|
uint16_t bma4_set_accel_enable(uint8_t accel_en, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
data = BMA4_SET_BITSLICE(data, BMA4_ACCEL_ENABLE, accel_en);
|
|
rslt |= bma4_write_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API checks whether Accel is enabled or not in the sensor.
|
|
*/
|
|
uint16_t bma4_get_accel_enable(uint8_t *accel_en, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*accel_en = BMA4_GET_BITSLICE(data, BMA4_ACCEL_ENABLE);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API is used to enable or disable auxiliary Mag
|
|
* in the sensor.
|
|
*/
|
|
uint16_t bma4_set_mag_enable(uint8_t mag_en, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
data = BMA4_SET_BITS_POS_0(data, BMA4_MAG_ENABLE, mag_en);
|
|
rslt |= bma4_write_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API is used to check whether the auxiliary Mag is enabled
|
|
* or not in the sensor.
|
|
*/
|
|
uint16_t bma4_get_mag_enable(uint8_t *mag_en, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*mag_en = BMA4_GET_BITS_POS_0(data, BMA4_MAG_ENABLE);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the SPI interface mode which is set for primary
|
|
* interface.
|
|
*/
|
|
uint16_t bma4_get_spi_interface(uint8_t *spi, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Read SPI mode */
|
|
rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*spi = BMA4_GET_BITS_POS_0(data, BMA4_CONFIG_SPI3);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API configures the SPI interface Mode for primary interface
|
|
*/
|
|
uint16_t bma4_set_spi_interface(uint8_t spi, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
if (spi <= BMA4_MAX_VALUE_SPI3) {
|
|
/* Write SPI mode */
|
|
rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
data = BMA4_SET_BITS_POS_0(data, BMA4_CONFIG_SPI3, spi);
|
|
rslt |= bma4_write_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
|
|
}
|
|
} else {
|
|
rslt |= BMA4_E_OUT_OF_RANGE;
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API writes the available sensor specific commands
|
|
* to the sensor.
|
|
*/
|
|
uint16_t bma4_set_command_register(uint8_t command_reg, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Write command register */
|
|
rslt |= bma4_write_regs(BMA4_CMD_ADDR, &command_reg, 1, dev);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the I2C device address of auxiliary sensor
|
|
*/
|
|
uint16_t bma4_set_i2c_device_addr(struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0, dev_id = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Write the auxiliary I2C device address */
|
|
rslt |= bma4_read_regs(BMA4_AUX_DEV_ID_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
dev_id = BMA4_SET_BITSLICE(data, BMA4_I2C_DEVICE_ADDR, dev->aux_config.aux_dev_addr);
|
|
rslt |= bma4_write_regs(BMA4_AUX_DEV_ID_ADDR, &dev_id, 1, dev);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the register access on MAG_IF[2], MAG_IF[3],
|
|
* MAG_IF[4] in the sensor. This implies that the DATA registers are
|
|
* not updated with Mag values automatically.
|
|
*/
|
|
uint16_t bma4_set_mag_manual_enable(uint8_t mag_manual, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Write the Mag manual*/
|
|
rslt |= bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev);
|
|
dev->delay(BMA4_GEN_READ_WRITE_DELAY);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
/* Set the bit of Mag manual enable */
|
|
data = BMA4_SET_BITSLICE(data, BMA4_MAG_MANUAL_ENABLE, mag_manual);
|
|
rslt |= bma4_write_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
dev->aux_config.manual_enable = (uint8_t)mag_manual;
|
|
} else {
|
|
/*dev->mag_manual_enable = 0;*/
|
|
dev->aux_config.manual_enable = 0;
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API checks whether the Mag access is done manually or
|
|
* automatically in the sensor.
|
|
* If the Mag access is done through manual mode then Mag data registers
|
|
* in sensor are not updated automatically.
|
|
*/
|
|
uint16_t bma4_get_mag_manual_enable(uint8_t *mag_manual, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Read Mag manual */
|
|
rslt |= bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*mag_manual = BMA4_GET_BITSLICE(data, BMA4_MAG_MANUAL_ENABLE);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the I2C interface configuration(if) mode
|
|
* for auxiliary Mag.
|
|
*/
|
|
uint16_t bma4_set_aux_if_mode(uint8_t if_mode, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
data = BMA4_SET_BITSLICE(data, BMA4_IF_CONFIG_IF_MODE, if_mode);
|
|
rslt |= bma4_write_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API gets the address of the register of Aux Mag sensor
|
|
* where the data to be read.
|
|
*/
|
|
uint16_t bma4_get_mag_read_addr(uint8_t *mag_read_addr, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_AUX_RD_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*mag_read_addr = BMA4_GET_BITS_POS_0(data, BMA4_READ_ADDR);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the address of the register of Aux Mag sensor
|
|
* where the data to be read.
|
|
*/
|
|
uint16_t bma4_set_mag_read_addr(uint8_t mag_read_addr, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Write the Mag read address*/
|
|
rslt |= bma4_write_regs(BMA4_AUX_RD_ADDR, &mag_read_addr, 1, dev);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API gets the Aux Mag write address from the sensor.
|
|
* Mag write address is where the Mag data will be written.
|
|
*/
|
|
uint16_t bma4_get_mag_write_addr(uint8_t *mag_write_addr, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_AUX_WR_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*mag_write_addr = BMA4_GET_BITS_POS_0(data, BMA4_WRITE_ADDR);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the Aux Mag write address in the sensor.
|
|
* Mag write address is where the Mag data will be written.
|
|
*/
|
|
uint16_t bma4_set_mag_write_addr(uint8_t mag_write_addr, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL)
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
else
|
|
rslt |= bma4_write_regs(BMA4_AUX_WR_ADDR, &mag_write_addr, 1, dev);
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the data from the sensor which is written to the
|
|
* Mag.
|
|
*/
|
|
uint16_t bma4_get_mag_write_data(uint8_t *mag_write_data, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_AUX_WR_DATA_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*mag_write_data = BMA4_GET_BITS_POS_0(data, BMA4_WRITE_DATA);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the data in the sensor which in turn will
|
|
* be written to Mag.
|
|
*/
|
|
uint16_t bma4_set_mag_write_data(uint8_t mag_write_data, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL)
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
else
|
|
rslt |= bma4_write_regs(BMA4_AUX_WR_DATA_ADDR, &mag_write_data, 1, dev);
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the x,y,z and r axis data from the auxiliary
|
|
* Mag BMM150/AKM9916 sensor.
|
|
*/
|
|
uint16_t bma4_read_mag_xyzr(struct bma4_mag_xyzr *mag, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint16_t msb = 0;
|
|
uint16_t lsb = 0;
|
|
uint8_t data[BMA4_MAG_XYZR_DATA_LENGTH] = {0};
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_DATA_0_ADDR, data, BMA4_MAG_XYZR_DATA_LENGTH, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
/* Data X */
|
|
/* X-axis LSB value shifting */
|
|
lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_X_LSB_BYTE], BMA4_DATA_MAG_X_LSB);
|
|
msb = data[BMA4_MAG_X_MSB_BYTE];
|
|
mag->x = (int16_t)((msb << 8) | lsb);
|
|
mag->x = (mag->x / 0x08);
|
|
|
|
/* Data Y */
|
|
/* Y-axis LSB value shifting */
|
|
lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_Y_LSB_BYTE], BMA4_DATA_MAG_Y_LSB);
|
|
msb = data[BMA4_MAG_Y_MSB_BYTE];
|
|
mag->y = (int16_t)((msb << 8) | lsb);
|
|
mag->y = (mag->y / 0x08);
|
|
|
|
/* Data Z */
|
|
/* Z-axis LSB value shifting */
|
|
lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_Z_LSB_BYTE], BMA4_DATA_MAG_Z_LSB);
|
|
msb = data[BMA4_MAG_Z_MSB_BYTE];
|
|
mag->z = (int16_t)((msb << 8) | lsb);
|
|
mag->z = (mag->z / 0x02);
|
|
|
|
/* RHall */
|
|
/* R-axis LSB value shifting */
|
|
lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_R_LSB_BYTE], BMA4_DATA_MAG_R_LSB);
|
|
msb = data[BMA4_MAG_R_MSB_BYTE];
|
|
mag->r = (int16_t)((msb << 8) | lsb);
|
|
mag->r = (mag->r / 0x04);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the burst data length (1,2,6,8 byte) of auxiliary
|
|
* Mag sensor.
|
|
*/
|
|
uint16_t bma4_set_mag_burst(uint8_t mag_burst, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Write auxiliary burst mode length*/
|
|
rslt |= bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
data = BMA4_SET_BITS_POS_0(data, BMA4_MAG_BURST, mag_burst);
|
|
rslt |= bma4_write_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the burst data length of Mag set in the sensor.
|
|
*/
|
|
uint16_t bma4_get_mag_burst(uint8_t *mag_burst, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Write Mag burst mode length*/
|
|
rslt |= bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*mag_burst = BMA4_GET_BITS_POS_0(data, BMA4_MAG_BURST);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the FIFO data of Accel and/or Mag sensor
|
|
*/
|
|
uint16_t bma4_read_fifo_data(struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
uint8_t addr = BMA4_FIFO_DATA_ADDR;
|
|
/* check the bma4 structure as NULL*/
|
|
if (dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
reset_fifo_data_structure(dev);
|
|
/* read FIFO data*/
|
|
if (dev->interface == BMA4_SPI_INTERFACE)
|
|
addr = addr | BMA4_SPI_RD_MASK;
|
|
|
|
rslt |= dev->bus_read(dev->dev_addr, addr, dev->fifo->data, dev->fifo->length);
|
|
/* read fifo frame content configuration*/
|
|
rslt |= bma4_read_regs(BMA4_FIFO_CONFIG_1_ADDR, &data, 1, dev);
|
|
/* filter fifo header enabled status */
|
|
dev->fifo->fifo_header_enable = data & BMA4_FIFO_HEADER;
|
|
/* filter accel/mag data enabled status */
|
|
dev->fifo->fifo_data_enable = data & BMA4_FIFO_M_A_ENABLE;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API parses and extracts the accelerometer frames from
|
|
* FIFO data read by the "bma4_read_fifo_data" API and stores it in the
|
|
* "accel_data" structure instance.
|
|
*/
|
|
uint16_t bma4_extract_accel(struct bma4_accel *accel_data, uint16_t *accel_length, const struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint16_t data_index = 0;
|
|
uint16_t accel_index = 0;
|
|
uint16_t data_read_length = 0;
|
|
|
|
if (dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Parsing the FIFO data in header-less mode */
|
|
if (dev->fifo->fifo_header_enable == 0) {
|
|
get_accel_len_to_parse(&data_index, &data_read_length, accel_length, dev);
|
|
|
|
for (; data_index < data_read_length;) {
|
|
unpack_acc_frm(accel_data, &data_index, &accel_index, dev->fifo->fifo_data_enable, dev);
|
|
/*Check for the availability of next
|
|
two bytes of FIFO data */
|
|
check_empty_fifo(&data_index, dev);
|
|
}
|
|
/* update number of accel data read*/
|
|
*accel_length = accel_index;
|
|
/*update the accel byte index*/
|
|
dev->fifo->accel_byte_start_idx = data_index;
|
|
} else {
|
|
/* Parsing the FIFO data in header mode */
|
|
extract_accel_header_mode(accel_data, accel_length, dev);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API parses and extracts the magnetometer frames from
|
|
* FIFO data read by the "bma4_read_fifo_data" API and stores it in the
|
|
* "mag_data" structure instance parameter of this API
|
|
*/
|
|
uint16_t bma4_extract_mag(struct bma4_mag *mag_data, uint16_t *mag_length, const struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint16_t data_index = 0;
|
|
uint16_t mag_index = 0;
|
|
uint16_t data_read_length = 0;
|
|
|
|
if (dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Parsing the FIFO data in header-less mode */
|
|
if (dev->fifo->fifo_header_enable == 0) {
|
|
get_mag_len_to_parse(&data_index, &data_read_length, mag_length, dev);
|
|
for (; data_index < data_read_length;) {
|
|
rslt |= unpack_mag_frm(mag_data, &data_index, &mag_index,
|
|
dev->fifo->fifo_data_enable, dev);
|
|
/*Check for the availability of next
|
|
two bytes of FIFO data */
|
|
check_empty_fifo(&data_index, dev);
|
|
}
|
|
/* update number of Aux. sensor data read*/
|
|
*mag_length = mag_index;
|
|
/*update the Aux. sensor frame index*/
|
|
dev->fifo->mag_byte_start_idx = data_index;
|
|
} else {
|
|
/* Parsing the FIFO data in header mode */
|
|
rslt |= extract_mag_header_mode(mag_data, mag_length, dev);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the FIFO water mark level which is set
|
|
* in the sensor.
|
|
*/
|
|
uint16_t bma4_get_fifo_wm(uint16_t *fifo_wm, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data[2] = {0, 0};
|
|
|
|
/* Check the bma4 structure as NULL*/
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Read the FIFO water mark level*/
|
|
rslt |= bma4_read_regs(BMA4_FIFO_WTM_0_ADDR, data, BMA4_FIFO_WM_LENGTH, dev);
|
|
|
|
if (BMA4_OK == rslt)
|
|
*fifo_wm = (data[1] << 8) | (data[0]);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the FIFO watermark level in the sensor.
|
|
*/
|
|
uint16_t bma4_set_fifo_wm(uint16_t fifo_wm, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data[2] = {0, 0};
|
|
|
|
/* Check the bma4 structure as NULL*/
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
|
|
data[0] = BMA4_GET_LSB(fifo_wm);
|
|
data[1] = BMA4_GET_MSB(fifo_wm);
|
|
/* consecutive write is not possible in suspend mode hence
|
|
separate write is used with delay of 1 ms*/
|
|
/* Write the fifo watermark level*/
|
|
rslt |= bma4_write_regs(BMA4_FIFO_WTM_0_ADDR, &data[0], 1, dev);
|
|
dev->delay(BMA4_GEN_READ_WRITE_DELAY);
|
|
rslt |= bma4_write_regs((BMA4_FIFO_WTM_0_ADDR + 1), &data[1], 1, dev);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API checks whether the Accel FIFO data is set for filtered
|
|
* or unfiltered mode.
|
|
*/
|
|
uint16_t bma4_get_accel_fifo_filter_data(uint8_t *accel_fifo_filter, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Read the Accel FIFO filter data */
|
|
rslt |= bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*accel_fifo_filter = BMA4_GET_BITSLICE(data, BMA4_FIFO_FILTER_ACCEL);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the condition of Accel FIFO data either to
|
|
* filtered or unfiltered mode.
|
|
*/
|
|
uint16_t bma4_set_accel_fifo_filter_data(uint8_t accel_fifo_filter, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
if (accel_fifo_filter <= BMA4_MAX_VALUE_FIFO_FILTER) {
|
|
rslt |= bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
/* Write Accel FIFO filter data */
|
|
data = BMA4_SET_BITSLICE(data, BMA4_FIFO_FILTER_ACCEL, accel_fifo_filter);
|
|
rslt |= bma4_write_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev);
|
|
}
|
|
} else {
|
|
rslt |= BMA4_E_OUT_OF_RANGE;
|
|
}
|
|
}
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the down sampling rates which is configured
|
|
* for Accel FIFO data.
|
|
*/
|
|
uint16_t bma4_get_fifo_down_accel(uint8_t *fifo_down, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Read the Accel FIFO down data */
|
|
rslt |= bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*fifo_down = BMA4_GET_BITSLICE(data, BMA4_FIFO_DOWN_ACCEL);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the down-sampling rates for Accel FIFO.
|
|
*/
|
|
uint16_t bma4_set_fifo_down_accel(uint8_t fifo_down, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Write the Accel FIFO down data */
|
|
rslt |= bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
data = BMA4_SET_BITSLICE(data, BMA4_FIFO_DOWN_ACCEL, fifo_down);
|
|
rslt |= bma4_write_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev);
|
|
}
|
|
}
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the length of FIFO data available in the sensor
|
|
* in the units of bytes.
|
|
*/
|
|
uint16_t bma4_get_fifo_length(uint16_t *fifo_length, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t index = 0;
|
|
uint8_t data[BMA4_FIFO_DATA_LENGTH] = {0, 0};
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Read FIFO length*/
|
|
rslt |= bma4_read_regs(BMA4_FIFO_LENGTH_0_ADDR, data, BMA4_FIFO_DATA_LENGTH, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
index = BMA4_FIFO_LENGTH_MSB_BYTE;
|
|
data[index] = BMA4_GET_BITS_POS_0(data[index], BMA4_FIFO_BYTE_COUNTER_MSB);
|
|
*fifo_length = ((data[index] << 8) | data[index - 1]);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API aligns and compensates the Mag data of BMM150/AKM9916
|
|
* sensor.
|
|
*/
|
|
uint16_t bma4_second_if_mag_compensate_xyz(struct bma4_mag_fifo_data mag_fifo_data,
|
|
uint8_t mag_second_if, struct bma4_mag *compensated_mag_data)
|
|
{
|
|
uint16_t rslt = 0;
|
|
#ifdef BMM150
|
|
int16_t mag_x = 0;
|
|
int16_t mag_y = 0;
|
|
int16_t mag_z = 0;
|
|
uint16_t mag_r = 0;
|
|
#endif
|
|
|
|
switch (mag_second_if) {
|
|
#ifdef BMM150
|
|
case BMA4_SEC_IF_BMM150:
|
|
/* X data*/
|
|
mag_x = (int16_t)((mag_fifo_data.mag_x_msb << 8) | (mag_fifo_data.mag_x_lsb));
|
|
mag_x = (int16_t) (mag_x / 0x08);
|
|
|
|
/* Y data*/
|
|
mag_y = (int16_t)((mag_fifo_data.mag_y_msb << 8) | (mag_fifo_data.mag_y_lsb));
|
|
mag_y = (int16_t) (mag_y / 0x08);
|
|
|
|
/* Z data*/
|
|
mag_z = (int16_t)((mag_fifo_data.mag_z_msb << 8) | (mag_fifo_data.mag_z_lsb));
|
|
mag_z = (int16_t) (mag_z / 0x02);
|
|
|
|
/* R data*/
|
|
mag_r = (uint16_t)((mag_fifo_data.mag_r_y2_msb << 8) | (mag_fifo_data.mag_r_y2_lsb));
|
|
mag_r = (uint16_t) (mag_r >> 2);
|
|
|
|
/* Compensated Mag x data */
|
|
compensated_mag_data->x = bma4_bmm150_mag_compensate_X(mag_x, mag_r);
|
|
|
|
/* Compensated Mag y data */
|
|
compensated_mag_data->y = bma4_bmm150_mag_compensate_Y(mag_y, mag_r);
|
|
|
|
/* Compensated Mag z data */
|
|
compensated_mag_data->z = bma4_bmm150_mag_compensate_Z(mag_z, mag_r);
|
|
break;
|
|
#endif
|
|
|
|
#ifdef AKM9916
|
|
|
|
case BMA4_SEC_IF_AKM09916:
|
|
/* Compensated X data */
|
|
compensated_mag_data->x = (int16_t)((mag_fifo_data.mag_x_msb << 8) | (mag_fifo_data.mag_x_lsb));
|
|
/* Compensated Y data*/
|
|
compensated_mag_data->y = (int16_t)((mag_fifo_data.mag_y_msb << 8) | (mag_fifo_data.mag_y_lsb));
|
|
/* Compensated Z data*/
|
|
compensated_mag_data->z = (int16_t)((mag_fifo_data.mag_z_msb << 8) | (mag_fifo_data.mag_z_lsb));
|
|
break;
|
|
|
|
#endif
|
|
default:
|
|
rslt |= BMA4_E_OUT_OF_RANGE;
|
|
break;
|
|
}
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads Mag. x,y and z axis data from either BMM150 or
|
|
* AKM9916 sensor
|
|
*/
|
|
uint16_t bma4_read_mag_xyz(struct bma4_mag *mag, uint8_t sensor_select, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
|
|
#if defined(AKM9916) || defined(BMM150)
|
|
uint8_t index;
|
|
uint16_t msb = 0;
|
|
uint16_t lsb = 0;
|
|
uint8_t data[BMA4_MAG_XYZ_DATA_LENGTH] = {0};
|
|
#endif
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
switch (sensor_select) {
|
|
|
|
#if defined(BMM150)
|
|
|
|
case BMA4_SEC_IF_BMM150:
|
|
rslt |= bma4_read_regs(BMA4_DATA_0_ADDR, data, BMA4_MAG_XYZ_DATA_LENGTH, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
index = BMA4_MAG_X_LSB_BYTE;
|
|
/*X-axis LSB value shifting*/
|
|
data[index] = BMA4_GET_BITSLICE(data[index], BMA4_DATA_MAG_X_LSB);
|
|
/* Data X */
|
|
msb = data[index + 1];
|
|
lsb = data[index];
|
|
mag->x = (int16_t)((msb << 8) | lsb);
|
|
mag->x = (mag->x / 0x08);
|
|
|
|
/* Data Y */
|
|
/*Y-axis LSB value shifting*/
|
|
data[index + 2] = BMA4_GET_BITSLICE(data[index + 2], BMA4_DATA_MAG_Y_LSB);
|
|
msb = data[index + 3];
|
|
lsb = data[index + 2];
|
|
mag->y = (int16_t)((msb << 8) | lsb);
|
|
mag->y = (mag->y / 0x08);
|
|
|
|
/* Data Z */
|
|
/*Z-axis LSB value shifting*/
|
|
data[index + 4] = BMA4_GET_BITSLICE(data[index + 4], BMA4_DATA_MAG_Z_LSB);
|
|
msb = data[index + 5];
|
|
lsb = data[index + 4];
|
|
mag->z = (int16_t)((msb << 8) | lsb);
|
|
mag->z = (mag->z / 0x02);
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#if defined(AKM9916)
|
|
case BMA4_SEC_IF_AKM09916:
|
|
|
|
if (AKM9916_SENSOR == dev->aux_sensor) {
|
|
rslt |= bma4_read_regs(BMA4_DATA_0_ADDR, data, BMA4_MAG_XYZ_DATA_LENGTH, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
index = BMA4_MAG_X_LSB_BYTE;
|
|
/* Data X */
|
|
msb = data[index + 1];
|
|
lsb = data[index];
|
|
mag->x = (int16_t)((msb << 8) | lsb);
|
|
|
|
/* Data Y */
|
|
msb = data[index + 3];
|
|
lsb = data[index + 2];
|
|
mag->y = (int32_t)((msb << 8) | lsb);
|
|
|
|
/* Data Z */
|
|
msb = data[index + 5];
|
|
lsb = data[index + 4];
|
|
mag->z = (int16_t)((msb << 8) | lsb);
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
rslt |= BMA4_E_OUT_OF_RANGE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the auxiliary I2C interface configuration which
|
|
* is set in the sensor.
|
|
*/
|
|
uint16_t bma4_get_if_mode(uint8_t *if_mode, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Read auxiliary interface configuration */
|
|
rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*if_mode = BMA4_GET_BITSLICE(data, BMA4_IF_CONFIG_IF_MODE);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the auxiliary interface configuration in the
|
|
* sensor.
|
|
*/
|
|
uint16_t bma4_set_if_mode(uint8_t if_mode, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
if (if_mode <= BMA4_MAX_IF_MODE) {
|
|
/* Write the interface configuration mode */
|
|
rslt |= bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
|
|
if (rslt == BMA4_OK) {
|
|
data = BMA4_SET_BITSLICE(data, BMA4_IF_CONFIG_IF_MODE, if_mode);
|
|
rslt |= bma4_write_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
|
|
}
|
|
} else {
|
|
rslt |= BMA4_E_OUT_OF_RANGE;
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the data ready status of Accel from the sensor.
|
|
*/
|
|
uint16_t bma4_get_accel_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/*Reads the status of Accel data ready*/
|
|
rslt |= bma4_read_regs(BMA4_STATUS_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*data_rdy = BMA4_GET_BITSLICE(data, BMA4_STAT_DATA_RDY_ACCEL);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the data ready status of Mag from the sensor.
|
|
* The status get reset when Mag data register is read.
|
|
*/
|
|
uint16_t bma4_get_mag_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/*Reads the status of Accel data ready*/
|
|
rslt |= bma4_read_regs(BMA4_STATUS_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*data_rdy = BMA4_GET_BITSLICE(data, BMA4_STAT_DATA_RDY_MAG);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the ASIC status from the sensor.
|
|
* The status information is mentioned in the below table.
|
|
*/
|
|
uint16_t bma4_get_asic_status(struct bma4_asic_status *asic_status, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
/* Read the Mag I2C device address*/
|
|
rslt |= bma4_read_regs(BMA4_INTERNAL_ERROR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
asic_status->sleep = (data & 0x01);
|
|
asic_status->irq_ovrn = ((data & 0x02) >> 0x01);
|
|
asic_status->wc_event = ((data & 0x04) >> 0x02);
|
|
asic_status->stream_transfer_active = ((data & 0x08) >> 0x03);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API enables the offset compensation for filtered and
|
|
* unfiltered Accel data.
|
|
*/
|
|
uint16_t bma4_set_offset_comp(uint8_t offset_en, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_NV_CONFIG_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
/* Write Accel FIFO filter data */
|
|
data = BMA4_SET_BITSLICE(data, BMA4_NV_ACCEL_OFFSET, offset_en);
|
|
rslt |= bma4_write_regs(BMA4_NV_CONFIG_ADDR, &data, 1, dev);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API gets the status of Accel offset compensation
|
|
*/
|
|
uint16_t bma4_get_offset_comp(uint8_t *offset_en, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_NV_CONFIG_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
/* Write Accel FIFO filter data */
|
|
*offset_en = BMA4_GET_BITSLICE(data, BMA4_NV_ACCEL_OFFSET);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API performs Fast Offset Compensation for Accel.
|
|
*
|
|
* @note The g-values to be passed to the parameter should be
|
|
* multiples of 1000000.
|
|
*/
|
|
uint16_t bma4_perform_accel_foc(const int32_t accel_g_value[3], struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
struct bma4_accel accel_value[10] = { {0} };
|
|
struct accel_offset offset = {0};
|
|
struct offset_delta delta = { {0,0},{0,0},{0,0} };
|
|
struct bma4_accel_config acc_conf = {0};
|
|
uint8_t accel_en = 0;
|
|
uint8_t adv_pwr_save = 0;
|
|
uint8_t range = 0;
|
|
uint16_t lsb_per_g = 0;
|
|
struct accel_temp temp = {0};
|
|
struct bma4_accel avg = {0};
|
|
struct bma4_accel accel_data = {0};
|
|
uint8_t i = 0;
|
|
|
|
/* used to validate user input */
|
|
rslt |= validate_user_input(accel_g_value);
|
|
|
|
if (BMA4_OK == rslt) {
|
|
/* Configure accel config, accel enable and
|
|
advance power save for FOC */
|
|
rslt |= foc_config(&acc_conf, &accel_en, &adv_pwr_save, dev);
|
|
|
|
/*TO DO: Check for data ready status before
|
|
reading accel values*/
|
|
|
|
if (BMA4_OK == rslt) {
|
|
/* Giving a delay of 20ms before reading accel data
|
|
since odr is configured as 50Hz */
|
|
for (i = 0; i < 10; i++) {
|
|
dev->delay(20);
|
|
rslt |= bma4_read_accel_xyz(&accel_value[i], dev);
|
|
temp.x = temp.x + (int32_t)accel_value[i].x;
|
|
temp.y = temp.y + (int32_t)accel_value[i].y;
|
|
temp.z = temp.z + (int32_t)accel_value[i].z;
|
|
}
|
|
|
|
/* Take average of x, y and z data for lesser noise */
|
|
avg.x = (int16_t)(temp.x / 10);
|
|
avg.y = (int16_t)(temp.y / 10);
|
|
avg.z = (int16_t)(temp.z / 10);
|
|
|
|
/* Copy average value in another structure */
|
|
accel_data = avg;
|
|
|
|
if (BMA4_OK == rslt) {
|
|
/* Get the exact range value */
|
|
map_range(acc_conf.range, &range);
|
|
/* Get LSB per bit given the range and resolution */
|
|
lsb_per_g = (uint16_t)(power(2, dev->resolution) / (2 * range));
|
|
/* Compensate accel data against gravity */
|
|
comp_for_grvty(lsb_per_g, accel_g_value, &accel_data, &delta);
|
|
/* scale according to offset register resolution*/
|
|
scale_offset(dev->resolution, range, &delta, &offset);
|
|
/* normalise the data with offset*/
|
|
normalise_offset(&delta, &offset);
|
|
|
|
/* offset values are written in the offset register */
|
|
rslt |= bma4_write_regs(BMA4_OFFSET_0_ADDR, (uint8_t *)&offset.x, 1, dev);
|
|
rslt |= bma4_write_regs(BMA4_OFFSET_1_ADDR, (uint8_t *)&offset.y, 1, dev);
|
|
rslt |= bma4_write_regs(BMA4_OFFSET_2_ADDR, (uint8_t *)&offset.z, 1, dev);
|
|
|
|
/* Enable offset compensation */
|
|
rslt |= bma4_set_offset_comp(BMA4_ENABLE, dev);
|
|
|
|
/* Set accel config, accel enable and advance power save */
|
|
rslt |= bma4_set_accel_config(&acc_conf, dev);
|
|
rslt |= bma4_set_accel_enable(accel_en, dev);
|
|
rslt |= bma4_set_advance_power_save(adv_pwr_save, dev);
|
|
} else {
|
|
rslt |= BMA4_E_FOC_FAIL;
|
|
}
|
|
}
|
|
}
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API checks whether the self test functionality of the sensor
|
|
* is working or not.
|
|
* The following parameter of struct bma4_dev, should have the valid value before
|
|
* performing the Self test,
|
|
* 1. Variant and 2. Resolution
|
|
*/
|
|
uint16_t bma4_perform_accel_selftest(uint8_t *result, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
struct bma4_accel positive = {0};
|
|
struct bma4_accel negative = {0};
|
|
/*! Structure for difference of accel values in g*/
|
|
struct selftest_delta_limit accel_data_diff = {0};
|
|
/*! Structure for difference of accel values in mg*/
|
|
struct selftest_delta_limit accel_data_diff_mg = {0};
|
|
|
|
*result = BMA4_SELFTEST_FAIL;
|
|
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
|
|
rslt = set_accel_selftest_config(dev);
|
|
dev->delay(20);
|
|
rslt |= bma4_selftest_config(BMA4_ENABLE, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
dev->delay(100);
|
|
rslt = bma4_read_accel_xyz(&positive, dev);
|
|
rslt |= bma4_selftest_config(BMA4_DISABLE, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
dev->delay(100);
|
|
rslt = bma4_read_accel_xyz(&negative, 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, dev);
|
|
/*! Validating self test for accel values in mg*/
|
|
rslt |= validate_selftest(&accel_data_diff_mg, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*result = BMA4_SELFTEST_PASS;
|
|
|
|
/* Triggers a soft reset */
|
|
rslt |= bma4_set_command_register(0xB6, dev);
|
|
dev->delay(200);
|
|
}
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API performs the steps needed for Self test operation
|
|
* before reading the Accel Self test data.
|
|
*/
|
|
uint16_t bma4_selftest_config(uint8_t sign, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
|
|
rslt |= set_accel_selftest_enable(BMA4_ENABLE, dev);
|
|
rslt |= set_accel_selftest_sign(sign, dev);
|
|
|
|
/* Set self test amplitude based on variant */
|
|
switch (dev->variant) {
|
|
case BMA42X_VARIANT:
|
|
/* Set self test amplitude to high for BMA42x */
|
|
rslt |= set_accel_selftest_amp(BMA4_ENABLE, dev);
|
|
break;
|
|
|
|
case BMA45X_VARIANT:
|
|
/* Set self test amplitude to low for BMA45x */
|
|
rslt |= set_accel_selftest_amp(BMA4_DISABLE, dev);
|
|
break;
|
|
|
|
default:
|
|
rslt = BMA4_E_INVALID_SENSOR;
|
|
break;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief API sets the interrupt to either interrupt1 or
|
|
* interrupt2 pin in the sensor.
|
|
*/
|
|
uint16_t bma4_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data[3] = {0, 0, 0};
|
|
uint8_t index[2] = {BMA4_INT_MAP_1_ADDR, BMA4_INT_MAP_2_ADDR};
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
|
|
rslt |= bma4_read_regs(BMA4_INT_MAP_1_ADDR, data, 3, dev);
|
|
|
|
if (enable == TRUE) {
|
|
/* Feature interrupt mapping */
|
|
data[int_line] |= (uint8_t)(int_map & (0x00FF));
|
|
/* Hardware interrupt mapping */
|
|
if (int_line == BMA4_INTR2_MAP)
|
|
data[2] |= (uint8_t)((int_map & (0xFF00)) >> 4);
|
|
else
|
|
data[2] |= (uint8_t)((int_map & (0xFF00)) >> 8);
|
|
|
|
rslt |= bma4_write_regs(index[int_line], &data[int_line], 1, dev);
|
|
rslt |= bma4_write_regs(BMA4_INT_MAP_DATA_ADDR, &data[2], 1, dev);
|
|
|
|
} else {
|
|
/* Feature interrupt un-mapping */
|
|
data[int_line] &= (~(uint8_t)(int_map & (0x00FF)));
|
|
/* Hardware interrupt un-mapping */
|
|
if (int_line == BMA4_INTR2_MAP)
|
|
data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 4));
|
|
else
|
|
data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 8));
|
|
|
|
rslt |= bma4_write_regs(index[int_line], &data[int_line], 1, dev);
|
|
rslt |= bma4_write_regs(BMA4_INT_MAP_DATA_ADDR, &data[2], 1, dev);
|
|
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the interrupt mode in the sensor.
|
|
*/
|
|
uint16_t bma4_set_interrupt_mode(uint8_t mode, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
|
|
if (mode == BMA4_NON_LATCH_MODE || mode == BMA4_LATCH_MODE)
|
|
rslt |= bma4_write_regs(BMA4_INTR_LATCH_ADDR, &mode, 1, dev);
|
|
else
|
|
rslt |= BMA4_E_OUT_OF_RANGE;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API gets the interrupt mode which is set in the sensor.
|
|
*/
|
|
uint16_t bma4_get_interrupt_mode(uint8_t *mode, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_INTR_LATCH_ADDR, &data, 1, dev);
|
|
*mode = data;
|
|
}
|
|
|
|
return rslt;
|
|
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the auxiliary Mag(BMM150 or AKM9916) output data
|
|
* rate and offset.
|
|
*/
|
|
uint16_t bma4_set_aux_mag_config(const struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
if ((aux_mag->odr >= BMA4_OUTPUT_DATA_RATE_0_78HZ) &&
|
|
(aux_mag->odr <= BMA4_OUTPUT_DATA_RATE_1600HZ)
|
|
&& ((aux_mag->offset & BMA4_MAG_CONFIG_OFFSET_MSK) == 0x00)) {
|
|
data = (uint8_t)(aux_mag->odr |
|
|
((aux_mag->offset <<
|
|
BMA4_MAG_CONFIG_OFFSET_POS)));
|
|
rslt |= bma4_write_regs(BMA4_AUX_CONFIG_ADDR, &data, 1, dev);
|
|
} else {
|
|
rslt |= BMA4_E_OUT_OF_RANGE;
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the auxiliary Mag(BMM150 or AKM9916) output data
|
|
* rate and offset.
|
|
*/
|
|
uint16_t bma4_get_aux_mag_config(struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_AUX_CONFIG_ADDR, &data, 1, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
aux_mag->odr = (data & 0x0F);
|
|
aux_mag->offset = (data & BMA4_MAG_CONFIG_OFFSET_MSK) >> 4;
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*! @brief This API sets the FIFO configuration in the sensor.
|
|
*/
|
|
uint16_t bma4_set_fifo_config(uint8_t config, uint8_t enable, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data[2] = {0, 0};
|
|
uint8_t fifo_config_0 = config & BMA4_FIFO_CONFIG_0_MASK;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_FIFO_CONFIG_0_ADDR, data, BMA4_FIFO_CONFIG_LENGTH, dev);
|
|
|
|
if (rslt == BMA4_OK) {
|
|
|
|
if (fifo_config_0 > 0) {
|
|
|
|
if (enable == TRUE)
|
|
data[0] = data[0] | fifo_config_0;
|
|
else
|
|
data[0] = data[0] & (~fifo_config_0);
|
|
}
|
|
|
|
if (enable == TRUE)
|
|
data[1] = data[1] | (config & BMA4_FIFO_CONFIG_1_MASK);
|
|
else
|
|
data[1] = data[1] & (~(config & BMA4_FIFO_CONFIG_1_MASK));
|
|
|
|
/* Burst write is not possible in suspend mode hence
|
|
separate write is used with delay of 1 ms*/
|
|
rslt |= bma4_write_regs(BMA4_FIFO_CONFIG_0_ADDR, &data[0], 1, dev);
|
|
dev->delay(BMA4_GEN_READ_WRITE_DELAY);
|
|
rslt |= bma4_write_regs((BMA4_FIFO_CONFIG_0_ADDR + 1), &data[1], 1, dev);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*! @brief This API reads the FIFO configuration from the sensor.
|
|
*/
|
|
uint16_t bma4_get_fifo_config(uint8_t *fifo_config, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data[2] = {0, 0};
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
rslt |= bma4_read_regs(BMA4_FIFO_CONFIG_0_ADDR, data, BMA4_FIFO_CONFIG_LENGTH, dev);
|
|
|
|
if (rslt == BMA4_OK)
|
|
*fifo_config = ((uint8_t)((data[0] & BMA4_FIFO_CONFIG_0_MASK) | (data[1])));
|
|
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*! @brief This function sets the electrical behaviour of interrupt pin1 or
|
|
* pin2 in the sensor.
|
|
*/
|
|
uint16_t bma4_set_int_pin_config(const struct bma4_int_pin_config *int_pin_config, uint8_t int_line,
|
|
struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t interrupt_address_array[2] = {BMA4_INT1_IO_CTRL_ADDR, BMA4_INT2_IO_CTRL_ADDR};
|
|
uint8_t data = 0;
|
|
|
|
/* Check the bma4 structure as NULL */
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
if (int_line <= 1) {
|
|
data = ((uint8_t)((int_pin_config->edge_ctrl & BMA4_INT_EDGE_CTRL_MASK) |
|
|
((int_pin_config->lvl << 1) & BMA4_INT_LEVEL_MASK) |
|
|
((int_pin_config->od << 2) & BMA4_INT_OPEN_DRAIN_MASK) |
|
|
((int_pin_config->output_en << 3) & BMA4_INT_OUTPUT_EN_MASK) |
|
|
((int_pin_config->input_en << 4) & BMA4_INT_INPUT_EN_MASK)));
|
|
|
|
rslt |= bma4_write_regs(interrupt_address_array[int_line], &data, 1, dev);
|
|
} else {
|
|
rslt |= BMA4_E_INT_LINE_INVALID;
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*! @brief This API reads the electrical behavior of interrupt pin1 or pin2
|
|
* from the sensor.
|
|
*/
|
|
uint16_t bma4_get_int_pin_config(struct bma4_int_pin_config *int_pin_config, uint8_t int_line, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t interrupt_address_array[2] = {BMA4_INT1_IO_CTRL_ADDR, BMA4_INT2_IO_CTRL_ADDR};
|
|
uint8_t data = 0;
|
|
|
|
if (dev == NULL) {
|
|
rslt |= BMA4_E_NULL_PTR;
|
|
} else {
|
|
if (int_line <= 1) {
|
|
rslt |= bma4_read_regs(interrupt_address_array[int_line], &data, 1, dev);
|
|
/* Assign interrupt configurations to the
|
|
structure members*/
|
|
if (rslt == BMA4_OK) {
|
|
int_pin_config->edge_ctrl = data & BMA4_INT_EDGE_CTRL_MASK;
|
|
int_pin_config->lvl = ((data & BMA4_INT_LEVEL_MASK) >> BMA4_INT_LEVEL_POS);
|
|
int_pin_config->od = ((data & BMA4_INT_OPEN_DRAIN_MASK) >> BMA4_INT_OPEN_DRAIN_POS);
|
|
int_pin_config->output_en = ((data & BMA4_INT_OUTPUT_EN_MASK)
|
|
>> BMA4_INT_OUTPUT_EN_POS);
|
|
int_pin_config->input_en = ((data & BMA4_INT_INPUT_EN_MASK) >> BMA4_INT_INPUT_EN_POS);
|
|
}
|
|
} else {
|
|
rslt |= BMA4_E_INT_LINE_INVALID;
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the Feature and Hardware interrupt status from the sensor.
|
|
*/
|
|
uint16_t bma4_read_int_status(uint16_t *int_status, struct bma4_dev *dev)
|
|
{
|
|
uint16_t rslt = 0;
|
|
uint8_t data[2] = {0};
|
|
|
|